Skip to content

Commit 9e721a3

Browse files
committed
Merge pull request #493 from plotly/trisurf_plus_2_colormap
Allow more than 2 colormaps again
2 parents ef9f4ba + dda0a9a commit 9e721a3

File tree

2 files changed

+63
-33
lines changed

2 files changed

+63
-33
lines changed

plotly/tests/test_optional/test_figure_factory.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,8 @@ def test_trisurf_all_args(self):
929929
z, simplices, color_func=colors_bad)
930930
# Check converting custom colors to strings
931931
test_colors_plot = tls.FigureFactory.create_trisurf(
932-
x, y, z, simplices, color_func=colors_raw)
932+
x, y, z, simplices, color_func=colors_raw
933+
)
933934
self.assertTrue(isinstance(test_colors_plot['data'][0]['facecolor'][0],
934935
str))
935936

plotly/tools.py

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,9 +1468,9 @@ def _find_intermediate_color(lowcolor, highcolor, intermed):
14681468
diff_1 = float(highcolor[1] - lowcolor[1])
14691469
diff_2 = float(highcolor[2] - lowcolor[2])
14701470

1471-
inter_colors = np.array([lowcolor[0] + intermed * diff_0,
1472-
lowcolor[1] + intermed * diff_1,
1473-
lowcolor[2] + intermed * diff_2])
1471+
inter_colors = (lowcolor[0] + intermed * diff_0,
1472+
lowcolor[1] + intermed * diff_1,
1473+
lowcolor[2] + intermed * diff_2)
14741474
return inter_colors
14751475

14761476
@staticmethod
@@ -1503,35 +1503,52 @@ def _unconvert_from_RGB_255(colors):
15031503
return un_rgb_colors
15041504

15051505
@staticmethod
1506-
def _map_array2color(array, colormap, vmin, vmax):
1506+
def _map_face2color(face, colormap, vmin, vmax):
15071507
"""
1508-
Normalize values in array by vmin/vmax and return plotly color strings.
1508+
Normalize facecolor values by vmin/vmax and return rgb-color strings
15091509
1510-
This function takes an array of values along with a colormap and a
1511-
minimum (vmin) and maximum (vmax) range of possible z values for the
1512-
given parametrized surface. It returns an rgb color based on the
1513-
relative position of zval between vmin and vmax
1510+
This function takes a tuple color along with a colormap and a minimum
1511+
(vmin) and maximum (vmax) range of possible mean distances for the
1512+
given parametrized surface. It returns an rgb color based on the mean
1513+
distance between vmin and vmax
15141514
15151515
"""
15161516
if vmin >= vmax:
15171517
raise exceptions.PlotlyError("Incorrect relation between vmin "
15181518
"and vmax. The vmin value cannot be "
15191519
"bigger than or equal to the value "
15201520
"of vmax.")
1521-
# find distance t of zval from vmin to vmax where the distance
1522-
# is normalized to be between 0 and 1
1523-
t = (array - vmin) / float((vmax - vmin))
1524-
t_colors = FigureFactory._find_intermediate_color(colormap[0],
1525-
colormap[1],
1526-
t)
1527-
t_colors = t_colors * 255.
1528-
labelled_colors = ['rgb(%s, %s, %s)' % (i, j, k)
1529-
for i, j, k in t_colors.T]
1530-
return labelled_colors
1521+
1522+
if len(colormap) == 1:
1523+
# color each triangle face with the same color in colormap
1524+
face_color = colormap[0]
1525+
face_color = FigureFactory._convert_to_RGB_255(face_color)
1526+
face_color = FigureFactory._label_rgb(face_color)
1527+
else:
1528+
if face == vmax:
1529+
# pick last color in colormap
1530+
face_color = colormap[-1]
1531+
face_color = FigureFactory._convert_to_RGB_255(face_color)
1532+
face_color = FigureFactory._label_rgb(face_color)
1533+
else:
1534+
# find the normalized distance t of a triangle face between
1535+
# vmin and vmax where the distance is between 0 and 1
1536+
t = (face - vmin) / float((vmax - vmin))
1537+
low_color_index = int(t / (1./(len(colormap) - 1)))
1538+
1539+
face_color = FigureFactory._find_intermediate_color(
1540+
colormap[low_color_index],
1541+
colormap[low_color_index + 1],
1542+
t * (len(colormap) - 1) - low_color_index)
1543+
face_color = FigureFactory._convert_to_RGB_255(face_color)
1544+
face_color = FigureFactory._label_rgb(face_color)
1545+
1546+
return face_color
15311547

