Ejemplo n.º 1
0
def edge_mesh(sheet, coords, **edge_specs):
    """
    Creates a ipyvolume Mesh of the edge lines to be displayed
    in Jupyter Notebooks

    Returns
    -------
    mesh: a :class:`ipyvolume.widgets.Mesh` mesh widget

    """
    spec = sheet_spec()["edge"]
    spec.update(**edge_specs)
    if callable(spec["color"]):
        spec["color"] = spec["color"](sheet)

    if isinstance(spec["color"], str):
        color = spec["color"]
    elif hasattr(spec["color"], "__len__"):
        color = _wire_color_from_sequence(spec, sheet)[:, :3]

    u, v, w = coords
    mesh = ipv.Mesh(
        x=sheet.vert_df[u],
        y=sheet.vert_df[v],
        z=sheet.vert_df[w],
        lines=sheet.edge_df[["srce", "trgt"]].astype(dtype=np.uint32),
        color=color,
    )
    return mesh
Ejemplo n.º 2
0
def plot_trisurf(x,
                 y,
                 z,
                 triangles=None,
                 lines=None,
                 color=default_color,
                 u=None,
                 v=None,
                 texture=None):
    """Draws a polygon/triangle mesh defined by a coordinate and triangle indices

    The following example plots a rectangle in the z==2 plane, consisting of 2 triangles:

    >>> plot_trisurf([0, 0, 3., 3.], [0, 4., 0, 4.], 2,
           triangles=[[0, 2, 3], [0, 3, 1]])

    Note that the z value is constant, and thus not a list/array. For guidance, the triangles
    refer to the vertices in this manner::

        ^ ydir
        |
        2 3
        0 1  ---> x dir

    Note that if you want per face/triangle colors, you need to duplicate each vertex.


    :param x: {x}
    :param y: {y}
    :param z: {z}
    :param triangles: numpy array with indices referring to the vertices, defining the triangles, with shape (M, 3)
    :param lines: numpy array with indices referring to the vertices, defining the lines, with shape (K, 2)
    :param color: {color}
    :param u: {u}
    :param v: {v}
    :param texture: {texture}
    :return: :any:`Mesh`
    """
    fig = gcf()
    if triangles is not None:
        triangles = np.array(triangles).astype(dtype=np.uint32)
    if lines is not None:
        lines = np.array(lines).astype(dtype=np.uint32)
    mesh = ipv.Mesh(x=x,
                    y=y,
                    z=z,
                    triangles=triangles,
                    lines=lines,
                    color=color,
                    u=u,
                    v=v,
                    texture=texture)
    _grow_limits(
        np.array(x).reshape(-1),
        np.array(y).reshape(-1),
        np.array(z).reshape(-1))
    fig.meshes = fig.meshes + [mesh]
    return mesh
Ejemplo n.º 3
0
def face_mesh(sheet, coords, **face_draw_specs):
    """
    Creates a ipyvolume Mesh of the face polygons
    """
    Ne, Nf = sheet.Ne, sheet.Nf
    if callable(face_draw_specs["color"]):
        face_draw_specs["color"] = face_draw_specs["color"](sheet)

    if isinstance(face_draw_specs["color"], str):
        color = face_draw_specs["color"]

    elif hasattr(face_draw_specs["color"], "__len__"):
        color = _face_color_from_sequence(face_draw_specs, sheet)[:, :3]

    if "visible" in sheet.face_df.columns:
        edges = sheet.edge_df[sheet.upcast_face(
            sheet.face_df["visible"])].index
        _sheet = get_sub_eptm(sheet, edges)
        if _sheet is not None:
            sheet = _sheet
            if isinstance(color, np.ndarray):
                faces = sheet.face_df["face_o"].values.astype(np.uint32)
                edges = edges.values.astype(np.uint32)
                indexer = np.concatenate([faces, edges + Nf, edges + Ne + Nf])
                color = color.take(indexer, axis=0)

    epsilon = face_draw_specs.get("epsilon", 0)
    up_srce = sheet.edge_df[["s" + c for c in coords]]
    up_trgt = sheet.edge_df[["t" + c for c in coords]]

    Ne, Nf = sheet.Ne, sheet.Nf

    if epsilon > 0:
        up_face = sheet.edge_df[["f" + c for c in coords]].values
        up_srce = (up_srce - up_face) * (1 - epsilon) + up_face
        up_trgt = (up_trgt - up_face) * (1 - epsilon) + up_face

    mesh_ = np.concatenate(
        [sheet.face_df[coords].values, up_srce.values, up_trgt.values])

    triangles = np.vstack(
        [sheet.edge_df["face"],
         np.arange(Ne) + Nf,
         np.arange(Ne) + Ne + Nf]).T.astype(dtype=np.uint32)

    mesh = ipv.Mesh(x=mesh_[:, 0],
                    y=mesh_[:, 1],
                    z=mesh_[:, 2],
                    triangles=triangles,
                    color=color)
    return mesh
