Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c66cd19

Browse files
authored
Merge pull request plotly#499 from choldgraf/optimize_trisurf_colors
Trisurf and color optimizations
2 parents a0ca3d0 + fbe8d2a commit c66cd19

File tree

1 file changed

+71
-49
lines changed

1 file changed

+71
-49
lines changed

plotly/tools.py

Lines changed: 71 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)