@@ -3022,47 +3022,60 @@ 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
- Normalize facecolor values by vmin/vmax and return rgb-color strings
3028
-
3029
- This function takes a tuple color along with a colormap and a minimum
3030
- (vmin) and maximum (vmax) range of possible mean distances for the
3031
- given parametrized surface. It returns an rgb color based on the mean
3032
- distance between vmin and vmax
3027
+ Normalize facecolors by their min/max and return rgb-color strings.
3033
3028
3029
+ This function takes a tuple color along with a colormap.
3030
+ It returns an rgb color based on the mean distance between the
3031
+ minimum and maximum value of faces.
3034
3032
"""
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 :
3033
+ colormap = np .atleast_2d (colormap )
3034
+ if colormap .shape [0 ] == 1 :
3042
3035
# 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 )
3036
+ face_colors = colormap
3046
3037
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 )))
3057
-
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 )
3038
+ # Convert face values to between 0 and 1
3039
+ vmin = faces .min ()
3040
+ vmax = faces .max ()
3041
+ if vmin >= vmax :
3042
+ raise exceptions .PlotlyError ("Incorrect relation between vmin"
3043
+ " and vmax. The vmin value cannot"
3044
+ " be bigger than or equal to the"
3045
+ " value of vmax." )
3046
+ # Scale t to between 0 and 1
3047
+ t = (faces - vmin ) / float ((vmax - vmin ))
3048
+ t_ixs = np .round (t * 255 ).astype (int )
3049
+
3050
+ # If a list of colors is given, interpolate between them.
3051
+ color_range = FigureFactory ._blend_colors (colormap )
3052
+ face_colors = color_range [t_ixs ]
3053
+
3054
+ # Convert to 255 scale, and round to nearest integer
3055
+ face_colors = np .round (face_colors * 255. , 0 )
3056
+ face_colors = FigureFactory ._label_rgb (face_colors )
3057
+ return face_colors
3064
3058
3065
- return face_color
3059
+ @staticmethod
3060
+ def _blend_colors (colormap , n_colors = 255. ):
3061
+ if len (colormap ) == 1 :
3062
+ raise ValueError ('Cannot blend a colormap with only one color' )
3063
+ # Figure out how many splits we need
3064
+ n_split = np .floor (n_colors / (len (colormap ) - 1 )).astype (int )
3065
+ n_remain = np .mod (n_colors , len (colormap ))
3066
+
3067
+ # Iterate through pairs of colors
3068
+ color_range = []
3069
+ for ii in range (len (colormap ) - 1 ):
3070
+ # For each channel (r, g, b)
3071
+ this_interp = []
3072
+ for cstt , cstp in zip (colormap [ii ], colormap [ii + 1 ]):
3073
+ # If it's not an even split, add req'd amount on first iter
3074
+ n_interp = n_split + n_remain if ii == 0 else n_split
3075
+ this_interp .append (np .linspace (cstt , cstp , n_interp ))
3076
+ color_range .append (np .vstack (this_interp ).T )
3077
+ color_range = np .vstack (color_range )
3078
+ return color_range
3066
3079
3067
3080
@staticmethod
3068
3081
def _trisurf (x , y , z , simplices , colormap = None , color_func = None ,
@@ -3117,17 +3130,12 @@ def _trisurf(x, y, z, simplices, colormap=None, color_func=None,
3117
3130
if isinstance (mean_dists [0 ], str ):
3118
3131
facecolor = mean_dists
3119
3132
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 )
3133
+ # Map distances to color using the given cmap
3134
+ dist_colors = FigureFactory ._map_faces2color (mean_dists , colormap )
3135
+ if facecolor is not None :
3136
+ facecolor = np .vstack ([facecolor , dist_colors ])
3137
+ else :
3138
+ facecolor = dist_colors
3131
3139
3132
3140
# Make sure we have arrays to speed up plotting
3133
3141
facecolor = np .asarray (facecolor )
@@ -4338,8 +4346,17 @@ def _convert_to_RGB_255(colors):
4338
4346
"""
4339
4347
Multiplies each element of a triplet by 255
4340
4348
"""
4341
-
4342
- return (colors [0 ]* 255.0 , colors [1 ]* 255.0 , colors [2 ]* 255.0 )
4349
+ if isinstance (colors , tuple ):
4350
+ return (colors [0 ]* 255.0 , colors [1 ]* 255.0 , colors [2 ]* 255.0 )
4351
+ elif isinstance (colors , np .ndarray ):
4352
+ # Vectorize the multiplication and return a list of tuples
4353
+ return [tuple (ii ) for ii in colors * 255.0 ]
4354
+ else :
4355
+ colors_255 = []
4356
+ for color in colors :
4357
+ rgb_color = (color [0 ]* 255.0 , color [1 ]* 255.0 , color [2 ]* 255.0 )
4358
+ colors_255 .append (rgb_color )
4359
+ return colors_255
4343
4360
4344
4361
@staticmethod
4345
4362
def _n_colors (lowcolor , highcolor , n_colors ):
@@ -4372,7 +4389,12 @@ def _label_rgb(colors):
4372
4389
"""
4373
4390
Takes tuple (a, b, c) and returns an rgb color 'rgb(a, b, c)'
4374
4391
"""
4375
- return ('rgb(%s, %s, %s)' % (colors [0 ], colors [1 ], colors [2 ]))
4392
+ if isinstance (colors , tuple ):
4393
+ return ('rgb(%s, %s, %s)' % (colors [0 ], colors [1 ], colors [2 ]))
4394
+ else :
4395
+ colors_label = ['rgb(%s, %s, %s)' % (r , g , b )
4396
+ for r , g , b in colors ]
4397
+ return colors_label
4376
4398
4377
4399
@staticmethod
4378
4400
def _unlabel_rgb (colors ):
0 commit comments