Ejemplo n.º 1
0
    def _3d_extend_contour(self, cset, stride=5):
        '''
        Extend a contour in 3D by creating
        '''

        levels = cset.levels
        colls = cset.collections
        dz = (levels[1] - levels[0]) / 2

        for z, linec in zip(levels, colls):
            topverts = art3d.paths_to_3d_segments(linec.get_paths(), z - dz)
            botverts = art3d.paths_to_3d_segments(linec.get_paths(), z + dz)

            color = linec.get_color()[0]

            polyverts = []
            normals = []
            nsteps = round(len(topverts[0]) / stride)
            if nsteps <= 1:
                if len(topverts[0]) > 1:
                    nsteps = 2
                else:
                    continue

            stepsize = (len(topverts[0]) - 1) / (nsteps - 1)
            for i in range(int(round(nsteps)) - 1):
                i1 = int(round(i * stepsize))
                i2 = int(round((i + 1) * stepsize))
                polyverts.append([topverts[0][i1],
                    topverts[0][i2],
                    botverts[0][i2],
                    botverts[0][i1]])

                v1 = np.array(topverts[0][i1]) - np.array(topverts[0][i2])
                v2 = np.array(topverts[0][i1]) - np.array(botverts[0][i1])
                normals.append(np.cross(v1, v2))

            colors = self._shade_colors(color, normals)
            colors2 = self._shade_colors(color, normals)
            polycol = art3d.Poly3DCollection(polyverts,
                                             facecolors=colors,
                                             edgecolors=colors2)
            polycol.set_sort_zpos(z)
            self.add_collection3d(polycol)

        for col in colls:
            self.collections.remove(col)
Ejemplo n.º 2
0
    def plot_surface(self, X, Y, Z, *args, **kwargs):
        had_data = self.has_data()

        rows, cols = Z.shape
        tX,tY,tZ = npy.transpose(X), npy.transpose(Y), npy.transpose(Z)
        rstride = cbook.popd(kwargs, 'rstride', 10)
        cstride = cbook.popd(kwargs, 'cstride', 10)
        #
        polys = []
        boxes = []
        for rs in npy.arange(0,rows-1,rstride):
            for cs in npy.arange(0,cols-1,cstride):
                ps = []
                corners = []
                for a,ta in [(X,tX),(Y,tY),(Z,tZ)]:
                    ztop = a[rs][cs:min(cols,cs+cstride+1)]
                    zleft = ta[min(cols-1,cs+cstride)][rs:min(rows,rs+rstride+1)]
                    zbase = a[min(rows-1,rs+rstride)][cs:min(cols,cs+cstride+1):]
                    zbase = zbase[::-1]
                    zright = ta[cs][rs:min(rows,rs+rstride+1):]
                    zright = zright[::-1]
                    corners.append([ztop[0],ztop[-1],zbase[0],zbase[-1]])
                    z = npy.concatenate((ztop,zleft,zbase,zright))
                    ps.append(z)
                boxes.append(map(npy.array,zip(*corners)))
                polys.append(zip(*ps))
        #
        lines = []
        shade = []
        for box in boxes:
            n = proj3d.cross(box[0]-box[1],
                         box[0]-box[2])
            n = n/proj3d.mod(n)*5
            shade.append(npy.dot(n,[-1,-1,0.5]))
            lines.append((box[0],n+box[0]))
        #
        color = npy.array([0,0,1,1])
        norm = Normalize(min(shade),max(shade))
        colors = [color * (0.5+norm(v)*0.5) for v in shade]
        for c in colors: c[3] = 1
        polyc = art3d.Poly3DCollection(polys, facecolors=colors, *args, **kwargs)
        polyc._zsort = 1
        self.add_collection(polyc)
        #
        self.auto_scale_xyz(X,Y,Z, had_data)
        return polyc