Ejemplo n.º 4
0
    def _default_plotter(self, **kwargs):
        """
        Basic plot function to be used if no custom function is specified.

        This is called by plot, you shouldn't call it directly.
        """

        self.lengths = np.array([length(x) for x in self.lines2use_])
        if not ("grayscale" in kwargs and kwargs["grayscale"]):
            self.colors = np.array([color(x) for x in self.lines2use_])
        else:
            self.colors = np.zeros((len(self.lines2use_), 3), dtype=np.float16)
            self.colors[:] = [0.5, 0.5, 0.5]
        self.state = {"threshold": 0, "indices": []}

        width = 600
        height = 600
        perc = 80
        if "width" in kwargs:
            width = kwargs["width"]
        if "height" in kwargs:
            height = kwargs["height"]
        if "percentile" in kwargs:
            perc = kwargs["percentile"]

        ipv.clear()
        fig = ipv.figure(width=width, height=height)
        self.state["fig"] = fig

        with fig.hold_sync():
            x, y, z, indices, colors, self.line_pointers = self._create_mesh()
            limits = np.array(
                [
                    min([x.min(), y.min(), z.min()]),
                    max([x.max(), y.max(), z.max()]),
                ]
            )
            mesh = ipv.Mesh(x=x, y=y, z=z, lines=indices, color=colors)
            fig.meshes = [mesh]
            if "style" not in kwargs:
                fig.style = {
                    "axes": {
                        "color": "black",
                        "label": {"color": "black"},
                        "ticklabel": {"color": "black"},
                        "visible": False,
                    },
                    "background-color": "white",
                    "box": {"visible": False},
                }
            else:
                fig.style = kwargs["style"]
            ipv.pylab._grow_limits(limits, limits, limits)
            fig.camera_fov = 1
        ipv.show()

        interact(
            self._plot_lines,
            state=fixed(self.state),
            threshold=widgets.FloatSlider(
                value=np.percentile(self.lengths, perc),
                min=self.lengths.min() - 1,
                max=self.lengths.max() - 1,
                continuous_update=False,
            ),
        )
Ejemplo n.º 5
0
def plot_mesh(x, y, z, color=default_color, wireframe=True, surface=True, wrapx=False, wrapy=False, u=None, v=None,
              texture=None):
    """Draws a 2d wireframe+surface in 3d: generalization of :any:`plot_wireframe` and :any:`plot_surface`

    :param x: {x2d}
    :param y: {y2d}
    :param z: {z2d}
    :param color: {color2d}
    :param bool wireframe: draw lines between the vertices
    :param bool surface: draw faces/triangles between the vertices
    :param bool wrapx: when True, the x direction is assumed to wrap, and polygons are drawn between the begin and end points
    :param boool wrapy: idem for y
    :param u: {u}
    :param v: {v}
    :param texture: {texture}
    :return: :any:`Mesh`
    """
    fig = gcf()

    # assert len(x.shape) == 2
    # assert len(y.shape) == 2
    # assert len(z.shape) == 2
    # if isinstance(color, np.ndarray):
    # 	assert len(color.shape) == 3
    # 	assert color.shape[:2] == x.shape
    # 	color = color.reshape(-1)

    def dim(x):
        d = 0
        el = x
        while True:
            try:
                el = el[0]
                d += 1
            except:
                break
        return d

    if dim(x) == 2:
        nx, ny = shape = x.shape
    else:
        nx, ny = shape = x[0].shape

    # assert len(x.shape) == 2, "Array x must be 2 dimensional."
    # assert len(y.shape) == 2, "Array y must be 2 dimensional."
    # assert len(z.shape) == 2, "Array z must be 2 dimensional."
    # assert x.shape == y.shape, "Arrays x and y must have same shape."
    # assert y.shape == z.shape, "Arrays y and z must have same shape."
    # convert x, y, z from shape (nx, ny) to (nx * ny) or
    # (frame, nx, ny) to (frame, nx*ny)
    def reshape(ar):
        if dim(ar) == 3:
            return [k.reshape(-1) for k in ar]
        else:
            return ar.reshape(-1)
    x = reshape(x)
    y = reshape(y)
    z = reshape(z)
    # similar for texture coordinates
    if u is not None:
        u = reshape(u)
    if v is not None:
        v = reshape(v)

    # convert color from shape (nx, ny, {3,4}) to (nx * ny, {3, 4}) or
    # (frame, nx, ny, {3,4}) to (frame, nx*ny, {3,4})
    def reshape_color(ar):
        if dim(ar) == 4:
            return [k.reshape(-1, k.shape[-1]) for k in ar]
        else:
            return ar.reshape(-1, ar.shape[-1])

    if isinstance(color, np.ndarray):
        color = reshape_color(color)

    _grow_limits(np.array(x).reshape(-1), np.array(y).reshape(-1), np.array(z).reshape(-1))
    triangles, lines = _make_triangles_lines((nx,ny) ,wrapx,wrapy)
    mesh = ipv.Mesh(x=x, y=y, z=z, triangles=triangles if surface else None, color=color,
                       lines=lines if wireframe else None,
                       u=u, v=v, texture=texture)
    fig.meshes = fig.meshes + [mesh]
    return mesh
