Revision: 8656
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8656&view=rev
Author:   heeres
Date:     2010-08-25 07:15:15 +0000 (Wed, 25 Aug 2010)

Log Message:
-----------
Fix ticks/limit setting, add tricontour(f),
make it easier to set pane colors

Modified Paths:
--------------
    trunk/matplotlib/examples/mplot3d/contour3d_demo2.py
    trunk/matplotlib/examples/mplot3d/surface3d_radial_demo.py
    trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py
    trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py
    trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py

Modified: trunk/matplotlib/examples/mplot3d/contour3d_demo2.py
===================================================================
--- trunk/matplotlib/examples/mplot3d/contour3d_demo2.py        2010-08-23 
18:24:25 UTC (rev 8655)
+++ trunk/matplotlib/examples/mplot3d/contour3d_demo2.py        2010-08-25 
07:15:15 UTC (rev 8656)
@@ -4,7 +4,7 @@
 fig = plt.figure()
 ax = fig.gca(projection='3d')
 X, Y, Z = axes3d.get_test_data(0.05)
-cset = ax.contour(X, Y, Z, 16, extend3d=True)
+cset = ax.contour(X, Y, Z, extend3d=True)
 ax.clabel(cset, fontsize=9, inline=1)
 
 plt.show()

Modified: trunk/matplotlib/examples/mplot3d/surface3d_radial_demo.py
===================================================================
--- trunk/matplotlib/examples/mplot3d/surface3d_radial_demo.py  2010-08-23 
18:24:25 UTC (rev 8655)
+++ trunk/matplotlib/examples/mplot3d/surface3d_radial_demo.py  2010-08-25 
07:15:15 UTC (rev 8656)
@@ -23,5 +23,4 @@
 ax.set_xlabel(r'$\phi_\mathrm{real}$')
 ax.set_ylabel(r'$\phi_\mathrm{im}$')
 ax.set_zlabel(r'$V(\phi)$')
-ax.set_xticks([])
 plt.show()

Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py
===================================================================
--- trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py  2010-08-23 18:24:25 UTC 
(rev 8655)
+++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py  2010-08-25 07:15:15 UTC 
(rev 8656)
@@ -291,8 +291,17 @@
         PatchCollection.__init__(self, *args, **kwargs)
         self._old_draw = lambda x: PatchCollection.draw(self, x)
 
+    def set_sort_zpos(self,val):
+        '''Set the position to use for z-sorting.'''
+        self._sort_zpos = val
+
     def set_3d_properties(self, zs, zdir):
-        xs, ys = zip(*self.get_offsets())
+        offsets = self.get_offsets()
+        if len(offsets) > 0:
+            xs, ys = zip(*self.get_offsets())
+        else:
+            xs = [0] * len(zs)
+            ys = [0] * len(zs)
         self._offsets3d = juggle_axes(xs, ys, zs, zdir)
         self._facecolor3d = self.get_facecolor()
         self._edgecolor3d = self.get_edgecolor()

Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py
===================================================================
--- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2010-08-23 18:24:25 UTC 
(rev 8655)
+++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2010-08-25 07:15:15 UTC 
(rev 8656)
@@ -58,7 +58,6 @@
 
         if rect is None:
             rect = [0.0, 0.0, 1.0, 1.0]
-        self.fig = fig
         self._cids = []
 
         self.initial_azim = kwargs.pop('azim', -60)
@@ -72,20 +71,28 @@
         # they can't be defined until Axes.__init__ has been called
         self.view_init(self.initial_elev, self.initial_azim)
         self._ready = 0
-        Axes.__init__(self, self.fig, rect,
+
+        Axes.__init__(self, fig, rect,
                       frameon=True,
-                      xticks=[], yticks=[], *args, **kwargs)
-
+                      *args, **kwargs)
+        # Disable drawing of axes by base class
+        Axes.set_axis_off(self)
+        self._axis3don = True
         self.M = None
 
         self._ready = 1
         self.mouse_init()
-        self.create_axes()
         self.set_top_view()
 
         self.axesPatch.set_linewidth(0)
-        self.fig.add_axes(self)
+        self.figure.add_axes(self)
 
