@@ -3022,7 +3022,7 @@ def _unconvert_from_RGB_255(colors):
30223022 return un_rgb_color
30233023
30243024 @staticmethod
3025- def _map_face2color ( face , colormap , vmin , vmax ):
3025+ def _map_faces2color ( faces , colormap ):
30263026 """
30273027 Normalize facecolor values by vmin/vmax and return rgb-color strings
30283028
@@ -3032,37 +3032,52 @@ def _map_face2color(face, colormap, vmin, vmax):
30323032 distance between vmin and vmax
30333033
30343034 """
3035- if vmin >= vmax :
3036- raise exceptions .PlotlyError ("Incorrect relation between vmin "
3037- "and vmax. The vmin value cannot be "
3038- "bigger than or equal to the value "
3039- "of vmax." )
3040- 3041- if len (colormap ) == 1 :
3035+ colormap = np .atleast_2d (colormap )
3036+ if colormap .shape [0 ] == 1 :
30423037 # color each triangle face with the same color in colormap
3043- face_color = colormap [0 ]
3044- face_color = FigureFactory ._convert_to_RGB_255 (face_color )
3045- face_color = FigureFactory ._label_rgb (face_color )
3038+ face_colors = colormap
30463039 else :
3047- if face == vmax :
3048- # pick last color in colormap
3049- face_color = colormap [- 1 ]
3050- face_color = FigureFactory ._convert_to_RGB_255 (face_color )
3051- face_color = FigureFactory ._label_rgb (face_color )
3052- else :
3053- # find the normalized distance t of a triangle face between
3054- # vmin and vmax where the distance is between 0 and 1
3055- t = (face - vmin ) / float ((vmax - vmin ))
3056- low_color_index = int (t / (1. / (len (colormap ) - 1 )))
3040+ # Convert face values to between 0 and 1
3041+ vmin = faces .min ()
3042+ vmax = faces .max ()
3043+ if vmin >= vmax :
3044+ raise exceptions .PlotlyError ("Incorrect relation between vmin"
3045+ " and vmax. The vmin value cannot"
3046+ " be bigger than or equal to the"
3047+ " value of vmax." )
3048+ # Scale t to between 0 and 1
3049+ t = (faces - vmin ) / float ((vmax - vmin ))
3050+ t_ixs = np .round (t * 255 ).astype (int )
3051+ 3052+ # If a list of colors is given, interpolate between them.
3053+ color_range = FigureFactory ._blend_colors (colormap )
3054+ face_colors = color_range [t_ixs ]
3055+ 3056+ # Convert to 255 scale, and round to nearest integer
3057+ face_colors = np .round (face_colors * 255. , 0 )
3058+ face_colors = FigureFactory ._label_rgb (face_colors )
3059+ return face_colors
30573060
3058- face_color = FigureFactory ._find_intermediate_color (
3059- colormap [low_color_index ],
3060- colormap [low_color_index + 1 ],
3061- t * (len (colormap ) - 1 ) - low_color_index )
3062- face_color = FigureFactory ._convert_to_RGB_255 (face_color )
3063- face_color = FigureFactory ._label_rgb (face_color )
3064- 3065- return face_color
3061+ @staticmethod
3062+ def _blend_colors (colormap , n_colors = 255. ):
3063+ if len (colormap ) == 1 :
3064+ raise ValueError ('Cannot blend a colormap with only one color' )
3065+ # Figure out how many splits we need
3066+ n_split = np .floor (n_colors / (len (colormap ) - 1 )).astype (int )
3067+ n_remain = np .mod (n_colors , len (colormap ))
3068+ 3069+ # Iterate through pairs of colors
3070+ color_range = []
3071+ for ii in range (len (colormap ) - 1 ):
3072+ # For each channel (r, g, b)
3073+ this_interp = []
3074+ for cstt , cstp in zip (colormap [ii ], colormap [ii + 1 ]):
3075+ # If it's not an even split, add req'd amount on first iter
3076+ n_interp = n_split + n_remain if ii == 0 else n_split
3077+ this_interp .append (np .linspace (cstt , cstp , n_interp ))
3078+ color_range .append (np .vstack (this_interp ).T )
3079+ color_range = np .vstack (color_range )
3080+ return color_range
30663081
30673082 @staticmethod
30683083 def _trisurf (x , y , z , simplices , colormap = None , color_func = None ,
@@ -3117,17 +3132,12 @@ def _trisurf(x, y, z, simplices, colormap=None, color_func=None,
31173132 if isinstance (mean_dists [0 ], str ):
31183133 facecolor = mean_dists
31193134 else :
3120- min_mean_dists = np .min (mean_dists )
3121- max_mean_dists = np .max (mean_dists )
3122- 3123- if facecolor is None :
3124- facecolor = []
3125- for index in range (len (mean_dists )):
3126- color = FigureFactory ._map_face2color (mean_dists [index ],
3127- colormap ,
3128- min_mean_dists ,
3129- max_mean_dists )
3130- facecolor .append (color )
3135+ # Map distances to color using the given cmap
3136+ dist_colors = FigureFactory ._map_faces2color (mean_dists , colormap )
3137+ if facecolor is not None :
3138+ facecolor = np .vstack ([facecolor , dist_colors ])
3139+ else :
3140+ facecolor = dist_colors
31313141
31323142 # Make sure we have arrays to speed up plotting
31333143 facecolor = np .asarray (facecolor )
@@ -4338,8 +4348,17 @@ def _convert_to_RGB_255(colors):
43384348 """
43394349 Multiplies each element of a triplet by 255
43404350 """
4341- 4342- return (colors [0 ]* 255.0 , colors [1 ]* 255.0 , colors [2 ]* 255.0 )
4351+ if isinstance (colors , tuple ):
4352+ return (colors [0 ]* 255.0 , colors [1 ]* 255.0 , colors [2 ]* 255.0 )
4353+ elif isinstance (colors , np .ndarray ):
4354+ # Vectorize the multiplication and return a list of tuples
4355+ return [tuple (ii ) for ii in colors * 255.0 ]
4356+ else :
4357+ colors_255 = []
4358+ for color in colors :
4359+ rgb_color = (color [0 ]* 255.0 , color [1 ]* 255.0 , color [2 ]* 255.0 )
4360+ colors_255 .append (rgb_color )
4361+ return colors_255
43434362
43444363 @staticmethod
43454364 def _n_colors (lowcolor , highcolor , n_colors ):
@@ -4372,7 +4391,12 @@ def _label_rgb(colors):
43724391 """
43734392 Takes tuple (a, b, c) and returns an rgb color 'rgb(a, b, c)'
43744393 """
4375- return ('rgb(%s, %s, %s)' % (colors [0 ], colors [1 ], colors [2 ]))
4394+ if isinstance (colors , tuple ):
4395+ return ('rgb(%s, %s, %s)' % (colors [0 ], colors [1 ], colors [2 ]))
4396+ else :
4397+ colors_label = ['rgb(%s, %s, %s)' % (r , g , b )
4398+ for r , g , b in colors ]
4399+ return colors_label
43764400
43774401 @staticmethod
43784402 def _unlabel_rgb (colors ):
0 commit comments