@@ -3227,47 +3227,60 @@ def _unconvert_from_RGB_255(colors):
32273227 return un_rgb_color
32283228
32293229 @staticmethod
3230- def _map_face2color ( face , colormap , vmin , vmax ):
3230+ def _map_faces2color ( faces , colormap ):
32313231 """
3232- Normalize facecolor values by vmin/vmax and return rgb-color strings
3233-
3234- This function takes a tuple color along with a colormap and a minimum
3235- (vmin) and maximum (vmax) range of possible mean distances for the
3236- given parametrized surface. It returns an rgb color based on the mean
3237- distance between vmin and vmax
3232+ Normalize facecolors by their min/max and return rgb-color strings.
32383233
3234+ This function takes a tuple color along with a colormap.
3235+ It returns an rgb color based on the mean distance between the
3236+ minimum and maximum value of faces.
32393237 """
3240- if vmin >= vmax :
3241- raise exceptions .PlotlyError ("Incorrect relation between vmin "
3242- "and vmax. The vmin value cannot be "
3243- "bigger than or equal to the value "
3244- "of vmax." )
3245-
3246- if len (colormap ) == 1 :
3238+ colormap = np .atleast_2d (colormap )
3239+ if colormap .shape [0 ] == 1 :
32473240 # color each triangle face with the same color in colormap
3248- face_color = colormap [0 ]
3249- face_color = FigureFactory ._convert_to_RGB_255 (face_color )
3250- face_color = FigureFactory ._label_rgb (face_color )
3241+ face_colors = colormap
32513242 else :
3252- if face == vmax :
3253- # pick last color in colormap
3254- face_color = colormap [- 1 ]
3255- face_color = FigureFactory ._convert_to_RGB_255 (face_color )
3256- face_color = FigureFactory ._label_rgb (face_color )
3257- else :
3258- # find the normalized distance t of a triangle face between
3259- # vmin and vmax where the distance is between 0 and 1
3260- t = (face - vmin ) / float ((vmax - vmin ))
3261- low_color_index = int (t / (1. / (len (colormap ) - 1 )))
3262-
3263- face_color = FigureFactory ._find_intermediate_color (
3264- colormap [low_color_index ],
3265- colormap [low_color_index + 1 ],
3266- t * (len (colormap ) - 1 ) - low_color_index )
3267- face_color = FigureFactory ._convert_to_RGB_255 (face_color )
3268- face_color = FigureFactory ._label_rgb (face_color )
3243+ # Convert face values to between 0 and 1
3244+ vmin = faces .min ()
3245+ vmax = faces .max ()
3246+ if vmin >= vmax :
3247+ raise exceptions .PlotlyError ("Incorrect relation between vmin"
3248+ " and vmax. The vmin value cannot"
3249+ " be bigger than or equal to the"
3250+ " value of vmax." )
3251+ # Scale t to between 0 and 1
3252+ t = (faces - vmin ) / float ((vmax - vmin ))
3253+ t_ixs = np .round (t * 255 ).astype (int )
3254+
3255+ # If a list of colors is given, interpolate between them.
3256+ color_range = FigureFactory ._blend_colors (colormap )
3257+ face_colors = color_range [t_ixs ]
3258+
3259+ # Convert to 255 scale, and round to nearest integer
3260+ face_colors = np .round (face_colors * 255. , 0 )
3261+ face_colors = FigureFactory ._label_rgb (face_colors )
3262+ return face_colors
32693263
3270- return face_color
3264+ @staticmethod
3265+ def _blend_colors (colormap , n_colors = 255. ):
3266+ if len (colormap ) == 1 :
3267+ raise ValueError ('Cannot blend a colormap with only one color' )
3268+ # Figure out how many splits we need
3269+ n_split = np .floor (n_colors / (len (colormap ) - 1 )).astype (int )
3270+ n_remain = np .mod (n_colors , len (colormap ))
3271+
3272+ # Iterate through pairs of colors
3273+ color_range = []
3274+ for ii in range (len (colormap ) - 1 ):
3275+ # For each channel (r, g, b)
3276+ this_interp = []
3277+ for cstt , cstp in zip (colormap [ii ], colormap [ii + 1 ]):
3278+ # If it's not an even split, add req'd amount on first iter
3279+ n_interp = n_split + n_remain if ii == 0 else n_split
3280+ this_interp .append (np .linspace (cstt , cstp , n_interp ))
3281+ color_range .append (np .vstack (this_interp ).T )
3282+ color_range = np .vstack (color_range )
3283+ return color_range
32713284
32723285 @staticmethod
32733286 def _trisurf (x , y , z , simplices , show_colorbar , colormap = None ,
@@ -3322,17 +3335,12 @@ def _trisurf(x, y, z, simplices, show_colorbar, colormap=None,
33223335 if isinstance (mean_dists [0 ], str ):
33233336 facecolor = mean_dists
33243337 else :
3325- min_mean_dists = np .min (mean_dists )
3326- max_mean_dists = np .max (mean_dists )
3327-
3328- if facecolor is None :
3329- facecolor = []
3330- for index in range (len (mean_dists )):
3331- color = FigureFactory ._map_face2color (mean_dists [index ],
3332- colormap ,
3333- min_mean_dists ,
3334- max_mean_dists )
3335- facecolor .append (color )
3338+ # Map distances to color using the given cmap
3339+ dist_colors = FigureFactory ._map_faces2color (mean_dists , colormap )
3340+ if facecolor is not None :
3341+ facecolor = np .vstack ([facecolor , dist_colors ])
3342+ else :
3343+ facecolor = dist_colors
33363344
33373345 # Make sure we have arrays to speed up plotting
33383346 facecolor = np .asarray (facecolor )
@@ -4564,8 +4572,17 @@ def _convert_to_RGB_255(colors):
45644572 """
45654573 Multiplies each element of a triplet by 255
45664574 """
4567-
4568- return (colors [0 ]* 255.0 , colors [1 ]* 255.0 , colors [2 ]* 255.0 )
4575+ if isinstance (colors , tuple ):
4576+ return (colors [0 ]* 255.0 , colors [1 ]* 255.0 , colors [2 ]* 255.0 )
4577+ elif isinstance (colors , np .ndarray ):
4578+ # Vectorize the multiplication and return a list of tuples
4579+ return [tuple (ii ) for ii in colors * 255.0 ]
4580+ else :
4581+ colors_255 = []
4582+ for color in colors :
4583+ rgb_color = (color [0 ]* 255.0 , color [1 ]* 255.0 , color [2 ]* 255.0 )
4584+ colors_255 .append (rgb_color )
4585+ return colors_255
45694586
45704587 @staticmethod
45714588 def _n_colors (lowcolor , highcolor , n_colors ):
@@ -4598,7 +4615,12 @@ def _label_rgb(colors):
45984615 """
45994616 Takes tuple (a, b, c) and returns an rgb color 'rgb(a, b, c)'
46004617 """
4601- return ('rgb(%s, %s, %s)' % (colors [0 ], colors [1 ], colors [2 ]))
4618+ if isinstance (colors , tuple ):
4619+ return ('rgb(%s, %s, %s)' % (colors [0 ], colors [1 ], colors [2 ]))
4620+ else :
4621+ colors_label = ['rgb(%s, %s, %s)' % (r , g , b )
4622+ for r , g , b in colors ]
4623+ return colors_label
46024624
46034625 @staticmethod
46044626 def _unlabel_rgb (colors ):
0 commit comments