Ejemplo n.º 3
0
    def plot_surface(self, X, Y, Z, *args, **kwargs):
        '''
        Create a surface plot.

        By default it will be colored in shades of a solid color,
        but it also supports color mapping by supplying the *cmap*
        argument.

        ============= ================================================
        Argument      Description
        ============= ================================================
        *X*, *Y*, *Z* Data values as numpy.arrays
        *rstride*     Array row stride (step size)
        *cstride*     Array column stride (step size)
        *color*       Color of the surface patches
        *cmap*        A colormap for the surface patches.
        *facecolors*  Face colors for the individual patches
        *norm*        An instance of Normalize to map values to colors
        *vmin*        Minimum value to map
        *vmax*        Maximum value to map
        *shade*       Whether to shade the facecolors
        ============= ================================================

        Other arguments are passed on to
        :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection.__init__`
        '''

        had_data = self.has_data()

        rows, cols = Z.shape
        rstride = kwargs.pop('rstride', 10)
        cstride = kwargs.pop('cstride', 10)

        if 'facecolors' in kwargs:
            fcolors = kwargs.pop('facecolors')
        else:
            color = np.array(colorConverter.to_rgba(kwargs.pop('color', 'b')))
            fcolors = None

        cmap = kwargs.get('cmap', None)
        norm = kwargs.pop('norm', None)
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        linewidth = kwargs.get('linewidth', None)
        shade = kwargs.pop('shade', cmap is None)
        lightsource = kwargs.pop('lightsource', None)

        # Shade the data
        if shade and cmap is not None and fcolors is not None:
            fcolors = self._shade_colors_lightsource(Z, cmap, lightsource)

        polys = []
        # Only need these vectors to shade if there is no cmap
        if cmap is None and shade :
            totpts = int(np.ceil(float(rows - 1) / rstride) *
                         np.ceil(float(cols - 1) / cstride))
            v1 = np.empty((totpts, 3))
            v2 = np.empty((totpts, 3))
            # This indexes the vertex points
            which_pt = 0


        #colset contains the data for coloring: either average z or the facecolor
        colset = []
        for rs in xrange(0, rows-1, rstride):
            for cs in xrange(0, cols-1, cstride):  
                ps = []
                for a in (X, Y, Z) :
                    ztop = a[rs,cs:min(cols, cs+cstride+1)]
                    zleft = a[rs+1:min(rows, rs+rstride+1),
                              min(cols-1, cs+cstride)]
                    zbase = a[min(rows-1, rs+rstride), cs:min(cols, cs+cstride+1):][::-1]
                    zright = a[rs:min(rows-1, rs+rstride):, cs][::-1]
                    z = np.concatenate((ztop, zleft, zbase, zright))
                    ps.append(z)

                # The construction leaves the array with duplicate points, which
                # are removed here.
                ps = zip(*ps)
                lastp = np.array([])
                ps2 = [ps[0]] + [ps[i] for i in xrange(1, len(ps)) if ps[i] != ps[i-1]]
                avgzsum = sum(p[2] for p in ps2)
                polys.append(ps2)

                if fcolors is not None:
                    colset.append(fcolors[rs][cs])
                else:
                    colset.append(avgzsum / len(ps2))

                # Only need vectors to shade if no cmap
                if cmap is None and shade:
                    i1, i2, i3 = 0, int(len(ps2)/3), int(2*len(ps2)/3)
                    v1[which_pt] = np.array(ps2[i1]) - np.array(ps2[i2])
                    v2[which_pt] = np.array(ps2[i2]) - np.array(ps2[i3])
                    which_pt += 1
        if cmap is None and shade:
            normals = np.cross(v1, v2)
        else :
            normals = []

        polyc = art3d.Poly3DCollection(polys, *args, **kwargs)

        if fcolors is not None:
            if shade:
                colset = self._shade_colors(colset, normals)
            polyc.set_facecolors(colset)
            polyc.set_edgecolors(colset)
        elif cmap:
            colset = np.array(colset)
            polyc.set_array(colset)
            if vmin is not None or vmax is not None:
                polyc.set_clim(vmin, vmax)
            if norm is not None:
                polyc.set_norm(norm)
        else:
            if shade:
                colset = self._shade_colors(color, normals)
            else:
                colset = color
            polyc.set_facecolors(colset)

        self.add_collection(polyc)
        self.auto_scale_xyz(X, Y, Z, had_data)

        return polyc
