Skip to content

Commit bed542d

Browse files
committed
making simplices and facecolor arrays for faster plotting
1 parent 99da200 commit bed542d

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

plotly/tests/test_optional/test_figure_factory.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,26 @@ def test_trisurf_all_args(self):
753753
self.assert_dict_equal(test_trisurf_plot['data'][1],
754754
exp_trisurf_plot['data'][1])
755755

756+
# Test passing custom colors
757+
colors_raw = np.random.randn(simplices.shape[0])
758+
colors_str = ['rgb(%s, %s, %s)' % (i, j, k)
759+
for i, j, k in np.random.randn(simplices.shape[0], 3)]
760+
761+
# Color == strings should be kept the same
762+
test_colors_plot = tls.FigureFactory.create_trisurf(
763+
x, y, z, simplices, color_func=colors_str)
764+
self.assertListEqual(list(test_colors_plot['data'][0]['facecolor']),
765+
list(colors_str))
766+
# Colors must match length of simplices
767+
colors_bad = colors_str[:-1]
768+
self.assertRaises(ValueError, tls.FigureFactory.create_trisurf, x, y,
769+
z, simplices, color_func=colors_bad)
770+
# Check converting custom colors to strings
771+
test_colors_plot = tls.FigureFactory.create_trisurf(
772+
x, y, z, simplices, color_func=colors_raw)
773+
self.assertTrue(isinstance(test_colors_plot['data'][0]['facecolor'][0],
774+
str))
775+
756776

757777
class TestScatterPlotMatrix(NumpyTestUtilsMixin, TestCase):
758778

plotly/tools.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,11 +1490,11 @@ def _unconvert_from_RGB_255(colors):
14901490
return un_rgb_colors
14911491

14921492
@staticmethod
1493-
def _map_z2color(zvals, colormap, vmin, vmax):
1493+
def _map_array2color(array, colormap, vmin, vmax):
14941494
"""
1495-
Returns the color corresponding zval's place between vmin and vmax
1495+
Normalize values in array by vmin/vmax and return plotly color strings.
14961496
1497-
This function takes a z value (zval) along with a colormap and a
1497+
This function takes an array of values along with a colormap and a
14981498
minimum (vmin) and maximum (vmax) range of possible z values for the
14991499
given parametrized surface. It returns an rgb color based on the
15001500
relative position of zval between vmin and vmax
@@ -1507,7 +1507,7 @@ def _map_z2color(zvals, colormap, vmin, vmax):
15071507
"of vmax.")
15081508
# find distance t of zval from vmin to vmax where the distance
15091509
# is normalized to be between 0 and 1
1510-
t = (zvals - vmin) / float((vmax - vmin))
1510+
t = (array - vmin) / float((vmax - vmin))
15111511
t_colors = FigureFactory._find_intermediate_color(colormap[0],
15121512
colormap[1],
15131513
t)
@@ -1529,41 +1529,46 @@ def _trisurf(x, y, z, simplices, colormap=None, color_func=None,
15291529
import numpy as np
15301530
from plotly.graph_objs import graph_objs
15311531
points3D = np.vstack((x, y, z)).T
1532+
simplices = np.atleast_2d(simplices)
15321533

15331534
# vertices of the surface triangles
15341535
tri_vertices = points3D[simplices]
15351536

1537+
# Define colors for the triangle faces
15361538
if color_func is None:
15371539
# mean values of z-coordinates of triangle vertices
15381540
mean_dists = tri_vertices[:, :, 2].mean(-1)
15391541
elif isinstance(color_func, (list, np.ndarray)):
1542+
# Pre-computed list / array of values to map onto color
15401543
if len(color_func) != len(simplices):
15411544
raise ValueError('If color_func is a list/array, must'
15421545
' be the same length as simplices')
1543-
mean_dists = color_func
1546+
mean_dists = np.asarray(color_func)
15441547
else:
15451548
# apply user inputted function to calculate
15461549
# custom coloring for triangle vertices
15471550
mean_dists = []
1548-
15491551
for triangle in tri_vertices:
15501552
dists = []
15511553
for vertex in triangle:
15521554
dist = color_func(vertex[0], vertex[1], vertex[2])
15531555
dists.append(dist)
1554-
15551556
mean_dists.append(np.mean(dists))
1557+
mean_dists = np.asarray(mean_dists)
1558+
1559+
# Check if facecolors are already strings and can be skipped
15561560
if isinstance(mean_dists[0], str):
15571561
facecolor = mean_dists
15581562
else:
15591563
min_mean_dists = np.min(mean_dists)
15601564
max_mean_dists = np.max(mean_dists)
1561-
facecolor = FigureFactory._map_z2color(mean_dists,
1562-
colormap,
1563-
min_mean_dists,
1564-
max_mean_dists)
1565-
1566-
ii, jj, kk = zip(*simplices)
1565+
facecolor = FigureFactory._map_array2color(mean_dists,
1566+
colormap,
1567+
min_mean_dists,
1568+
max_mean_dists)
1569+
# Make sure we have arrays to speed up plotting
1570+
facecolor = np.asarray(facecolor)
1571+
ii, jj, kk = simplices.T
15671572
triangles = graph_objs.Mesh3d(x=x, y=y, z=z, facecolor=facecolor,
15681573
i=ii, j=jj, k=kk, name='')
15691574

0 commit comments

Comments
 (0)