15321548
@staticmethod
15331549
def _trisurf(x, y, z, simplices, colormap=None, color_func=None,
1534-
plot_edges=False, x_edge=None, y_edge=None, z_edge=None):
1550+
plot_edges=False, x_edge=None, y_edge=None, z_edge=None,
1551+
facecolor=None):
15351552
"""
15361553
Refer to FigureFactory.create_trisurf() for docstring
15371554
"""
@@ -1556,8 +1573,10 @@ def _trisurf(x, y, z, simplices, colormap=None, color_func=None,
15561573
if len(color_func) != len(simplices):
15571574
raise ValueError("If color_func is a list/array, it must "
15581575
"be the same length as simplices.")
1559-
# convert all colors to rgb
1560-
for index in range(len(color_func)):
1576+
1577+
# convert all colors to rgb
1578+
for index in range(len(color_func)):
1579+
if isinstance(color_func[index], str):
15611580
if '#' in color_func[index]:
15621581
foo = FigureFactory._hex_to_rgb(color_func[index])
15631582
color_func[index] = FigureFactory._label_rgb(foo)
@@ -1581,10 +1600,16 @@ def _trisurf(x, y, z, simplices, colormap=None, color_func=None,
15811600
else:
15821601
min_mean_dists = np.min(mean_dists)
15831602
max_mean_dists = np.max(mean_dists)
1584-
facecolor = FigureFactory._map_array2color(mean_dists,
1585-
colormap,
1586-
min_mean_dists,
1587-
max_mean_dists)
1603+
1604+
if facecolor is None:
1605+
facecolor = []
1606+
for index in range(len(mean_dists)):
1607+
color = FigureFactory._map_face2color(mean_dists[index],
1608+
colormap,
1609+
min_mean_dists,
1610+
max_mean_dists)
1611+
facecolor.append(color)
1612+
15881613
# Make sure we have arrays to speed up plotting
15891614
facecolor = np.asarray(facecolor)
15901615
ii, jj, kk = simplices.T
@@ -1653,10 +1678,12 @@ def create_trisurf(x, y, z, simplices, colormap=None, color_func=None,
16531678
:param (array) simplices: an array of shape (ntri, 3) where ntri is
16541679
the number of triangles in the triangularization. Each row of the
16551680
array contains the indicies of the verticies of each triangle
1656-
:param (str|list) colormap: either a plotly scale name, or a list
1657-
containing 2 triplets. These triplets must be of the form (a,b,c)
1658-
or 'rgb(x,y,z)' where a,b,c belong to the interval [0,1] and x,y,z
1659-
belong to [0,255]
1681+
:param (str|tuple|list) colormap: either a plotly scale name, an rgb
1682+
or hex color, a color tuple or a list of colors. An rgb color is
1683+
of the form 'rgb(x, y, z)' where x, y, z belong to the interval
1684+
[0, 255] and a color tuple is a tuple of the form (a, b, c) where
1685+
a, b and c belong to [0, 1]. If colormap is a list, it must
1686+
contain the valid color types aforementioned as its members.
16601687
:param (function|list) color_func: The parameter that determines the
16611688
coloring of the surface. Takes either a function with 3 arguments
16621689
x, y, z or a list/array of color values the same length as
@@ -2931,11 +2958,13 @@ def _label_rgb(colors):
29312958
29322959
"""
29332960
if isinstance(colors, tuple):
2934-
return 'rgb{}'.format(colors)
2961+
return ('rgb(%s, %s, %s)' % (colors[0], colors[1], colors[2]))
29352962
else:
29362963
colors_label = []
29372964
for color in colors:
2938-
color_label = 'rgb{}'.format(color)
2965+
color_label = ('rgb(%s, %s, %s)' % (color[0],
2966+
color[1],
2967+
color[2]))
29392968
colors_label.append(color_label)
29402969

29412970
return colors_label

0 commit comments

Comments
 (0)