@@ -3022,7 +3022,7 @@ def _unconvert_from_RGB_255(colors):
3022
3022
return un_rgb_color
3023
3023
3024
3024
@staticmethod
3025
- def _map_face2color ( face , colormap , vmin , vmax ):
3025
+ def _map_faces2color ( faces , colormap ):
3026
3026
"""
3027
3027
Normalize facecolor values by vmin/vmax and return rgb-color strings
3028
3028
@@ -3032,37 +3032,52 @@ def _map_face2color(face, colormap, vmin, vmax):
3032
3032
distance between vmin and vmax
3033
3033
3034
3034
"""
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 :
3042
3037
# 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
3046
3039
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
3057
3060
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
3066
3081
3067
3082
@staticmethod
3068
3083
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,
3117
3132
if isinstance (mean_dists [0 ], str ):
3118
3133
facecolor = mean_dists
3119
3134
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
3131
3141
3132
3142
# Make sure we have arrays to speed up plotting
3133
3143
facecolor = np .asarray (facecolor )
@@ -4338,8 +4348,17 @@ def _convert_to_RGB_255(colors):
4338
4348
"""
4339
4349
Multiplies each element of a triplet by 255
4340
4350
"""
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
4343
4362
4344
4363
@staticmethod
4345
4364
def _n_colors (lowcolor , highcolor , n_colors ):
@@ -4372,7 +4391,12 @@ def _label_rgb(colors):
4372
4391
"""
4373
4392
Takes tuple (a, b, c) and returns an rgb color 'rgb(a, b, c)'
4374
4393
"""
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
4376
4400
4377
4401
@staticmethod
4378
4402
def _unlabel_rgb (colors ):
0 commit comments