Ejemplo n.º 6
0
def plot_mesh(x,
              y,
              z,
              color=default_color,
              wireframe=True,
              surface=True,
              wrapx=False,
              wrapy=False,
              u=None,
              v=None,
              texture=None):
    fig = gcf()

    # assert len(x.shape) == 2
    # assert len(y.shape) == 2
    # assert len(z.shape) == 2
    # if isinstance(color, np.ndarray):
    # 	assert len(color.shape) == 3
    # 	assert color.shape[:2] == x.shape
    # 	color = color.reshape(-1)

    def dim(x):
        d = 0
        el = x
        while True:
            try:
                el = el[0]
                d += 1
            except:
                break
        return d

    if dim(x) == 2:
        nx, ny = shape = x.shape
    else:
        nx, ny = shape = x[0].shape

    def reshape(ar):
        if dim(ar) == 3:
            return [k.reshape(-1) for k in ar]
        else:
            return ar.reshape(-1)

    def reshape_color(ar):
        if dim(ar) == 4:
            return [k.reshape(-1, 3) for k in ar]
        else:
            return ar.reshape(-1, 3)

    if isinstance(color, np.ndarray):
        # if dim(color) == 4:
        #	color = color.reshape((color.shape[0], -1, color.shape[-1]))
        color = reshape_color(color)
        # print(color.shape)

    x = reshape(x)
    y = reshape(y)
    z = reshape(z)
    if u is not None:
        u = reshape(u)
    if v is not None:
        v = reshape(v)
    _grow_limits(
        np.array(x).reshape(-1),
        np.array(y).reshape(-1),
        np.array(z).reshape(-1))
    mx = nx if wrapx else nx - 1
    my = ny if wrapy else ny - 1
    triangles = np.zeros(((mx) * (my) * 2, 3), dtype=np.uint32)
    lines = np.zeros(((mx) * (my) * 4, 2), dtype=np.uint32)

    def index_from2d(i, j):
        xi = (i % nx)
        yi = (j % ny)
        return nx * xi + yi
        """
        ^ ydir
        |
        2 3
        0 1  ---> x dir
        """

    for i in range(mx):
        for j in range(my):
            p0 = index_from2d(i, j)
            p1 = index_from2d(i + 1, j)
            p2 = index_from2d(i, j + 1)
            p3 = index_from2d(i + 1, j + 1)
            triangle_index = (i * mx) + j
            triangles[triangle_index * 2 + 0, :] = [p0, p1, p3]
            triangles[triangle_index * 2 + 1, :] = [p0, p3, p2]
            lines[triangle_index * 4 + 0, :] = [p0, p1]
            lines[triangle_index * 4 + 1, :] = [p0, p2]
            lines[triangle_index * 4 + 2, :] = [p2, p3]
            lines[triangle_index * 4 + 3, :] = [p1, p3]
    # print(i, j, p0, p1, p2, p3)
    mesh = ipv.Mesh(x=x,
                    y=y,
                    z=z,
                    triangles=triangles if surface else None,
                    color=color,
                    lines=lines if wireframe else None,
                    u=u,
                    v=v,
                    texture=texture)
    fig.meshes = fig.meshes + [mesh]
    return mesh
