From: <he...@us...> - 2009-06-07 23:23:51
|
Revision: 7198 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7198&view=rev Author: heeres Date: 2009-06-07 23:23:41 +0000 (Sun, 07 Jun 2009) Log Message: ----------- mplot3d: update axes code, add support for '3D' text. Split and add examples and begin documentation. Modified Paths: -------------- trunk/matplotlib/doc/devel/documenting_mpl.rst trunk/matplotlib/doc/users/toolkits.rst trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/proj3d.py Added Paths: ----------- trunk/matplotlib/examples/mplot3d/2dcollections3d_demo.py trunk/matplotlib/examples/mplot3d/bars3d_demo.py trunk/matplotlib/examples/mplot3d/contour3d_demo.py trunk/matplotlib/examples/mplot3d/contourf3d_demo.py trunk/matplotlib/examples/mplot3d/lines3d_demo.py trunk/matplotlib/examples/mplot3d/polys3d_demo.py trunk/matplotlib/examples/mplot3d/scatter3d_demo.py trunk/matplotlib/examples/mplot3d/surface3d_demo.py trunk/matplotlib/examples/mplot3d/text3d_demo.py trunk/matplotlib/examples/mplot3d/wire3d_demo.py Removed Paths: ------------- trunk/matplotlib/examples/mplot3d/contour.py trunk/matplotlib/examples/mplot3d/contourf.py trunk/matplotlib/examples/mplot3d/demo.py trunk/matplotlib/examples/mplot3d/polys.py trunk/matplotlib/examples/mplot3d/scatter.py trunk/matplotlib/examples/mplot3d/surface.py trunk/matplotlib/examples/mplot3d/wire.py Modified: trunk/matplotlib/doc/devel/documenting_mpl.rst =================================================================== --- trunk/matplotlib/doc/devel/documenting_mpl.rst 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/doc/devel/documenting_mpl.rst 2009-06-07 23:23:41 UTC (rev 7198) @@ -9,9 +9,11 @@ The documentation for matplotlib is generated from ReStructured Text using the Sphinx_ documentation generation tool. Sphinx-0.5 or later -is required. Most developers work from the sphinx subversion repository because it is a rapidly evolving project:: +is required. You might still run into problems, so most developers +work from the sphinx source repository (Mercurial based) because it +is a rapidly evolving project:: - svn co http://svn.python.org/projects/doctools/trunk sphinx + hg clone http://bitbucket.org/birkenfeld/sphinx/ cd sphinx python setup.py install Modified: trunk/matplotlib/doc/users/toolkits.rst =================================================================== --- trunk/matplotlib/doc/users/toolkits.rst 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/doc/users/toolkits.rst 2009-06-07 23:23:41 UTC (rev 7198) @@ -54,6 +54,7 @@ there, but ships with matplotlib and thus may be a lighter weight solution for some use cases. +See :ref:`toolkit_mplot3d-index` for more documentation and examples. .. _toolkit_axes_grid: Added: trunk/matplotlib/examples/mplot3d/2dcollections3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/2dcollections3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/2dcollections3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,24 @@ +from mpl_toolkits.mplot3d import Axes3D +import numpy as np +import pylab + +fig = pylab.figure() +ax = Axes3D(fig) + +x = np.linspace(0, 1, 100) +y = np.sin(x * 2 * np.pi) / 2 + 0.5 +ax.plot(x, y, zs=0, zdir='z', label='zs=0, zdir=z') + +colors = ('r', 'g', 'b', 'k') +for c in colors: + x = np.random.sample(20) + y = np.random.sample(20) + ax.scatter(x, y, 0, zdir='y', c=c) + +ax.legend() +ax.set_xlim3d(0, 1) +ax.set_ylim3d(0, 1) +ax.set_zlim3d(0, 1) + +pylab.show() + Added: trunk/matplotlib/examples/mplot3d/bars3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/bars3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/bars3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,20 @@ +from mpl_toolkits.mplot3d import Axes3D +from matplotlib.collections import PolyCollection +from matplotlib.colors import colorConverter +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = Axes3D(fig) +for c, z in zip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]): + xs = np.arange(20) + ys = [random.random() for x in xs] + ax.bar(xs, ys, zs=z, zdir='y', color=c, alpha=0.8) + +ax.set_xlabel('X') +ax.set_ylabel('Y') +ax.set_zlabel('Z') + +pylab.show() + Deleted: trunk/matplotlib/examples/mplot3d/contour.py =================================================================== --- trunk/matplotlib/examples/mplot3d/contour.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/contour.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,12 +0,0 @@ -from mpl_toolkits.mplot3d import axes3d -import pylab -import random - -fig = pylab.figure() -ax = axes3d.Axes3D(fig) -X, Y, Z = axes3d.get_test_data(0.05) -cset = ax.contour3D(X, Y, Z) -ax.clabel(cset, fontsize=9, inline=1) - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/contour3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/contour.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/contour3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/contour3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,12 @@ +from mpl_toolkits.mplot3d import axes3d +import pylab +import random + +fig = pylab.figure() +ax = axes3d.Axes3D(fig) +X, Y, Z = axes3d.get_test_data(0.05) +cset = ax.contour(X, Y, Z) +ax.clabel(cset, fontsize=9, inline=1) + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/contour3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/contour.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/contour.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Deleted: trunk/matplotlib/examples/mplot3d/contourf.py =================================================================== --- trunk/matplotlib/examples/mplot3d/contourf.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/contourf.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,12 +0,0 @@ -from mpl_toolkits.mplot3d import axes3d -import pylab -import random - -fig = pylab.figure() -ax = axes3d.Axes3D(fig) -X, Y, Z = axes3d.get_test_data(0.05) -cset = ax.contourf3D(X, Y, Z) -ax.clabel(cset, fontsize=9, inline=1) - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/contourf3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/contourf.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/contourf3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/contourf3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,12 @@ +from mpl_toolkits.mplot3d import axes3d +import pylab +import random + +fig = pylab.figure() +ax = axes3d.Axes3D(fig) +X, Y, Z = axes3d.get_test_data(0.05) +cset = ax.contourf(X, Y, Z) +ax.clabel(cset, fontsize=9, inline=1) + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/contourf3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/contourf.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/contourf.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Deleted: trunk/matplotlib/examples/mplot3d/demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/demo.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,138 +0,0 @@ -import random -import numpy as np -import matplotlib.pyplot as plt -import mpl_toolkits.mplot3d.axes3d as axes3d -from matplotlib.colors import Normalize, colorConverter - -def test_scatter(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - n = 100 - for c,zl,zh in [('r',-50,-25),('b',-30,-5)]: - xs,ys,zs = zip(* - [(random.randrange(23,32), - random.randrange(100), - random.randrange(zl,zh) - ) for i in range(n)]) - ax.scatter3D(xs,ys,zs, c=c) - - ax.set_xlabel('------------ X Label --------------------') - ax.set_ylabel('------------ Y Label --------------------') - ax.set_zlabel('------------ Z Label --------------------') - -def test_wire(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - X,Y,Z = axes3d.get_test_data(0.05) - ax.plot_wireframe(X,Y,Z, rstride=10,cstride=10) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - -def test_surface(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - X,Y,Z = axes3d.get_test_data(0.05) - ax.plot_surface(X,Y,Z, rstride=10,cstride=10) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - -def test_contour(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - X,Y,Z = axes3d.get_test_data(0.05) - cset = ax.contour3D(X,Y,Z) - ax.clabel(cset, fontsize=9, inline=1) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - -def test_contourf(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - X,Y,Z = axes3d.get_test_data(0.05) - cset = ax.contourf3D(X,Y,Z) - ax.clabel(cset, fontsize=9, inline=1) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - -def test_plot(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - xs = np.arange(0,4*np.pi+0.1,0.1) - ys = np.sin(xs) - ax.plot(xs,ys, label='zl') - ax.plot(xs,ys+max(xs),label='zh') - ax.plot(xs,ys,dir='x', label='xl') - ax.plot(xs,ys,dir='x', z=max(xs),label='xh') - ax.plot(xs,ys,dir='y', label='yl') - ax.plot(xs,ys,dir='y', z=max(xs), label='yh') - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - ax.legend() - -def test_polys(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6) - - xs = np.arange(0,10,0.4) - verts = [] - zs = [0.0,1.0,2.0,3.0] - for z in zs: - ys = [random.random() for x in xs] - ys[0],ys[-1] = 0,0 - verts.append(zip(xs,ys)) - - from matplotlib.collections import PolyCollection - poly = PolyCollection(verts, facecolors = [cc('r'),cc('g'),cc('b'), - cc('y')]) - poly.set_alpha(0.7) - ax.add_collection(poly,zs=zs,dir='y') - - ax.set_xlim(0,10) - ax.set_ylim(-1,4) - ax.set_zlim(0,1) - -def test_scatter2D(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - xs = [random.random() for i in range(20)] - ys = [random.random() for x in xs] - ax.scatter(xs, ys) - ax.scatter(xs, ys, dir='y', c='r') - ax.scatter(xs, ys, dir='x', c='g') - -def test_bar2D(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - for c,z in zip(['r','g','b', 'y'],[30,20,10,0]): - xs = np.arange(20) - ys = [random.random() for x in xs] - ax.bar(xs, ys, z=z, dir='y', color=c, alpha=0.8) - -if __name__ == "__main__": - - test_scatter() - test_wire() - test_surface() - test_contour() - test_contourf() - test_plot() - test_polys() - test_scatter2D() - test_bar2D() - - plt.show() Added: trunk/matplotlib/examples/mplot3d/lines3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/lines3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/lines3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,19 @@ +import matplotlib as mpl +from mpl_toolkits.mplot3d import Axes3D +import numpy as np +import pylab + +mpl.rcParams['legend.fontsize'] = 10 + +fig = pylab.figure() +ax = Axes3D(fig) +theta = np.linspace(-4 * np.pi, 4 * np.pi, 100) +z = np.linspace(-2, 2, 100) +r = z**2 + 1 +x = r * np.sin(theta) +y = r * np.cos(theta) +ax.plot(x, y, z, label='parametric curve') +ax.legend() + +pylab.show() + Deleted: trunk/matplotlib/examples/mplot3d/polys.py =================================================================== --- trunk/matplotlib/examples/mplot3d/polys.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/polys.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,31 +0,0 @@ -from mpl_toolkits.mplot3d import Axes3D -from matplotlib.collections import PolyCollection -from matplotlib.colors import colorConverter -import pylab -import random -import numpy as np - -fig = pylab.figure() -ax = Axes3D(fig) - -cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6) - -xs = np.arange(0, 10, 0.4) -verts = [] -zs = [0.0, 1.0, 2.0, 3.0] -for z in zs: - ys = [random.random() for x in xs] - ys[0], ys[-1] = 0, 0 - verts.append(zip(xs, ys)) - -poly = PolyCollection(verts, facecolors = [cc('r'), cc('g'), cc('b'), - cc('y')]) -poly.set_alpha(0.7) -ax.add_collection(poly, zs=zs, dir='y') - -ax.set_xlim(0, 10) -ax.set_ylim(-1, 4) -ax.set_zlim(0, 1) - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/polys3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/polys.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/polys3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/polys3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,31 @@ +from mpl_toolkits.mplot3d import Axes3D +from matplotlib.collections import PolyCollection +from matplotlib.colors import colorConverter +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = Axes3D(fig) + +cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6) + +xs = np.arange(0, 10, 0.4) +verts = [] +zs = [0.0, 1.0, 2.0, 3.0] +for z in zs: + ys = [random.random() for x in xs] + ys[0], ys[-1] = 0, 0 + verts.append(zip(xs, ys)) + +poly = PolyCollection(verts, facecolors = [cc('r'), cc('g'), cc('b'), + cc('y')]) +poly.set_alpha(0.7) +ax.add_collection3d(poly, zs=zs, zdir='y') + +ax.set_xlim3d(0, 10) +ax.set_ylim3d(-1, 4) +ax.set_zlim3d(0, 1) + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/polys3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/polys.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/polys.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Deleted: trunk/matplotlib/examples/mplot3d/scatter.py =================================================================== --- trunk/matplotlib/examples/mplot3d/scatter.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/scatter.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,21 +0,0 @@ -from mpl_toolkits.mplot3d import Axes3D -import pylab -import random - -fig = pylab.figure() -ax = Axes3D(fig) -n = 100 -for c, zl, zh in [('r', -50, -25), ('b', -30, -5)]: - xs, ys, zs = zip(* - [(random.randrange(23, 32), - random.randrange(100), - random.randrange(zl, zh) - ) for i in range(n)]) - ax.scatter3D(xs, ys, zs, c=c) - -ax.set_xlabel('X Label') -ax.set_ylabel('Y Label') -ax.set_zlabel('Z Label') - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/scatter3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/scatter.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/scatter3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/scatter3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,21 @@ +from mpl_toolkits.mplot3d import Axes3D +import pylab +import random + +fig = pylab.figure() +ax = Axes3D(fig) +n = 100 +for c, zl, zh in [('r', -50, -25), ('b', -30, -5)]: + xs, ys, zs = zip(* + [(random.randrange(23, 32), + random.randrange(100), + random.randrange(zl, zh) + ) for i in range(n)]) + ax.scatter(xs, ys, zs, c=c) + +ax.set_xlabel('X Label') +ax.set_ylabel('Y Label') +ax.set_zlabel('Z Label') + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/scatter3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/scatter.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/scatter.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Deleted: trunk/matplotlib/examples/mplot3d/surface.py =================================================================== --- trunk/matplotlib/examples/mplot3d/surface.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/surface.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,16 +0,0 @@ -from mpl_toolkits.mplot3d import Axes3D -import pylab -import random -import numpy as np - -fig = pylab.figure() -ax = Axes3D(fig) -X = np.arange(-5, 5, 0.5) -Y = np.arange(-5, 5, 0.5) -X, Y = np.meshgrid(X, Y) -R = np.sqrt(X**2 + Y**2) -Z = np.sin(R) -ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color='forestgreen') - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/surface3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/surface.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/surface3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/surface3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,16 @@ +from mpl_toolkits.mplot3d import Axes3D +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = Axes3D(fig) +X = np.arange(-5, 5, 0.5) +Y = np.arange(-5, 5, 0.5) +X, Y = np.meshgrid(X, Y) +R = np.sqrt(X**2 + Y**2) +Z = np.sin(R) +ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color='forestgreen') + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/surface3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/surface.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/surface.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Added: trunk/matplotlib/examples/mplot3d/text3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/text3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/text3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,26 @@ +from mpl_toolkits.mplot3d import Axes3D +import pylab +import random + +fig = pylab.figure() +ax = Axes3D(fig) + +zdirs = (None, 'x', 'y', 'z', (1, 1, 0), (1, 1, 1)) +xs = (2, 6, 4, 9, 7, 2) +ys = (6, 4, 8, 7, 2, 2) +zs = (4, 2, 5, 6, 1, 7) + +for zdir, x, y, z in zip(zdirs, xs, ys, zs): + label = '(%d, %d, %d), dir=%s' % (x, y, z, zdir) + ax.text(x, y, z, label, zdir) + +ax.set_xlim3d(0, 10) +ax.set_ylim3d(0, 10) +ax.set_zlim3d(0, 10) + +ax.set_xlabel('X axis') +ax.set_ylabel('Y axis') +ax.set_zlabel('Z axis') + +pylab.show() + Deleted: trunk/matplotlib/examples/mplot3d/wire.py =================================================================== --- trunk/matplotlib/examples/mplot3d/wire.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/wire.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,12 +0,0 @@ -from mpl_toolkits.mplot3d import axes3d -import pylab -import random -import numpy as np - -fig = pylab.figure() -ax = axes3d.Axes3D(fig) -X, Y, Z = axes3d.get_test_data(0.05) -ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/wire3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/wire.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/wire3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/wire3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,12 @@ +from mpl_toolkits.mplot3d import axes3d +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = axes3d.Axes3D(fig) +X, Y, Z = axes3d.get_test_data(0.05) +ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/wire3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/wire.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/wire.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -2,45 +2,89 @@ # art3d.py, original mplot3d version by John Porter # Parts rewritten by Reinier Heeres <re...@he...> -from matplotlib import lines, text, path as mpath +''' +Module containing 3D artist code and functions to convert 2D +artists into 3D versions which can be added to an Axes3D. +''' + +from matplotlib import lines, text as mtext, path as mpath, colors as mcolors from matplotlib.collections import Collection, LineCollection, \ PolyCollection, PatchCollection -from matplotlib.patches import Patch, Rectangle +from matplotlib.patches import Patch from matplotlib.colors import Normalize -from matplotlib import transforms +from matplotlib.cbook import iterable -import types import numpy as np +import math import proj3d -class Text3D(text.Text): +def norm_angle(a): + """Return angle between -180 and +180""" + a = (a + 360) % 360 + if a > 180: + a = a - 360 + return a - def __init__(self, x=0, y=0, z=0, text='', dir='z'): - text.Text.__init__(self, x, y, text) - self.set_3d_properties(z, dir) +def norm_text_angle(a): + """Return angle between -90 and +90""" + a = (a + 180) % 180 + if a > 90: + a = a - 180 + return a - def set_3d_properties(self, z=0, dir='z'): +def get_dir_vector(zdir): + if zdir == 'x': + return np.array((1, 0, 0)) + elif zdir == 'y': + return np.array((0, 1, 0)) + elif zdir == 'z': + return np.array((0, 0, 1)) + elif zdir == None: + return np.array((0, 0, 0)) + elif iterable(zdir) and len(zdir) == 3: + return zdir + else: + raise ValueError("'x', 'y', 'z', None or vector of length 3 expected") + +class Text3D(mtext.Text): + ''' + Text object with 3D position and (in the future) direction. + ''' + + def __init__(self, x=0, y=0, z=0, text='', zdir='z'): + mtext.Text.__init__(self, x, y, text) + self.set_3d_properties(z, zdir) + + def set_3d_properties(self, z=0, zdir='z'): x, y = self.get_position() - self._position3d = juggle_axes(x, y, z, dir) + self._position3d = np.array((x, y, z)) + self._dir_vec = get_dir_vector(zdir) def draw(self, renderer): - x, y, z = self._position3d - x, y, z = proj3d.proj_transform(x, y, z, renderer.M) - self.set_position(x, y) - text.Text.draw(self, renderer) + proj = proj3d.proj_trans_points([self._position3d, \ + self._position3d + self._dir_vec], renderer.M) + dx = proj[0][1] - proj[0][0] + dy = proj[1][1] - proj[1][0] + angle = math.degrees(math.atan2(dy, dx)) + self.set_position((proj[0][0], proj[1][0])) + self.set_rotation(norm_text_angle(angle)) + mtext.Text.draw(self, renderer) -def text_2d_to_3d(obj, z=0, dir='z'): +def text_2d_to_3d(obj, z=0, zdir='z'): """Convert a Text to a Text3D object.""" obj.__class__ = Text3D - obj.set_3d_properties(z, dir) + obj.set_3d_properties(z, zdir) class Line3D(lines.Line2D): + ''' + 3D line object. + ''' def __init__(self, xs, ys, zs, *args, **kwargs): lines.Line2D.__init__(self, [], [], *args, **kwargs) self._verts3d = xs, ys, zs - def set_3d_properties(self, zs=0, dir='z'): + def set_3d_properties(self, zs=0, zdir='z'): xs = self.get_xdata() ys = self.get_ydata() try: @@ -48,7 +92,7 @@ zs = [zs for x in xs] except: pass - self._verts3d = juggle_axes(xs, ys, zs, dir) + self._verts3d = juggle_axes(xs, ys, zs, zdir) def draw(self, renderer): xs3d, ys3d, zs3d = self._verts3d @@ -56,46 +100,58 @@ self.set_data(xs, ys) lines.Line2D.draw(self, renderer) -def line_2d_to_3d(line, z=0, dir='z'): +def line_2d_to_3d(line, zs=0, zdir='z'): + ''' + Convert a 2D line to 3D. + ''' line.__class__ = Line3D - line.set_3d_properties(z, dir) + line.set_3d_properties(zs, zdir) -def path_to_3d_segment(path, z=0, dir='z'): - '''Convert a path to a 3d segment.''' +def path_to_3d_segment(path, z=0, zdir='z'): + '''Convert a path to a 3D segment.''' seg = [] for (pathseg, code) in path.iter_segments(): seg.append(pathseg) - seg3d = [juggle_axes(x, y, z, dir) for (x, y) in seg] + seg3d = [juggle_axes(x, y, z, zdir) for (x, y) in seg] return seg3d -def paths_to_3d_segments(paths, zs=0, dir='z'): - '''Convert paths from a collection object to 3d segments.''' +def paths_to_3d_segments(paths, zs=0, zdir='z'): + '''Convert paths from a collection object to 3D segments.''' try: zs = float(zs) - zs = [zs for i in range(len(paths))] + zs = [zs] * len(paths) except: pass segments = [] for path, z in zip(paths, zs): - segments.append(path_to_3d_segment(path, z, dir)) + segments.append(path_to_3d_segment(path, z, zdir)) return segments class Line3DCollection(LineCollection): + ''' + A collection of 3D lines. + ''' def __init__(self, segments, *args, **kwargs): LineCollection.__init__(self, segments, *args, **kwargs) def set_segments(self, segments): + ''' + Set 3D segments + ''' self._segments3d = segments LineCollection.set_segments(self, []) def do_3d_projection(self, renderer): + ''' + Project the points according to renderer matrix. + ''' xyslist = [ proj3d.proj_trans_points(points, renderer.M) for points in self._segments3d] - segments_2d = [zip(xs,ys) for (xs,ys,zs) in xyslist] + segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist] LineCollection.set_segments(self, segments_2d) minz = 1e9 @@ -108,22 +164,28 @@ self.do_3d_projection(renderer) LineCollection.draw(self, renderer) -def line_collection_2d_to_3d(col, z=0, dir='z'): +def line_collection_2d_to_3d(col, zs=0, zdir='z'): """Convert a LineCollection to a Line3DCollection object.""" - segments3d = paths_to_3d_segments(col.get_paths(), z, dir) + segments3d = paths_to_3d_segments(col.get_paths(), zs, zdir) col.__class__ = Line3DCollection col.set_segments(segments3d) class Patch3D(Patch): + ''' + 3D patch object. + ''' def __init__(self, *args, **kwargs): zs = kwargs.pop('zs', []) - dir = kwargs.pop('dir', 'z') + zdir = kwargs.pop('zdir', 'z') Patch.__init__(self, *args, **kwargs) - self.set_3d_properties(zs, dir) + self.set_3d_properties(zs, zdir) - def set_3d_properties(self, verts, z=0, dir='z'): - self._segment3d = [juggle_axes(x, y, z, dir) for (x, y) in verts] + def set_3d_properties(self, verts, zs=0, zdir='z'): + if not iterable(zs): + zs = [zs] * len(verts) + self._segment3d = [juggle_axes(x, y, z, zdir) \ + for ((x, y), z) in zip(verts, zs)] self._facecolor3d = Patch.get_facecolor(self) def get_path(self): @@ -135,7 +197,7 @@ def do_3d_projection(self, renderer): s = self._segment3d xs, ys, zs = zip(*s) - vxs,vys,vzs,vis = proj3d.proj_transform_clip(xs,ys,zs, renderer.M) + vxs, vys,vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M) self._path2d = mpath.Path(zip(vxs, vys)) # FIXME: coloring self._facecolor2d = self._facecolor3d @@ -144,26 +206,29 @@ def draw(self, renderer): Patch.draw(self, renderer) -def patch_2d_to_3d(patch, z=0, dir='z'): +def patch_2d_to_3d(patch, z=0, zdir='z'): """Convert a Patch to a Patch3D object.""" verts = patch.get_verts() patch.__class__ = Patch3D - patch.set_3d_properties(verts, z, dir) + patch.set_3d_properties(verts, z, zdir) class Patch3DCollection(PatchCollection): + ''' + A collection of 3D patches. + ''' def __init__(self, *args, **kwargs): PatchCollection.__init__(self, *args, **kwargs) - def set_3d_properties(self, zs, dir): + def set_3d_properties(self, zs, zdir): xs, ys = zip(*self.get_offsets()) - self._offsets3d = juggle_axes(xs, ys, zs, dir) + self._offsets3d = juggle_axes(xs, ys, zs, zdir) self._facecolor3d = self.get_facecolor() self._edgecolor3d = self.get_edgecolor() def do_3d_projection(self, renderer): - xs,ys,zs = self._offsets3d - vxs,vys,vzs,vis = proj3d.proj_transform_clip(xs,ys,zs, renderer.M) + xs, ys, zs = self._offsets3d + vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M) #FIXME: mpl allows us no way to unset the collection alpha value self._alpha = None self.set_facecolors(zalpha(self._facecolor3d, vzs)) @@ -175,19 +240,22 @@ def draw(self, renderer): PatchCollection.draw(self, renderer) -def patch_collection_2d_to_3d(col, zs=0, dir='z'): +def patch_collection_2d_to_3d(col, zs=0, zdir='z'): """Convert a PatchCollection to a Patch3DCollection object.""" col.__class__ = Patch3DCollection - col.set_3d_properties(zs, dir) + col.set_3d_properties(zs, zdir) class Poly3DCollection(PolyCollection): + ''' + A collection of 3D polygons. + ''' def __init__(self, verts, *args, **kwargs): PolyCollection.__init__(self, verts, *args, **kwargs) self.set_3d_properties() def get_vector(self, segments3d): - """optimise points for projection""" + """Optimize points for projection""" si = 0 ei = 0 segis = [] @@ -195,11 +263,11 @@ for p in segments3d: points.extend(p) ei = si+len(p) - segis.append((si,ei)) + segis.append((si, ei)) si = ei - xs,ys,zs = zip(*points) + xs, ys, zs = zip(*points) ones = np.ones(len(xs)) - self._vec = np.array([xs,ys,zs,ones]) + self._vec = np.array([xs, ys, zs, ones]) self._segis = segis self._sort_zpos = min(zs) @@ -221,14 +289,14 @@ # if required sort by depth (furthest drawn first) if self._zsort: - z_segments_2d = [(min(zs),zip(xs,ys),c) for - (xs,ys,zs),c in zip(xyzlist,colors)] + z_segments_2d = [(min(zs), zip(xs, ys), c) for + (xs, ys, zs), c in zip(xyzlist, colors)] z_segments_2d.sort() z_segments_2d.reverse() else: raise ValueError, "whoops" - segments_2d = [s for z,s,c in z_segments_2d] - colors = [c for z,s,c in z_segments_2d] + segments_2d = [s for z, s, c in z_segments_2d] + colors = [c for z, s, c in z_segments_2d] PolyCollection.set_verts(self, segments_2d) self._facecolors2d = colors @@ -244,21 +312,23 @@ def draw(self, renderer): return Collection.draw(self, renderer) -def poly_collection_2d_to_3d(col, zs=None, dir='z'): +def poly_collection_2d_to_3d(col, zs=None, zdir='z'): """Convert a PolyCollection to a Poly3DCollection object.""" - segments_3d = paths_to_3d_segments(col.get_paths(), zs, dir) + segments_3d = paths_to_3d_segments(col.get_paths(), zs, zdir) col.__class__ = Poly3DCollection col.set_verts(segments_3d) col.set_3d_properties() -def juggle_axes(xs,ys,zs, dir): +def juggle_axes(xs, ys, zs, zdir): """ - Depending on the direction of the plot re-order the axis. - This is so that 2d plots can be plotted along any direction. + Reorder coordinates so that zdir """ - if dir == 'x': return zs,xs,ys - elif dir == 'y': return xs,zs,ys - else: return xs,ys,zs + if zdir == 'x': + return zs, xs, ys + elif zdir == 'y': + return xs, zs, ys + else: + return xs, ys, zs def iscolor(c): try: @@ -269,8 +339,8 @@ def get_colors(c, num): """Stretch the color argument to provide the required number num""" - if type(c)==type("string"): - c = colors.colorConverter.to_rgba(colors) + if type(c) == type("string"): + c = mcolors.colorConverter.to_rgba(c) if iscolor(c): return [c] * num @@ -285,9 +355,9 @@ def zalpha(colors, zs): """Modify the alphas of the color list according to depth""" - colors = get_colors(colors,len(zs)) - norm = Normalize(min(zs),max(zs)) - sats = 1 - norm(zs)*0.7 - colors = [(c[0],c[1],c[2],c[3]*s) for c,s in zip(colors,sats)] + colors = get_colors(colors, len(zs)) + norm = Normalize(min(zs), max(zs)) + sats = 1 - norm(zs) * 0.7 + colors = [(c[0], c[1], c[2], c[3] * s) for c, s in zip(colors, sats)] return colors Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -4,17 +4,14 @@ # Parts fixed by Reinier Heeres <re...@he...> """ -3D projection glued onto 2D Axes. - -Axes3D +Module containing Axes3D, an object which can plot 3D objects on a +2D matplotlib figure. """ -from matplotlib import pyplot as plt -import random - from matplotlib.axes import Axes from matplotlib import cbook from matplotlib.transforms import Bbox +from matplotlib import collections import numpy as np from matplotlib.colors import Normalize, colorConverter @@ -25,32 +22,23 @@ def sensible_format_data(self, value): """Used to generate more comprehensible numbers in status bar""" if abs(value) > 1e4 or abs(value)<1e-3: - s = '%1.4e'% value + s = '%1.4e' % value return self._formatSciNotation(s) else: return '%4.3f' % value def unit_bbox(): - box = Bbox(np.array([[0,0],[1,1]])) + box = Bbox(np.array([[0, 0], [1, 1]])) return box -class Axes3DI(Axes): - """Wrap an Axes object - - The x,y data coordinates, which are manipulated by set_xlim and - set_ylim are used as the target view coordinates by the 3D - transformations. These coordinates are mostly invisible to the - outside world. - - set_w_xlim, set_w_ylim and set_w_zlim manipulate the 3D world - coordinates which are scaled to represent the data and are stored - in the xy_dataLim, zz_datalim bboxes. - - The axes representing the x,y,z world dimensions are self.w_xaxis, - self.w_yaxis and self.w_zaxis. They can probably be controlled in - more or less the normal ways. +class Axes3D(Axes): """ - def __init__(self, fig, rect=[0.0, 0.0, 1.0, 1.0], *args, **kwargs): + 3D axes object. + """ + + def __init__(self, fig, rect=None, *args, **kwargs): + if rect is None: + rect = [0.0, 0.0, 1.0, 1.0] self.fig = fig self.cids = [] @@ -87,71 +75,47 @@ ydwl = (0.95/self.dist) ydw = (0.9/self.dist) - self.set_xlim(-xdwl,xdw) - self.set_ylim(-ydwl,ydw) + Axes.set_xlim(self, -xdwl, xdw) + Axes.set_ylim(self, -ydwl, ydw) - def really_set_xlim(self, vmin, vmax): - self.viewLim.intervalx().set_bounds(vmin, vmax) - - def really_set_ylim(self, vmin, vmax): - self.viewLim.intervaly().set_bounds(vmin, vmax) - - def vlim_argument(self, get_lim, *args): - if not args: - vmin,vmax = get_lim() - elif len(args)==2: - vmin,vmax = args - elif len(args)==1: - vmin,vmax = args[0] - return vmin,vmax - - def nset_xlim(self, *args): - raise - vmin,vmax = self.vlim_argument(self.get_xlim) - print 'xlim', vmin,vmax - - def nset_ylim(self, *args): - vmin,vmax = self.vlim_argument(self.get_ylim) - print 'ylim', vmin,vmax - def create_axes(self): - self.w_xaxis = axis3d.XAxis('x',self.xy_viewLim.intervalx, + self.w_xaxis = axis3d.XAxis('x', self.xy_viewLim.intervalx, self.xy_dataLim.intervalx, self) - self.w_yaxis = axis3d.YAxis('y',self.xy_viewLim.intervaly, + self.w_yaxis = axis3d.YAxis('y', self.xy_viewLim.intervaly, self.xy_dataLim.intervaly, self) - self.w_zaxis = axis3d.ZAxis('z',self.zz_viewLim.intervalx, + self.w_zaxis = axis3d.ZAxis('z', self.zz_viewLim.intervalx, self.zz_dataLim.intervalx, 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], - [miny,miny,maxy,maxy,miny,miny,maxy,maxy], - [minz,minz,minz,minz,maxz,maxz,maxz,maxz]) - return zip(xs,ys,zs) + 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], + [miny, miny, maxy, maxy, miny, miny, maxy, maxy], + [minz, minz, minz, minz, maxz, maxz, maxz, maxz]) + return zip(xs, ys, zs) - def tunit_cube(self,vals=None,M=None): + def tunit_cube(self, vals=None, M=None): if M is None: M = self.M xyzs = self.unit_cube(vals) - tcube = proj3d.proj_points(xyzs,M) + tcube = proj3d.proj_points(xyzs, M) return tcube - def tunit_edges(self, vals=None,M=None): - tc = self.tunit_cube(vals,M) - edges = [(tc[0],tc[1]), - (tc[1],tc[2]), - (tc[2],tc[3]), - (tc[3],tc[0]), + def tunit_edges(self, vals=None, M=None): + tc = self.tunit_cube(vals, M) + edges = [(tc[0], tc[1]), + (tc[1], tc[2]), + (tc[2], tc[3]), + (tc[3], tc[0]), - (tc[0],tc[4]), - (tc[1],tc[5]), - (tc[2],tc[6]), - (tc[3],tc[7]), + (tc[0], tc[4]), + (tc[1], tc[5]), + (tc[2], tc[6]), + (tc[3], tc[7]), - (tc[4],tc[5]), - (tc[5],tc[6]), - (tc[6],tc[7]), - (tc[7],tc[4])] + (tc[4], tc[5]), + (tc[5], tc[6]), + (tc[6], tc[7]), + (tc[7], tc[4])] return edges def draw(self, renderer): @@ -189,22 +153,19 @@ def get_axis_position(self): vals = self.get_w_lims() - tc = self.tunit_cube(vals,self.M) - xhigh = tc[1][2]>tc[2][2] - yhigh = tc[3][2]>tc[2][2] - zhigh = tc[0][2]>tc[2][2] - return xhigh,yhigh,zhigh + tc = self.tunit_cube(vals, self.M) + xhigh = tc[1][2] > tc[2][2] + yhigh = tc[3][2] > tc[2][2] + zhigh = tc[0][2] > tc[2][2] + return xhigh, yhigh, zhigh def update_datalim(self, xys, **kwargs): pass - def update_datalim_numerix(self, x, y): - pass - - def auto_scale_xyz(self, X,Y,Z=None,had_data=None): - x,y,z = map(np.asarray, (X,Y,Z)) + def auto_scale_xyz(self, X, Y, Z=None, had_data=None): + x, y, z = map(np.asarray, (X, Y, Z)) try: - x,y = x.flatten(),y.flatten() + x, y = x.flatten(), y.flatten() if Z is not None: z = z.flatten() except AttributeError: @@ -225,55 +186,63 @@ # of data and decides how to scale the view portal to fit it. self.set_top_view() - if not self._ready: return + if not self._ready: + return - if not self.get_autoscale_on(): return + if not self.get_autoscale_on(): + return if scalex: - self.set_w_xlim(self.xy_dataLim.intervalx) + self.set_xlim3d(self.xy_dataLim.intervalx) if scaley: - self.set_w_ylim(self.xy_dataLim.intervaly) + self.set_ylim3d(self.xy_dataLim.intervaly) if scalez: - self.set_w_zlim(self.zz_dataLim.intervalx) + self.set_zlim3d(self.zz_dataLim.intervalx) def get_w_lims(self): '''Get 3d world limits.''' - minpy,maxx = self.get_w_xlim() - miny,maxy = self.get_w_ylim() - minz,maxz = self.get_w_zlim() - return minpy,maxx,miny,maxy,minz,maxz + minpy, maxx = self.get_xlim3d() + miny, maxy = self.get_ylim3d() + minz, maxz = self.get_zlim3d() + return minpy, maxx, miny, maxy, minz, maxz def _determine_lims(self, xmin=None, xmax=None, *args, **kwargs): if xmax is None and cbook.iterable(xmin): xmin, xmax = xmin return (xmin, xmax) - def set_w_zlim(self, *args, **kwargs): - '''Set 3d z limits.''' + def set_xlim3d(self, *args, **kwargs): + '''Set 3D x limits.''' lims = self._determine_lims(*args, **kwargs) - self.zz_viewLim.intervalx = lims + self.xy_viewLim.intervalx = lims return lims - def set_w_xlim(self, *args, **kwargs): - '''Set 3d x limits.''' + def set_ylim3d(self, *args, **kwargs): + '''Set 3D y limits.''' lims = self._determine_lims(*args, **kwargs) - self.xy_viewLim.intervalx = lims + self.xy_viewLim.intervaly = lims return lims - def set_w_ylim(self, *args, **kwargs): - '''Set 3d y limits.''' + def set_zlim3d(self, *args, **kwargs): + '''Set 3D z limits.''' lims = self._determine_lims(*args, **kwargs) - self.xy_viewLim.intervaly = lims + self.zz_viewLim.intervalx = lims return lims - def get_w_zlim(self): - return self.zz_viewLim.intervalx - - def get_w_xlim(self): + def get_xlim3d(self): + '''Get 3D x limits.''' return self.xy_viewLim.intervalx - def get_w_ylim(self): + def get_ylim3d(self): + '''Get 3D y limits.''' return self.xy_viewLim.intervaly + def get_zlim3d(self): + '''Get 3D z limits.''' + return self.zz_viewLim.intervalx + + def clabel(self, *args, **kwargs): + return None + def pany(self, numsteps): print 'numsteps', numsteps @@ -296,23 +265,23 @@ point. """ - relev,razim = np.pi * self.elev/180, np.pi * self.azim/180 + relev, razim = np.pi * self.elev/180, np.pi * self.azim/180 - xmin,xmax = self.get_w_xlim() - ymin,ymax = self.get_w_ylim() - zmin,zmax = self.get_w_zlim() + xmin, xmax = self.get_xlim3d() + ymin, ymax = self.get_ylim3d() + zmin, zmax = self.get_zlim3d() # transform to uniform world coordinates 0-1.0,0-1.0,0-1.0 - worldM = proj3d.world_transformation(xmin,xmax, - ymin,ymax, - zmin,zmax) + worldM = proj3d.world_transformation(xmin, xmax, + ymin, ymax, + zmin, zmax) # look into the middle of the new coordinates - R = np.array([0.5,0.5,0.5]) + R = np.array([0.5, 0.5, 0.5]) - xp = R[0] + np.cos(razim)*np.cos(relev)*self.dist - yp = R[1] + np.sin(razim)*np.cos(relev)*self.dist - zp = R[2] + np.sin(relev)*self.dist + xp = R[0] + np.cos(razim) * np.cos(relev) * self.dist + yp = R[1] + np.sin(razim) * np.cos(relev) * self.dist + zp = R[2] + np.sin(relev) * self.dist E = np.array((xp, yp, zp)) self.eye = E @@ -321,24 +290,24 @@ if abs(relev) > np.pi/2: # upside down - V = np.array((0,0,-1)) + V = np.array((0, 0, -1)) else: - V = np.array((0,0,1)) - zfront,zback = -self.dist,self.dist + V = np.array((0, 0, 1)) + zfront, zback = -self.dist, self.dist - viewM = proj3d.view_transformation(E,R,V) - perspM = proj3d.persp_transformation(zfront,zback) - M0 = np.dot(viewM,worldM) - M = np.dot(perspM,M0) + viewM = proj3d.view_transformation(E, R, V) + perspM = proj3d.persp_transformation(zfront, zback) + M0 = np.dot(viewM, worldM) + M = np.dot(perspM, M0) return M def mouse_init(self): self.button_pressed = None canv = self.figure.canvas if canv != None: - c1 = canv.mpl_connect('motion_notify_event', self.on_move) - c2 = canv.mpl_connect('button_press_event', self.button_press) - c3 = canv.mpl_connect('button_release_event', self.button_release) + c1 = canv.mpl_connect('motion_notify_event', self._on_move) + c2 = canv.mpl_connect('button_press_event', self._button_press) + c3 = canv.mpl_connect('button_release_event', self._button_release) self.cids = [c1, c2, c3] def cla(self): @@ -348,11 +317,11 @@ self.cids = [] Axes.cla(self) - def button_press(self, event): + def _button_press(self, event): self.button_pressed = event.button - self.sx,self.sy = event.xdata,event.ydata + self.sx, self.sy = event.xdata, event.ydata - def button_release(self, event): + def _button_release(self, event): self.button_pressed = None def format_xdata(self, x): @@ -361,10 +330,11 @@ self.fmt_xdata if it is callable, else will fall back on the xaxis major formatter """ - try: return self.fmt_xdata(x) + try: + return self.fmt_xdata(x) except TypeError: fmt = self.w_xaxis.get_major_formatter() - return sensible_format_data(fmt,x) + return sensible_format_data(fmt, x) def format_ydata(self, y): """ @@ -372,28 +342,30 @@ self.fmt_ydata if it is callable, else will fall back on the yaxis major formatter """ - try: return self.fmt_ydata(y) + try: + return self.fmt_ydata(y) except TypeError: fmt = self.w_yaxis.get_major_formatter() - return sensible_format_data(fmt,y) + return sensible_format_data(fmt, y) def format_zdata(self, z): """ - Return y string formatted. This function will use the attribute - self.fmt_ydata if it is callable, else will fall back on the yaxis + Return z string formatted. This function will use the attribute + self.fmt_zdata if it is callable, else will fall back on the yaxis major formatter """ - try: return self.fmt_zdata(z) - except (AttributeError,TypeError): + try: + return self.fmt_zdata(z) + except (AttributeError, TypeError): fmt = self.w_zaxis.get_major_formatter() - return sensible_format_data(fmt,z) + return sensible_format_data(fmt, z) def format_coord(self, xd, yd): - """Given the 2D view coordinates attempt to guess a 3D coordinate - - Looks for the nearest edge to the point and then assumes that the point is - at the same z location as the nearest point on the edge. """ + Given the 2D view coordinates attempt to guess a 3D coordinate. + Looks for the nearest edge to the point and then assumes that + the point is at the same z location as the nearest point on the edge. + """ if self.M is None: return '' @@ -402,32 +374,33 @@ return 'azimuth=%d deg, elevation=%d deg ' % (self.azim, self.elev) # ignore xd and yd and display angles instead - p = (xd,yd) + p = (xd, yd) edges = self.tunit_edges() #lines = [proj3d.line2d(p0,p1) for (p0,p1) in edges] - ldists = [(proj3d.line2d_seg_dist(p0,p1,p),i) for i,(p0,p1) in enumerate(edges)] + ldists = [(proj3d.line2d_seg_dist(p0, p1, p), i) for \ + i, (p0, p1) in enumerate(edges)] ldists.sort() # nearest edge edgei = ldists[0][1] - p0,p1 = edges[edgei] + p0, p1 = edges[edgei] # scale the z value to match - x0,y0,z0 = p0 - x1,y1,z1 = p1 - d0 = np.hypot(x0-xd,y0-yd) - d1 = np.hypot(x1-xd,y1-yd) + x0, y0, z0 = p0 + x1, y1, z1 = p1 + d0 = np.hypot(x0-xd, y0-yd) + d1 = np.hypot(x1-xd, y1-yd) dt = d0+d1 z = d1/dt * z0 + d0/dt * z1 - x,y,z = proj3d.inv_transform(xd,yd,z,self.M) + x, y, z = proj3d.inv_transform(xd, yd, z, self.M) xs = self.format_xdata(x) ys = self.format_ydata(y) zs = self.format_ydata(z) - return 'x=%s, y=%s, z=%s'%(xs,ys,zs) + return 'x=%s, y=%s, z=%s' % (xs, ys, zs) - def on_move(self, event): + def _on_move(self, event): """Mouse moving button-1 rotates @@ -438,27 +411,26 @@ if self.M is None: return - # this shouldn't be called before the graph has been drawn for the first time! + x, y = event.xdata, event.ydata - # In case the mouse is out of bounds. if x == None: - return - dx,dy = x-self.sx,y-self.sy - x0,x1 = self.get_xlim() - y0,y1 = self.get_ylim() + + dx, dy = x - self.sx, y - self.sy + x0, x1 = self.get_xlim() + y0, y1 = self.get_ylim() w = (x1-x0) h = (y1-y0) - self.sx,self.sy = x,y + self.sx, self.sy = x, y if self.button_pressed == 1: # rotate viewing point # get the x and y pixel coords if dx == 0 and dy == 0: return - self.elev = axis3d.norm_angle(self.elev - (dy/h)*180) - self.azim = axis3d.norm_angle(self.azim - (dx/w)*180) + self.elev = art3d.norm_angle(self.elev - (dy/h)*180) + self.azim = art3d.norm_angle(self.azim - (dx/w)*180) self.get_proj() self.figure.canvas.draw() elif self.button_pressed == 2: @@ -469,73 +441,122 @@ elif self.button_pressed == 3: # zoom view # hmmm..this needs some help from clipping.... - minpy,maxx,miny,maxy,minz,maxz = self.get_w_lims() + minpy, maxx, miny, maxy, minz, maxz = self.get_w_lims() df = 1-((h - dy)/h) dx = (maxx-minpy)*df dy = (maxy-miny)*df dz = (maxz-minz)*df - self.set_w_xlim(minpy-dx,maxx+dx) - self.set_w_ylim(miny-dy,maxy+dy) - self.set_w_zlim(minz-dz,maxz+dz) + self.set_xlim3d(minpy - dx, maxx + dx) + self.set_ylim3d(miny - dy, maxy + dy) + self.set_zlim3d(minz - dz, maxz + dz) self.get_proj() self.figure.canvas.draw() def set_xlabel(self, xlabel, fontdict=None, **kwargs): - #par = cbook.popd(kwargs, 'par',None) - #label.set_par(par) + '''Set xlabel. ''' label = self.w_xaxis.get_label() label.set_text(xlabel) - if fontdict is not None: label.update(fontdict) + if fontdict is not None: + label.update(fontdict) label.update(kwargs) return label def set_ylabel(self, ylabel, fontdict=None, **kwargs): + '''Set ylabel.''' + label = self.w_yaxis.get_label() label.set_text(ylabel) - if fontdict is not None: label.update(fontdict) + if fontdict is not None: + label.update(fontdict) label.update(kwargs) return label def set_zlabel(self, zlabel, fontdict=None, **kwargs): + '''Set zlabel.''' + label = self.w_zaxis.get_label() label.set_text(zlabel) - if fontdict is not None: label.update(fontdict) + if fontdict is not None: + label.update(fontdict) label.update(kwargs) return label - def plot(self, *args, **kwargs): + def text(self, x, y, z, s, zdir=None): + '''Add text to the plot.''' + text = Axes.text(self, x, y, s) + art3d.text_2d_to_3d(text, z, zdir) + return text + + text3D = text + + def plot(self, xs, ys, *args, **kwargs): + ''' + Plot 2D or 3D data. + + ========== ================================================ + Argument Description + ========== ================================================ + *xs*, *ys* X, y coordinates of vertices + + *zs* z value(s), either one for all points or one for + each point. + *zdir* Which direction to use as z ('x', 'y' or 'z') + when plotting a 2d set. + ========== ================================================ + + Other arguments are passed on to + :func:`~matplotlib.axes.Axes.plot` + ''' + had_data = self.has_data() + zs = kwargs.pop('zs', 0) + zdir = kwargs.pop('zdir', 'z') - zval = kwargs.pop( 'z', 0) - zdir = kwargs.pop('dir', 'z') - lines = Axes.plot(self, *args, **kwargs) + argsi = 0 + # First argument is array of zs + if len(args) > 0 and cbook.iterable(args[0]) and \ + len(xs) == len(args[0]) and cbook.is_scalar(args[0][0]): + zs = args[argsi] + argsi += 1 + + # First argument is z value + elif len(args) > 0 and cbook.is_scalar(args[0]): + zs = args[argsi] + argsi += 1 + + # Match length + if not cbook.iterable(zs): + zs = [zs] * len(xs) + + lines = Axes.plot(self, xs, ys, *args[argsi:], **kwargs) for line in lines: - art3d.line_2d_to_3d(line, z=zval, dir=zdir) + art3d.line_2d_to_3d(line, zs=zs, zdir=zdir) - xs = lines[0].get_xdata() - ys = lines[0].get_ydata() - zs = [zval for x in xs] - xs,ys,zs = art3d.juggle_axes(xs,ys,zs,zdir) - self.auto_scale_xyz(xs,ys,zs, had_data) + self.auto_scale_xyz(xs, ys, zs, had_data) return lines - def plot3D(self, xs, ys, zs, *args, **kwargs): - had_data = self.has_data() - lines = Axes.plot(self, xs,ys, *args, **kwargs) - if len(lines)==1: - line = lines[0] - art3d.line_2d_to_3d(line, zs) - self.auto_scale_xyz(xs,ys,zs, had_data) - return lines + plot3D = plot - plot3d=plot3D - def plot_surface(self, X, Y, Z, *args, **kwargs): + ''' + Create a surface plot. + + ========== ================================================ + 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 + ========== ================================================ + ''' + had_data = self.has_data() rows, cols = Z.shape - tX,tY,tZ = np.transpose(X), np.transpose(Y), np.transpose(Z) + tX, tY, tZ = np.transpose(X), np.transpose(Y), np.transpose(Z) rstride = kwargs.pop('rstride', 10) cstride = kwargs.pop('cstride', 10) @@ -544,21 +565,21 @@ polys = [] boxes = [] - for rs in np.arange(0,rows-1,rstride): - for cs in np.arange(0,cols-1,cstride): + 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):] + 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 = 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)) + corners.append([ztop[0], ztop[-1], zbase[0], zbase[-1]]) + z = np.concatenate((ztop, zleft, zbase, zright)) ps.append(z) - boxes.append(map(np.array,zip(*corners))) + boxes.append(map(np.array, zip(*corners))) polys.append(zip(*ps)) lines = [] @@ -567,8 +588,8 @@ n = proj3d.cross(box[0]-box[1], box[0]-box[2]) n = n/proj3d.mod(n)*5 - shade.append(np.dot(n,[-1,-1,0.5])) - lines.append((box[0],n+box[0])) + shade.append(np.d... [truncated message content] |