Ejemplo n.º 4
0
    def bar3d(self, x, y, z, dx, dy, dz, color='b',
              zsort='average', *args, **kwargs):
        '''
        Generate a 3D bar, or multiple bars.

        When generating multiple bars, x, y, z have to be arrays.
        dx, dy, dz can be arrays or scalars.

        *color* can be:

         - A single color value, to color all bars the same color.

         - An array of colors of length N bars, to color each bar
           independently.

         - An array of colors of length 6, to color the faces of the
           bars similarly.

         - An array of colors of length 6 * N bars, to color each face
           independently.

         When coloring the faces of the boxes specifically, this is
         the order of the coloring:

          1. -Z (bottom of box)
          2. +Z (top of box)
          3. -Y
          4. +Y
          5. -X
          6. +X

        Keyword arguments are passed onto
        :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
        '''
        had_data = self.has_data()

        if not cbook.iterable(x):
            x = [x]
        if not cbook.iterable(y):
            y = [y]
        if not cbook.iterable(z):
            z = [z]

        if not cbook.iterable(dx):
            dx = [dx]
        if not cbook.iterable(dy):
            dy = [dy]
        if not cbook.iterable(dz):
            dz = [dz]

        if len(dx) == 1:
            dx = dx * len(x)
        if len(dy) == 1:
            dy = dy * len(y)
        if len(dz) == 1:
            dz = dz * len(z)

        if len(x) != len(y) or len(x) != len(z):
            warnings.warn('x, y, and z must be the same length.')

        minx, miny, minz = 1e20, 1e20, 1e20
        maxx, maxy, maxz = -1e20, -1e20, -1e20

        polys = []
        for xi, yi, zi, dxi, dyi, dzi in zip(x, y, z, dx, dy, dz):
            minx = min(xi, minx)
            maxx = max(xi + dxi, maxx)
            miny = min(yi, miny)
            maxy = max(yi + dyi, maxy)
            minz = min(zi, minz)
            maxz = max(zi + dzi, maxz)

            polys.extend([
                ((xi, yi, zi), (xi + dxi, yi, zi),
                    (xi + dxi, yi + dyi, zi), (xi, yi + dyi, zi)),
                ((xi, yi, zi + dzi), (xi + dxi, yi, zi + dzi),
                    (xi + dxi, yi + dyi, zi + dzi), (xi, yi + dyi, zi + dzi)),

                ((xi, yi, zi), (xi + dxi, yi, zi),
                    (xi + dxi, yi, zi + dzi), (xi, yi, zi + dzi)),
                ((xi, yi + dyi, zi), (xi + dxi, yi + dyi, zi),
                    (xi + dxi, yi + dyi, zi + dzi), (xi, yi + dyi, zi + dzi)),

                ((xi, yi, zi), (xi, yi + dyi, zi),
                    (xi, yi + dyi, zi + dzi), (xi, yi, zi + dzi)),
                ((xi + dxi, yi, zi), (xi + dxi, yi + dyi, zi),
                    (xi + dxi, yi + dyi, zi + dzi), (xi + dxi, yi, zi + dzi)),
            ])

        facecolors = []
        if color is None:
            # no color specified
            facecolors = [None] * len(x)
        elif len(color) == len(x):
            # bar colors specified, need to expand to number of faces
            for c in color:
                facecolors.extend([c] * 6)
        else:
            # a single color specified, or face colors specified explicitly
            facecolors = list(colorConverter.to_rgba_array(color))
            if len(facecolors) < len(x):
                facecolors *= (6 * len(x))

        normals = self._generate_normals(polys)
        sfacecolors = self._shade_colors(facecolors, normals)
        col = art3d.Poly3DCollection(polys,
                                     zsort=zsort,
                                     facecolor=sfacecolors,
                                     *args, **kwargs)
        self.add_collection(col)

        self.auto_scale_xyz((minx, maxx), (miny, maxy), (minz, maxz), had_data)
Ejemplo n.º 5
0
    def plot_surface(self, X, Y, Z, *args, **kwargs):
        '''
        Create a surface plot.

        By default it will be colored in shades of a solid color,
        but it also supports color mapping by supplying the *cmap*
        argument.

        ==========  ================================================
        Argument    Description
        ==========  ================================================
        *X*, *Y*,   Data values as numpy.arrays
        *Z*
        *rstride*   Array row stride (step size)
        *cstride*   Array column stride (step size)
        *color*     Color of the surface patches
        *cmap*      A colormap for the surface patches.
        ==========  ================================================
        '''

        had_data = self.has_data()

        rows, cols = Z.shape
        tX, tY, tZ = np.transpose(X), np.transpose(Y), np.transpose(Z)
        rstride = kwargs.pop('rstride', 10)
        cstride = kwargs.pop('cstride', 10)

        color = kwargs.pop('color', 'b')
        color = np.array(colorConverter.to_rgba(color))
        cmap = kwargs.get('cmap', None)

        polys = []
        normals = []
        avgz = []
        for rs in np.arange(0, rows - 1, rstride):
            for cs in np.arange(0, cols - 1, cstride):
                ps = []
                corners = []
                for a, ta in [(X, tX), (Y, tY), (Z, tZ)]:
                    ztop = a[rs][cs:min(cols, cs + cstride + 1)]
                    zleft = ta[min(cols - 1, cs +
                                   cstride)][rs:min(rows, rs + rstride + 1)]
                    zbase = a[min(rows - 1, rs +
                                  rstride)][cs:min(cols, cs + cstride + 1):]
                    zbase = zbase[::-1]
                    zright = ta[cs][rs:min(rows, rs + rstride + 1):]
                    zright = zright[::-1]
                    corners.append([ztop[0], ztop[-1], zbase[0], zbase[-1]])
                    z = np.concatenate((ztop, zleft, zbase, zright))
                    ps.append(z)

                # The construction leaves the array with duplicate points, which
                # are removed here.
                ps = zip(*ps)
                lastp = np.array([])
                ps2 = []
                avgzsum = 0.0
                for p in ps:
                    if p != lastp:
                        ps2.append(p)
                        lastp = p
                        avgzsum += p[2]
                polys.append(ps2)
                avgz.append(avgzsum / len(ps2))

                v1 = np.array(ps2[0]) - np.array(ps2[1])
                v2 = np.array(ps2[2]) - np.array(ps2[0])
                normals.append(np.cross(v1, v2))

        polyc = art3d.Poly3DCollection(polys, *args, **kwargs)
        if cmap is not None:
            polyc.set_array(np.array(avgz))
            polyc.set_linewidth(0)
        else:
            colors = self._shade_colors(color, normals)
            polyc.set_facecolors(colors)

        self.add_collection(polyc)
        self.auto_scale_xyz(X, Y, Z, had_data)

        return polyc
