Beispiel #1
0
def my_map_face2color(face, colormap, vmin, vmax):
    """
	Normalize facecolor values by vmin/vmax and return rgb-color strings

	This function takes a tuple color along with a colormap and a minimum
	(vmin) and maximum (vmax) range of possible mean distances for the
	given parametrized surface. It returns an rgb color based on the mean
	distance between vmin and vmax

	"""
    if vmin >= vmax:
        vmax = vmin + 1

    if len(colormap) == 1:
        # color each triangle face with the same color in colormap
        face_color = colormap[0]
        face_color = FigureFactory._convert_to_RGB_255(face_color)
        face_color = FigureFactory._label_rgb(face_color)
    else:
        if face >= vmax:
            # pick last color in colormap
            face_color = colormap[-1]
            face_color = FigureFactory._convert_to_RGB_255(face_color)
            face_color = FigureFactory._label_rgb(face_color)
        else:
            # find the normalized distance t of a triangle face between
            # vmin and vmax where the distance is between 0 and 1
            t = (face - vmin) / float((vmax - vmin))
            low_color_index = int(t / (1. / (len(colormap) - 1)))

            face_color = FigureFactory._find_intermediate_color(
                colormap[low_color_index], colormap[low_color_index + 1],
                t * (len(colormap) - 1) - low_color_index)

            face_color = FigureFactory._convert_to_RGB_255(face_color)
            face_color = FigureFactory._label_rgb(face_color)
    return face_color
Beispiel #2
0
def my_trisurf(x,
               y,
               z,
               simplices,
               show_colorbar,
               edges_color,
               colormap=None,
               color_func=None,
               plot_edges=False,
               x_edge=None,
               y_edge=None,
               z_edge=None,
               facecolor=None,
               data_list=False,
               minmax_values=None):
    """
		Refer to FigureFactory.create_trisurf() for docstring
		"""
    # numpy import check
    if _numpy_imported is False:
        raise ImportError("FigureFactory._trisurf() requires "
                          "numpy imported.")
    import numpy as np
    from plotly.graph_objs import graph_objs
    points3D = np.vstack((x, y, z)).T
    simplices = np.atleast_2d(simplices)

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

    # Define colors for the triangle faces
    if color_func is None:
        # mean values of z-coordinates of triangle vertices
        mean_dists = tri_vertices[:, :, 2].mean(-1)
    elif isinstance(color_func, (list, np.ndarray)):
        # Pre-computed list / array of values to map onto color
        if len(color_func) != len(simplices):
            raise ValueError("If color_func is a list/array, it must "
                             "be the same length as simplices.")

        # convert all colors in color_func to rgb
        for index in range(len(color_func)):
            if isinstance(color_func[index], str):
                if '#' in color_func[index]:
                    foo = FigureFactory._hex_to_rgb(color_func[index])
                    color_func[index] = FigureFactory._label_rgb(foo)

            if isinstance(color_func[index], tuple):
                foo = FigureFactory._convert_to_RGB_255(color_func[index])
                color_func[index] = FigureFactory._label_rgb(foo)

        mean_dists = np.asarray(color_func)
    else:
        # apply user inputted function to calculate
        # custom coloring for triangle vertices
        mean_dists = []
        for triangle in tri_vertices:
            dists = []
            for vertex in triangle:
                dist = color_func(vertex[0], vertex[1], vertex[2])
                dists.append(dist)
            mean_dists.append(np.mean(dists))
        mean_dists = np.asarray(mean_dists)

    # Check if facecolors are already strings and can be skipped
    if isinstance(mean_dists[0], str):
        facecolor = mean_dists
    else:
        if minmax_values == None:
            min_mean_dists = np.min(mean_dists)
            max_mean_dists = np.max(mean_dists)
        else:
            min_mean_dists = minmax_values[0]
            max_mean_dists = minmax_values[1]
        if facecolor is None:
            facecolor = []
        for index in range(len(mean_dists)):
            color = my_map_face2color(mean_dists[index], colormap,
                                      min_mean_dists, max_mean_dists)
            facecolor.append(color)

    # Make sure facecolor is a list so output is consistent across Pythons
    facecolor = list(facecolor)
    ii, jj, kk = simplices.T

    triangles = graph_objs.Mesh3d(x=x,
                                  y=y,
                                  z=z,
                                  facecolor=facecolor,
                                  i=ii,
                                  j=jj,
                                  k=kk,
                                  name='',
                                  hoverinfo='skip')

    mean_dists_are_numbers = not isinstance(mean_dists[0], str)

    if mean_dists_are_numbers and show_colorbar is True:
        # make a colorscale from the colors
        colorscale = FigureFactory._make_colorscale(colormap)
        colorscale = FigureFactory._convert_colorscale_to_rgb(colorscale)

        colorbar = graph_objs.Scatter3d(
            x=[x[0]],  # !!! solve a bug in the orginal file !
            y=[y[0]],
            z=[z[0]],
            mode='markers',
            marker=dict(
                size=0.1,
                color=[min_mean_dists, max_mean_dists],
                colorscale=colorscale,
                showscale=True,
                colorbar=dict(len=0.5),
            ),
            hoverinfo='None',
            showlegend=False)

    # the triangle sides are not plotted
    if plot_edges is False:
        if mean_dists_are_numbers and show_colorbar is True:
            return graph_objs.Data([triangles, colorbar])
        else:
            return graph_objs.Data([triangles])

    # define the lists x_edge, y_edge and z_edge, of x, y, resp z
    # coordinates of edge end points for each triangle
    # None separates data corresponding to two consecutive triangles
    is_none = [ii is None for ii in [x_edge, y_edge, z_edge]]
    if any(is_none):
        if not all(is_none):
            raise ValueError("If any (x_edge, y_edge, z_edge) is None, "
                             "all must be None")
        else:
            x_edge = []
            y_edge = []
            z_edge = []

    # Pull indices we care about, then add a None column to separate tris
    ixs_triangles = [0, 1, 2, 0]
    pull_edges = tri_vertices[:, ixs_triangles, :]
    x_edge_pull = np.hstack(
        [pull_edges[:, :, 0],
         np.tile(None, [pull_edges.shape[0], 1])])
    y_edge_pull = np.hstack(
        [pull_edges[:, :, 1],
         np.tile(None, [pull_edges.shape[0], 1])])
    z_edge_pull = np.hstack(
        [pull_edges[:, :, 2],
         np.tile(None, [pull_edges.shape[0], 1])])

    # Now unravel the edges into a 1-d vector for plotting
    x_edge = np.hstack([x_edge, x_edge_pull.reshape([1, -1])[0]])
    y_edge = np.hstack([y_edge, y_edge_pull.reshape([1, -1])[0]])
    z_edge = np.hstack([z_edge, z_edge_pull.reshape([1, -1])[0]])

    if not (len(x_edge) == len(y_edge) == len(z_edge)):
        raise exceptions.PlotlyError("The lengths of x_edge, y_edge and "
                                     "z_edge are not the same.")

    # define the lines for plotting
    lines = graph_objs.Scatter3d(x=x_edge,
                                 y=y_edge,
                                 z=z_edge,
                                 mode='lines',
                                 line=graph_objs.Line(color=edges_color,
                                                      width=1.5),
                                 showlegend=False)
    if data_list:
        if mean_dists_are_numbers and show_colorbar is True:
            return [triangles, lines, colorbar]
        else:
            return [triangles, lines]
    else:
        if mean_dists_are_numbers and show_colorbar is True:
            return graph_objs.Data([triangles, lines, colorbar])
        else:
            return graph_objs.Data([triangles, lines])