Ejemplo n.º 7
0
def plot_mesh(x,
              y,
              z,
              color=default_color,
              wireframe=True,
              surface=True,
              wrapx=False,
              wrapy=False,
              u=None,
              v=None,
              texture=None):
    """Draws a 2d wireframe+surface in 3d: generalization of :any:`plot_wireframe` and :any:`plot_surface`

    :param x: {x2d}
    :param y: {y2d}
    :param z: {z2d}
    :param color: {color2d}
    :param bool wireframe: draw lines between the vertices
    :param bool surface: draw faces/triangles between the vertices
    :param bool wrapx: when True, the x direction is assumed to wrap, and polygons are drawn between the begin and end points
    :param boool wrapy: idem for y
    :param u: {u}
    :param v: {v}
    :param texture: {texture}
    :return: :any:`Mesh`
    """
    fig = gcf()

    # assert len(x.shape) == 2
    # assert len(y.shape) == 2
    # assert len(z.shape) == 2
    # if isinstance(color, np.ndarray):
    # 	assert len(color.shape) == 3
    # 	assert color.shape[:2] == x.shape
    # 	color = color.reshape(-1)

    def dim(x):
        d = 0
        el = x
        while True:
            try:
                el = el[0]
                d += 1
            except:
                break
        return d

    if dim(x) == 2:
        nx, ny = shape = x.shape
    else:
        nx, ny = shape = x[0].shape

    def reshape(ar):
        if dim(ar) == 3:
            return [k.reshape(-1) for k in ar]
        else:
            return ar.reshape(-1)

    def reshape_color(ar):
        if dim(ar) == 4:
            return [k.reshape(-1, 3) for k in ar]
        else:
            return ar.reshape(-1, 3)

    if isinstance(color, np.ndarray):
        # if dim(color) == 4:
        #	color = color.reshape((color.shape[0], -1, color.shape[-1]))
        color = reshape_color(color)
        # print(color.shape)

    x = reshape(x)
    y = reshape(y)
    z = reshape(z)
    if u is not None:
        u = reshape(u)
    if v is not None:
        v = reshape(v)
    _grow_limits(
        np.array(x).reshape(-1),
        np.array(y).reshape(-1),
        np.array(z).reshape(-1))
    mx = nx if wrapx else nx - 1
    my = ny if wrapy else ny - 1
    triangles = np.zeros(((mx) * (my) * 2, 3), dtype=np.uint32)
    lines = np.zeros(((mx) * (my) * 4, 2), dtype=np.uint32)

    def index_from2d(i, j):
        xi = (i % nx)
        yi = (j % ny)
        return nx * xi + yi
        """
        ^ ydir
        |
        2 3
        0 1  ---> x dir
        """

    for i in range(mx):
        for j in range(my):
            p0 = index_from2d(i, j)
            p1 = index_from2d(i + 1, j)
            p2 = index_from2d(i, j + 1)
            p3 = index_from2d(i + 1, j + 1)
            triangle_index = (i * mx) + j
            triangles[triangle_index * 2 + 0, :] = [p0, p1, p3]
            triangles[triangle_index * 2 + 1, :] = [p0, p3, p2]
            lines[triangle_index * 4 + 0, :] = [p0, p1]
            lines[triangle_index * 4 + 1, :] = [p0, p2]
            lines[triangle_index * 4 + 2, :] = [p2, p3]
            lines[triangle_index * 4 + 3, :] = [p1, p3]
    # print(i, j, p0, p1, p2, p3)
    mesh = ipv.Mesh(x=x,
                    y=y,
                    z=z,
                    triangles=triangles if surface else None,
                    color=color,
                    lines=lines if wireframe else None,
                    u=u,
                    v=v,
                    texture=texture)
    fig.meshes = fig.meshes + [mesh]
    return mesh
Ejemplo n.º 8
0
    def _default_plotter(self, **kwargs):
        """
        Basic plot function to be used if no custom function is specified.

        This is called by plot, you shouldn't call it directly.
        """

        self.lengths = np.array([length(x) for x in self.lines2use_])
        if not ('grayscale' in kwargs and kwargs['grayscale']):
            self.colors = np.array([color(x) for x in self.lines2use_])
        else:
            self.colors = np.zeros((len(self.lines2use_), 3), dtype=np.float16)
            self.colors[:] = [0.5, 0.5, 0.5]
        self.state = {'threshold': 0, 'indices': []}

        width = 600
        height = 600
        perc = 80
        if 'width' in kwargs:
            width = kwargs['width']
        if 'height' in kwargs:
            height = kwargs['height']
        if 'percentile' in kwargs:
            perc = kwargs['percentile']

        ipv.clear()
        fig = ipv.figure(width=width, height=height)
        self.state['fig'] = fig

        with fig.hold_sync():
            x, y, z, indices, colors, self.line_pointers = self._create_mesh()
            limits = np.array([
                min([x.min(), y.min(), z.min()]),
                max([x.max(), y.max(), z.max()])
            ])
            mesh = ipv.Mesh(x=x, y=y, z=z, lines=indices, color=colors)
            fig.meshes = [mesh]
            if 'style' not in kwargs:
                fig.style = {
                    'axes': {
                        'color': 'black',
                        'label': {
                            'color': 'black'
                        },
                        'ticklabel': {
                            'color': 'black'
                        },
                        'visible': False
                    },
                    'background-color': 'white',
                    'box': {
                        'visible': False
                    }
                }
            else:
                fig.style = kwargs['style']
            ipv.pylab._grow_limits(limits, limits, limits)
            fig.camera_fov = 1
        ipv.show()

        interact(self._plot_lines,
                 state=fixed(self.state),
                 threshold=widgets.FloatSlider(value=np.percentile(
                     self.lengths, perc),
                                               min=self.lengths.min() - 1,
                                               max=self.lengths.max() - 1,
                                               continuous_update=False))