+    def set_axis_off(self):
+        self._axis3don = False
+
+    def set_axis_on(self):
+        self._axis3don = True
+
     def set_top_view(self):
         # this happens to be the right view for the viewing coordinates
         # moved up and to the left slightly to fit labels and axes
@@ -97,14 +104,24 @@
         Axes.set_xlim(self, -xdwl, xdw, auto=None)
         Axes.set_ylim(self, -ydwl, ydw, auto=None)
 
-    def create_axes(self):
+    def _init_axis(self):
+        '''Init 3d axes; overrides creation of regular X/Y axes'''
         self.w_xaxis = axis3d.XAxis('x', self.xy_viewLim.intervalx,
                             self.xy_dataLim.intervalx, self)
+        self.xaxis = self.w_xaxis
         self.w_yaxis = axis3d.YAxis('y', self.xy_viewLim.intervaly,
                             self.xy_dataLim.intervaly, self)
+        self.yaxis = self.w_yaxis
         self.w_zaxis = axis3d.ZAxis('z', self.zz_viewLim.intervalx,
                             self.zz_dataLim.intervalx, self)
+        self.zaxis = self.w_zaxis
 
+        for ax in self.xaxis, self.yaxis, self.zaxis:
+            ax.init3d()
+
+    def get_children(self):
+        return [self.zaxis,] + Axes.get_children(self)
+
     def unit_cube(self, vals=None):
         minx, maxx, miny, maxy, minz, maxz = vals or self.get_w_lims()
         xs, ys, zs = ([minx, maxx, maxx, minx, minx, maxx, maxx, minx],
@@ -165,12 +182,16 @@
         for i, (z, patch) in enumerate(zlist):
             patch.zorder = i
 
-        axes = (self.w_xaxis, self.w_yaxis, self.w_zaxis)
-        for ax in axes:
-            ax.draw_pane(renderer)
-        for ax in axes:
-            ax.draw(renderer)
+        if self._axis3don:
+            axes = (self.w_xaxis, self.w_yaxis, self.w_zaxis)
+            # Draw panes first
+            for ax in axes:
+                ax.draw_pane(renderer)
+            # Then axes
+            for ax in axes:
+                ax.draw(renderer)
 
+        # Then rest
         Axes.draw(self, renderer)
 
     def get_axis_position(self):
@@ -240,18 +261,21 @@
         lims = self._determine_lims(*args, **kwargs)
         self.xy_viewLim.intervalx = lims
         return lims
+    set_xlim = set_xlim3d
 
     def set_ylim3d(self, *args, **kwargs):
         '''Set 3D y limits.'''
         lims = self._determine_lims(*args, **kwargs)
         self.xy_viewLim.intervaly = lims
         return lims
+    set_ylim = set_ylim3d
 
     def set_zlim3d(self, *args, **kwargs):
         '''Set 3D z limits.'''
         lims = self._determine_lims(*args, **kwargs)
         self.zz_viewLim.intervalx = lims
         return lims
+    set_zlim = set_zlim3d
 
     def get_xlim3d(self):
         '''Get 3D x limits.'''
@@ -264,7 +288,18 @@
     def get_zlim3d(self):
         '''Get 3D z limits.'''
         return self.zz_viewLim.intervalx
+    get_zlim = get_zlim3d
 
+    def set_zticks(self,*args,**kwargs):
+        """
+        Set 3d z tick locations and (optionally labels).
+        See set_xticks3d for more details.
+        """
+        return self.w_zaxis.set_ticks(*args, **kwargs)
+        
+    def get_zticks(self):
+        return self.w_zaxis.get_ticks()
+
     def clabel(self, *args, **kwargs):
         return None
 
@@ -722,8 +757,9 @@
 
                 # 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])
+                    i1, i2, i3 = 0, int(len(ps2)/3), int(2*len(ps2)/3)
+                    v1 = np.array(ps2[i1]) - np.array(ps2[i2])
+                    v2 = np.array(ps2[i2]) - np.array(ps2[i3])
                     normals.append(np.cross(v1, v2))
 
         polyc = art3d.Poly3DCollection(polys, *args, **kwargs)
@@ -896,6 +932,16 @@
         for col in colls:
             self.collections.remove(col)
 
+    def add_contour_set(self, cset, extend3d=False, stride=5, zdir='z', 
offset=None):
+        zdir = '-' + zdir
+        if extend3d:
+            self._3d_extend_contour(cset, stride)
+        else:
+            for z, linec in zip(cset.levels, cset.collections):
+                if offset is not None:
+                    z = offset
+                art3d.line_collection_2d_to_3d(linec, z, zdir=zdir)
+
     def contour(self, X, Y, Z, *args, **kwargs):
         '''
         Create a 3D contour plot.
@@ -927,21 +973,49 @@
 
         jX, jY, jZ = art3d.rotate_axes(X, Y, Z, zdir)
         cset = Axes.contour(self, jX, jY, jZ, *args, **kwargs)
+        self.add_contour_set(cset, extend3d, stride, zdir, offset)
 
-        zdir = '-' + zdir
-        if extend3d:
-            self._3d_extend_contour(cset, stride)
-        else:
-            for z, linec in zip(cset.levels, cset.collections):
-                if offset is not None:
-                    z = offset
-                art3d.line_collection_2d_to_3d(linec, z, zdir=zdir)
-
         self.auto_scale_xyz(X, Y, Z, had_data)
         return cset
 
     contour3D = contour
 
+    def tricontour(self, X, Y, Z, *args, **kwargs):
+        '''
+        Create a 3D contour plot.
+
+        ==========  ================================================
+        Argument    Description
+        ==========  ================================================
+        *X*, *Y*,   Data values as numpy.arrays
+        *Z*
+        *extend3d*  Whether to extend contour in 3D (default: False)
+        *stride*    Stride (step size) for extending contour
+        *zdir*      The direction to use: x, y or z (default)
+        *offset*    If specified plot a projection of the contour
+                    lines on this position in plane normal to zdir
+        ==========  ================================================
+
+        Other keyword arguments are passed on to
+        :func:`~matplotlib.axes.Axes.tricontour`
+
+        Returns a :class:`~matplotlib.axes.Axes.contour`
+        '''
+
+        extend3d = kwargs.pop('extend3d', False)
+        stride = kwargs.pop('stride', 5)
+        zdir = kwargs.pop('zdir', 'z')
+        offset = kwargs.pop('offset', None)
+
+        had_data = self.has_data()
+
+        jX, jY, jZ = art3d.rotate_axes(X, Y, Z, zdir)
+        cset = Axes.tricontour(self, jX, jY, jZ, *args, **kwargs)
+        self.add_contour_set(cset, extend3d, stride, zdir, offset)
+
+        self.auto_scale_xyz(X, Y, Z, had_data)
+        return cset
+
     def contourf(self, X, Y, Z, *args, **kwargs):
         '''
         Plot filled 3D contours.
@@ -968,6 +1042,43 @@
 
     contourf3D = contourf
 
+    def tricontourf(self, X, Y, Z, offset=None, zdir='z', *args, **kwargs):
+        '''
+        Create a 3D contourf plot.
+
+        ==========  ================================================
+        Argument    Description
+        ==========  ================================================
+        *X*, *Y*,   Data values as numpy.arrays
+        *Z*
+        *extend3d*  Whether to extend contour in 3D (default: False)
+        *stride*    Stride (step size) for extending contour
+        *zdir*      The direction to use: x, y or z (default)
+        *offset*    If specified plot a projection of the contour
+                    lines on this position in plane normal to zdir
+        ==========  ================================================
+
+        Other keyword arguments are passed on to
+        :func:`~matplotlib.axes.Axes.tricontour`
+
+        Returns a :class:`~matplotlib.axes.Axes.contour`
+        '''
+
+        zdir = '-' + zdir
+        had_data = self.has_data()
+
+        cset = Axes.tricontourf(self, X, Y, Z, *args, **kwargs)
+        levels = cset.levels
+        colls = cset.collections
+        for z1, linec in zip(levels, colls):
+            if offset is not None:
+                z1 = offset
+            art3d.poly_collection_2d_to_3d(linec, z1, zdir=zdir)
+            linec.set_sort_zpos(z1)
+
+        self.auto_scale_xyz(X, Y, Z, had_data)
+        return cset
+
     def add_collection3d(self, col, zs=0, zdir='z'):
         '''
         Add a 3d collection object to the plot.
@@ -993,21 +1104,32 @@
 
         Axes.add_collection(self, col)
 
-    def scatter(self, xs, ys, zs=0, zdir='z', *args, **kwargs):
+    def scatter(self, xs, ys, zs=0, zdir='z', s=20, c='b', *args, **kwargs):
         '''
         Create a scatter plot.
 
         ==========  ================================================
         Argument    Description
-        ==========  ================================================
+        ==========  ==========================================================
         *xs*, *ys*  Positions of data points.
         *zs*        Either an array of the same length as *xs* and
                     *ys* or a single value to place all points in
                     the same plane. Default is 0.
         *zdir*      Which direction to use as z ('x', 'y' or 'z')
                     when plotting a 2d set.
-        ==========  ================================================
+        *s*         size in points^2.  It is a scalar or an array of the same
+                    length as *x* and *y*.
 
+        *c*         a color. *c* can be a single color format string, or a
+                    sequence of color specifications of length *N*, or a
+                    sequence of *N* numbers to be mapped to colors using the
+                    *cmap* and *norm* specified via kwargs (see below). Note
+                    that *c* should not be a single numeric RGB or RGBA
+                    sequence because that is indistinguishable from an array
+                    of values to be colormapped.  *c* can be a 2-D array in
+                    which the rows are RGB or RGBA, however.
+        ==========  ==========================================================
+
         Keyword arguments are passed on to
         :func:`~matplotlib.axes.Axes.scatter`.
 
@@ -1016,7 +1138,25 @@
 
         had_data = self.has_data()
 
-        patches = Axes.scatter(self, xs, ys, *args, **kwargs)
+        xs = np.ma.ravel(xs)
+        ys = np.ma.ravel(ys)
+        zs = np.ma.ravel(zs)
+        if xs.size != ys.size:
+            raise ValueError("x and y must be the same size")
+        if xs.size != zs.size and zs.size == 1:
+            zs = np.array(zs[0] * xs.size)
+
+        s = np.ma.ravel(s)  # This doesn't have to match x, y in size.
+
+        cstr = cbook.is_string_like(c) or cbook.is_sequence_of_strings(c)
+        if not cstr:
+            c = np.asanyarray(c)
+            if c.size == xs.size:
+                c = np.ma.ravel(c)
+
+        xs, ys, zs, s, c = cbook.delete_masked_points(xs, ys, zs, s, c)
+
+        patches = Axes.scatter(self, xs, ys, s=s, c=c, *args, **kwargs)
         if not cbook.iterable(zs):
             is_2d = True
             zs = np.ones(len(xs)) * zs

Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py
===================================================================
--- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py 2010-08-23 18:24:25 UTC 
(rev 8655)
+++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py 2010-08-25 07:15:15 UTC 
(rev 8656)
@@ -73,6 +73,11 @@
         self.v_interval = v_intervalx
 
         maxis.XAxis.__init__(self, axes, *args, **kwargs)
+
+        self.set_rotate_label(kwargs.get('rotate_label', None))
+
+
+    def init3d(self):
         self.line = mlines.Line2D(xdata=(0, 0), ydata=(0, 0),
                                  linewidth=0.75,
                                  color=(0, 0, 0, 1),
@@ -80,11 +85,11 @@
                            )
 
         # Store dummy data in Polygon object
-        self.has_pane = True
         self.pane = mpatches.Polygon(np.array([[0,0], [0,1], [1,0], [0,0]]),
                                     alpha=0.8,
                                     facecolor=(1,1,1,0),
                                     edgecolor=(1,1,1,0))
+        self.set_pane_color(self._AXINFO[self.adir]['color'])
 
         self.axes._set_artist_props(self.line)
         self.axes._set_artist_props(self.pane)
@@ -92,7 +97,6 @@
         self.axes._set_artist_props(self.gridlines)
         self.axes._set_artist_props(self.label)
         self.label._transform = self.axes.transData
-        self.set_rotate_label(kwargs.get('rotate_label', None))
 
     def get_tick_positions(self):
         majorLocs = self.major.locator()
@@ -110,15 +114,17 @@
             t.label2.set_transform(self.axes.transData)
         return ticks
 
-    def set_pane(self, xys, color):
-        if self.has_pane:
-            xys = np.asarray(xys)
-            xys = xys[:,:2]
-            self.pane.xy = xys
-            self.pane.set_edgecolor(color)
-            self.pane.set_facecolor(color)
-            self.pane.set_alpha(color[-1])
+    def set_pane_pos(self, xys):
+        xys = np.asarray(xys)
+        xys = xys[:,:2]
+        self.pane.xy = xys
 
+    def set_pane_color(self, color):
+        '''Set pane color to a RGBA tuple'''
+        self.pane.set_edgecolor(color)
+        self.pane.set_facecolor(color)
+        self.pane.set_alpha(color[-1])
+
     def set_rotate_label(self, val):
         '''
         Whether to rotate the axis label: True, False or None.
@@ -161,7 +167,7 @@
         else:
             plane = self._PLANES[2 * index + 1]
         xys = [tc[p] for p in plane]
-        self.set_pane(xys, info['color'])
+        self.set_pane_pos(xys)
         self.pane.draw(renderer)
 
         renderer.close_group('pane3d')
@@ -225,25 +231,26 @@
         self.label.set_va('center')
         self.label.draw(renderer)
 
-        # Grid points at end of one plane
-        xyz1 = copy.deepcopy(xyz0)
-        newindex = (index + 1) % 3
-        newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
-        for i in range(len(majorLocs)):
-            xyz1[i][newindex] = newval
+        if len(xyz0) > 0:
+            # Grid points at end of one plane
+            xyz1 = copy.deepcopy(xyz0)
+            newindex = (index + 1) % 3
+            newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
+            for i in range(len(majorLocs)):
+                xyz1[i][newindex] = newval
 
-        # Grid points at end of the other plane
-        xyz2 = copy.deepcopy(xyz0)
-        newindex = (index + 2) %  3
-        newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
-        for i in range(len(majorLocs)):
-            xyz2[i][newindex] = newval
+            # Grid points at end of the other plane
+            xyz2 = copy.deepcopy(xyz0)
+            newindex = (index + 2) %  3
+            newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
+            for i in range(len(majorLocs)):
+                xyz2[i][newindex] = newval
 
-        lines = zip(xyz1, xyz0, xyz2)
-        if self.axes._draw_grid:
-            self.gridlines.set_segments(lines)
-            self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines))
-            self.gridlines.draw(renderer, project=True)
+            lines = zip(xyz1, xyz0, xyz2)
+            if self.axes._draw_grid:
+                self.gridlines.set_segments(lines)
+                self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines))
+                self.gridlines.draw(renderer, project=True)
 
         # Draw ticks
         tickdir = info['tickdir']
@@ -284,19 +291,23 @@
         renderer.close_group('axis3d')
 
     def get_view_interval(self):
-        """return the Interval instance for this axis view limits"""
+        """return the Interval instance for this 3d axis view limits"""
         return self.v_interval
+        
+    def set_view_interval(self, vmin, vmax, ignore=False):
+        if ignore:
+            self.v_interval = vmin, vmax
+        else:
+            Vmin, Vmax = self.get_view_interval()
+            self.v_interval = min(vmin, Vmin), max(vmax, Vmax)
 
-# Each type of axis should be looking in a different place for its
-# current data limits so we do this with classes.  I think there is
-# a lot more that I can and should move down into these classes also.
+# Use classes to look at different data limits
 
 class XAxis(Axis):
     def get_data_interval(self):
         'return the Interval instance for this axis data limits'
         return self.axes.xy_dataLim.intervalx
 
-
 class YAxis(Axis):
     def get_data_interval(self):
         'return the Interval instance for this axis data limits'


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Sell apps to millions through the Intel(R) Atom(Tm) Developer Program
Be part of this innovative community and reach millions of netbook users 
worldwide. Take advantage of special opportunities to increase revenue and 
speed time-to-market. Join now, and jumpstart your future.
http://p.sf.net/sfu/intel-atom-d2d
_______________________________________________
Matplotlib-checkins mailing list
Matplotlib-checkins@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to