Ejemplo n.º 6
0
    def plot_surface(self, X, Y, Z, *args, **kwargs):
        '''
        Create a surface plot.

        By default it will be colored in shades of a solid color,
        but it also supports color mapping by supplying the *cmap*
        argument.

        ============= ================================================
        Argument      Description
        ============= ================================================
        *X*, *Y*, *Z* Data values as numpy.arrays
        *rstride*     Array row stride (step size)
        *cstride*     Array column stride (step size)
        *color*       Color of the surface patches
        *cmap*        A colormap for the surface patches.
        *facecolors*  Face colors for the individual patches
        *norm*        An instance of Normalize to map values to colors
        *vmin*        Minimum value to map
        *vmax*        Maximum value to map
        *shade*       Whether to shade the facecolors
        ============= ================================================

        Other arguments are passed on to
        :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection.__init__`
        '''

        had_data = self.has_data()

        rows, cols = Z.shape
        tX, tY, tZ = np.transpose(X), np.transpose(Y), np.transpose(Z)
        rstride = kwargs.pop('rstride', 10)
        cstride = kwargs.pop('cstride', 10)

        if 'facecolors' in kwargs:
            fcolors = kwargs.pop('facecolors')
        else:
            color = np.array(colorConverter.to_rgba(kwargs.pop('color', 'b')))
            fcolors = None

        cmap = kwargs.get('cmap', None)
        norm = kwargs.pop('norm', None)
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        linewidth = kwargs.get('linewidth', None)
        shade = kwargs.pop('shade', cmap is None)
        lightsource = kwargs.pop('lightsource', None)

        # Shade the data
        if shade and cmap is not None and fcolors is not None:
            fcolors = self._shade_colors_lightsource(Z, cmap, lightsource)

        polys = []
        normals = []
        #colset contains the data for coloring: either average z or the facecolor
        colset = []
        for rs in np.arange(0, rows - 1, rstride):
            for cs in np.arange(0, cols - 1, cstride):
                ps = []
                corners = []
                for a, ta in [(X, tX), (Y, tY), (Z, tZ)]:
                    ztop = a[rs][cs:min(cols, cs + cstride + 1)]
                    zleft = ta[min(cols - 1, cs +
                                   cstride)][rs:min(rows, rs + rstride + 1)]
                    zbase = a[min(rows - 1, rs +
                                  rstride)][cs:min(cols, cs + cstride + 1):]
                    zbase = zbase[::-1]
                    zright = ta[cs][rs:min(rows, rs + rstride + 1):]
                    zright = zright[::-1]
                    corners.append([ztop[0], ztop[-1], zbase[0], zbase[-1]])
                    z = np.concatenate((ztop, zleft, zbase, zright))
                    ps.append(z)

                # The construction leaves the array with duplicate points, which
                # are removed here.
                ps = zip(*ps)
                lastp = np.array([])
                ps2 = []
                avgzsum = 0.0
                for p in ps:
                    if p != lastp:
                        ps2.append(p)
                        lastp = p
                        avgzsum += p[2]
                polys.append(ps2)

                if fcolors is not None:
                    colset.append(fcolors[rs][cs])
                else:
                    colset.append(avgzsum / len(ps2))

                # Only need vectors to shade if no cmap
                if cmap is None and shade:
                    v1 = np.array(ps2[0]) - np.array(ps2[1])
                    v2 = np.array(ps2[2]) - np.array(ps2[0])
                    normals.append(np.cross(v1, v2))

        polyc = art3d.Poly3DCollection(polys, *args, **kwargs)

        if fcolors is not None:
            if shade:
                colset = self._shade_colors(colset, normals)
            polyc.set_facecolors(colset)
            polyc.set_edgecolors(colset)
        elif cmap:
            colset = np.array(colset)
            polyc.set_array(colset)
            if vmin is not None or vmax is not None:
                polyc.set_clim(vmin, vmax)
            if norm is not None:
                polyc.set_norm(norm)
        else:
            if shade:
                colset = self._shade_colors(color, normals)
            else:
                colset = color
            polyc.set_facecolors(colset)

        self.add_collection(polyc)
        self.auto_scale_xyz(X, Y, Z, had_data)

        return polyc