From b20732052e07fc6917009fb6796bd4362a6a27e2 Mon Sep 17 00:00:00 2001 From: Trish Gillett-Kawamoto Date: Sat, 2 Apr 2016 16:42:31 -0400 Subject: [PATCH 1/7] Cleaning up example mplot3d/2dcollections3d_demo. --- examples/mplot3d/2dcollections3d_demo.py | 27 ++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/examples/mplot3d/2dcollections3d_demo.py b/examples/mplot3d/2dcollections3d_demo.py index 099fce832076..107f0479087d 100644 --- a/examples/mplot3d/2dcollections3d_demo.py +++ b/examples/mplot3d/2dcollections3d_demo.py @@ -1,3 +1,8 @@ +''' +Demonstrates using ax.plot's zdir keyword to plot 2D scatterplot data on +selective axes of a 3D plot. +''' + from mpl_toolkits.mplot3d import Axes3D import numpy as np import matplotlib.pyplot as plt @@ -5,19 +10,33 @@ fig = plt.figure() ax = fig.gca(projection='3d') +# Plot a sin curve using the x and y axes. 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') +ax.plot(x, y, zs=0, zdir='z', label='curve in (x,y)') +# Plot scatterplot data (20 2D points per colour) on the x and z axes. colors = ('r', 'g', 'b', 'k') +x = np.random.sample(20*len(colors)) +y = np.random.sample(20*len(colors)) +c_list = [] for c in colors: - x = np.random.sample(20) - y = np.random.sample(20) - ax.scatter(x, y, 0, zdir='y', c=c) + c_list.append([c]*20) +# By using zdir='y', the y value of these points is fixed to the zs value 0 +# and the (x,y) points are plotted on the x and z axes. +ax.scatter(x, y, zs=0, zdir='y', c=c_list, label='points in (x,z)') +# Make legend, set axes limits and labels ax.legend() ax.set_xlim3d(0, 1) ax.set_ylim3d(0, 1) ax.set_zlim3d(0, 1) +ax.set_xlabel('X') +ax.set_ylabel('Y') +ax.set_zlabel('Z') + +# Customize the view angle so it's easier to see that the scatter points lie +# on the plane y=0 +ax.view_init(elev=20., azim=-35) plt.show() From e1ff0bbede2e643e037a869ffaf855c239f273f3 Mon Sep 17 00:00:00 2001 From: Trish Gillett-Kawamoto Date: Sat, 2 Apr 2016 17:58:55 -0400 Subject: [PATCH 2/7] Cleaning up example mplot3d/bars3d_demo --- examples/mplot3d/bars3d_demo.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/examples/mplot3d/bars3d_demo.py b/examples/mplot3d/bars3d_demo.py index d378af98b51d..90bd58c6c9fa 100644 --- a/examples/mplot3d/bars3d_demo.py +++ b/examples/mplot3d/bars3d_demo.py @@ -1,21 +1,35 @@ +''' +Demonstrates making a 3D plot which has 2D bar graphs projected onto +planes y=0, y=1, etc. +''' + from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np fig = plt.figure() ax = fig.add_subplot(111, projection='3d') -for c, z in zip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]): + +colors = ['r', 'g', 'b', 'y'] +yticks = [3, 2, 1, 0] +for c, k in zip(colors, yticks): + # Generate the random data for the y=k 'layer'. xs = np.arange(20) ys = np.random.rand(20) - # You can provide either a single color or an array. To demonstrate this, - # the first bar of each set will be colored cyan. + # You can provide either a single color or an array with the same length as + # xs and ys. To demonstrate this, we color the first bar of each set cyan. cs = [c] * len(xs) cs[0] = 'c' - ax.bar(xs, ys, zs=z, zdir='y', color=cs, alpha=0.8) + + # Plot the bar graph given by xs and ys on the plane y=k with 80% opacity. + ax.bar(xs, ys, zs=k, zdir='y', color=cs, alpha=0.8) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') +# On the y axis let's only label the discrete values that we have data for. +ax.set_yticks(yticks) + plt.show() From dcc0d7cc3e8b8185398f2db640c6eec8bc3b6fce Mon Sep 17 00:00:00 2001 From: Trish Gillett-Kawamoto Date: Sun, 3 Apr 2016 10:57:26 -0400 Subject: [PATCH 3/7] Cleaning up example mplot3d/lorenz_attractor.py. --- examples/mplot3d/lorenz_attractor.py | 42 ++++++++++++++++++---------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/examples/mplot3d/lorenz_attractor.py b/examples/mplot3d/lorenz_attractor.py index 976eee902687..9fceb0af149d 100644 --- a/examples/mplot3d/lorenz_attractor.py +++ b/examples/mplot3d/lorenz_attractor.py @@ -1,10 +1,12 @@ -# Plot of the Lorenz Attractor based on Edward Lorenz's 1963 "Deterministic -# Nonperiodic Flow" publication. -# http://journals.ametsoc.org/doi/abs/10.1175/1520-0469%281963%29020%3C0130%3ADNF%3E2.0.CO%3B2 -# -# Note: Because this is a simple non-linear ODE, it would be more easily -# done using SciPy's ode solver, but this approach depends only -# upon NumPy. +''' +Plot of the Lorenz Attractor based on Edward Lorenz's 1963 "Deterministic +Nonperiodic Flow" publication. +http://journals.ametsoc.org/doi/abs/10.1175/1520-0469%281963%29020%3C0130%3ADNF%3E2.0.CO%3B2 + +Note: Because this is a simple non-linear ODE, it would be more easily + done using SciPy's ode solver, but this approach depends only + upon NumPy. +''' import numpy as np import matplotlib.pyplot as plt @@ -12,6 +14,14 @@ def lorenz(x, y, z, s=10, r=28, b=2.667): + ''' + Given: + x, y, z: a point of interest in three dimensional space + s, r, b: parameters defining the lorenz attractor + Returns: + x_dot, y_dot, z_dot: values of the lorenz attractor's partial + derivatives at the point x, y, z + ''' x_dot = s*(y - x) y_dot = r*x - y - x*z z_dot = x*y - b*z @@ -19,24 +29,26 @@ def lorenz(x, y, z, s=10, r=28, b=2.667): dt = 0.01 -stepCnt = 10000 +num_steps = 10000 # Need one more for the initial values -xs = np.empty((stepCnt + 1,)) -ys = np.empty((stepCnt + 1,)) -zs = np.empty((stepCnt + 1,)) +xs = np.empty((num_steps + 1,)) +ys = np.empty((num_steps + 1,)) +zs = np.empty((num_steps + 1,)) -# Setting initial values +# Set initial values xs[0], ys[0], zs[0] = (0., 1., 1.05) -# Stepping through "time". -for i in range(stepCnt): - # Derivatives of the X, Y, Z state +# Step through "time", calculating the partial derivatives at the current point +# and using them to estimate the next point +for i in range(num_steps): x_dot, y_dot, z_dot = lorenz(xs[i], ys[i], zs[i]) xs[i + 1] = xs[i] + (x_dot * dt) ys[i + 1] = ys[i] + (y_dot * dt) zs[i + 1] = zs[i] + (z_dot * dt) + +# Plot fig = plt.figure() ax = fig.gca(projection='3d') From ac0edb8fea34efc9e664c48ab279e1f67c4556cc Mon Sep 17 00:00:00 2001 From: Trish Gillett-Kawamoto Date: Mon, 4 Apr 2016 12:22:45 -0400 Subject: [PATCH 4/7] Comments and cosmetic changes to mplot3d examples: custom_shaded_3d_surface, lines3d_demo, offset_demo --- examples/mplot3d/custom_shaded_3d_surface.py | 3 ++ examples/mplot3d/lines3d_demo.py | 7 +++++ examples/mplot3d/offset_demo.py | 29 ++++++++++++-------- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/examples/mplot3d/custom_shaded_3d_surface.py b/examples/mplot3d/custom_shaded_3d_surface.py index 4bfff3ca6633..dc35b235a161 100644 --- a/examples/mplot3d/custom_shaded_3d_surface.py +++ b/examples/mplot3d/custom_shaded_3d_surface.py @@ -1,6 +1,7 @@ """ Demonstrates using custom hillshading in a 3D surface plot. """ + from mpl_toolkits.mplot3d import Axes3D from matplotlib import cbook from matplotlib import cm @@ -8,6 +9,7 @@ import matplotlib.pyplot as plt import numpy as np +# Load and format data filename = cbook.get_sample_data('jacksboro_fault_dem.npz', asfileobj=False) with np.load(filename) as dem: z = dem['elevation'] @@ -19,6 +21,7 @@ region = np.s_[5:50, 5:50] x, y, z = x[region], y[region], z[region] +# Set up plot fig, ax = plt.subplots(subplot_kw=dict(projection='3d')) ls = LightSource(270, 45) diff --git a/examples/mplot3d/lines3d_demo.py b/examples/mplot3d/lines3d_demo.py index cc349bda2230..8e73a301b39c 100644 --- a/examples/mplot3d/lines3d_demo.py +++ b/examples/mplot3d/lines3d_demo.py @@ -1,3 +1,7 @@ +''' +Demonstrating plotting a parametric curve in 3D. +''' + import matplotlib as mpl from mpl_toolkits.mplot3d import Axes3D import numpy as np @@ -7,11 +11,14 @@ fig = plt.figure() ax = fig.gca(projection='3d') + +# Prepare arrays x, y, z 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() diff --git a/examples/mplot3d/offset_demo.py b/examples/mplot3d/offset_demo.py index 7b80ff2864a6..c4f6d35e021a 100644 --- a/examples/mplot3d/offset_demo.py +++ b/examples/mplot3d/offset_demo.py @@ -1,25 +1,30 @@ +''' +This example demonstrates mplot3d's offset text display. +As one rotates the 3D figure, the offsets should remain oriented the +same way as the axis label, and should also be located "away" +from the center of the plot. + +This demo triggers the display of the offset text for the x and +y axis by adding 1e5 to X and Y. Anything less would not +automatically trigger it. +''' + from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np -# This example demonstrates mplot3d's offset text display. -# As one rotates the 3D figure, the offsets should remain oriented -# same way as the axis label, and should also be located "away" -# from the center of the plot. -# -# This demo triggers the display of the offset text for the x and -# y axis by adding 1e5 to X and Y. Anything less would not -# automatically trigger it. fig = plt.figure() ax = fig.gca(projection='3d') + X, Y = np.mgrid[0:6*np.pi:0.25, 0:4*np.pi:0.25] Z = np.sqrt(np.abs(np.cos(X) + np.cos(Y))) -surf = ax.plot_surface(X + 1e5, Y + 1e5, Z, cmap='autumn', cstride=2, rstride=2) -ax.set_xlabel("X-Label") -ax.set_ylabel("Y-Label") -ax.set_zlabel("Z-Label") +ax.plot_surface(X + 1e5, Y + 1e5, Z, cmap='autumn', cstride=2, rstride=2) + +ax.set_xlabel("X label") +ax.set_ylabel("Y label") +ax.set_zlabel("Z label") ax.set_zlim(0, 2) plt.show() From 35ea0fdff0eae85496ae134f418a336b10547ad3 Mon Sep 17 00:00:00 2001 From: Trish Gillett-Kawamoto Date: Thu, 14 Apr 2016 12:20:13 -0400 Subject: [PATCH 5/7] Document contour3d and contourf3d examples --- examples/mplot3d/contour3d_demo.py | 12 +++++++++++- examples/mplot3d/contour3d_demo2.py | 9 +++++++++ examples/mplot3d/contour3d_demo3.py | 20 +++++++++++++++++--- examples/mplot3d/contourf3d_demo.py | 10 ++++++++++ examples/mplot3d/contourf3d_demo2.py | 23 ++++++++++++++++------- 5 files changed, 63 insertions(+), 11 deletions(-) diff --git a/examples/mplot3d/contour3d_demo.py b/examples/mplot3d/contour3d_demo.py index 6c3fba8ce6b6..d41f8e8bc937 100644 --- a/examples/mplot3d/contour3d_demo.py +++ b/examples/mplot3d/contour3d_demo.py @@ -1,11 +1,21 @@ +''' +Demonstrates plotting contour (level) curves in 3D. + +This is like a contour plot in 2D except that the f(x,y)=c curve is plotted +on the plane z=c. +''' + from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt from matplotlib import cm fig = plt.figure() -ax = fig.add_subplot(111, projection='3d') +ax = fig.gca(projection='3d') X, Y, Z = axes3d.get_test_data(0.05) + +# Plot contour curves cset = ax.contour(X, Y, Z, cmap=cm.coolwarm) + ax.clabel(cset, fontsize=9, inline=1) plt.show() diff --git a/examples/mplot3d/contour3d_demo2.py b/examples/mplot3d/contour3d_demo2.py index 64e053cbb64b..e1f408294e3c 100644 --- a/examples/mplot3d/contour3d_demo2.py +++ b/examples/mplot3d/contour3d_demo2.py @@ -1,3 +1,10 @@ +''' +Demonstrates plotting contour (level) curves in 3D using the extend3d option. + +This modification of the contour3d_demo example uses extend3d=True to +extend the curves vertically into 'ribbons'. +''' + from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt from matplotlib import cm @@ -5,7 +12,9 @@ fig = plt.figure() ax = fig.gca(projection='3d') X, Y, Z = axes3d.get_test_data(0.05) + cset = ax.contour(X, Y, Z, extend3d=True, cmap=cm.coolwarm) + ax.clabel(cset, fontsize=9, inline=1) plt.show() diff --git a/examples/mplot3d/contour3d_demo3.py b/examples/mplot3d/contour3d_demo3.py index f0b2fbf23f2a..ed2474400bd8 100644 --- a/examples/mplot3d/contour3d_demo3.py +++ b/examples/mplot3d/contour3d_demo3.py @@ -1,3 +1,10 @@ +''' +Demonstrates displaying a 3D surface while also projecting contour 'profiles' +onto the 'walls' of the graph. + +See contourf3d_demo2 for the filled version. +''' + from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt from matplotlib import cm @@ -5,16 +12,23 @@ fig = plt.figure() ax = fig.gca(projection='3d') X, Y, Z = axes3d.get_test_data(0.05) + +# Plot the 3D surface ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3) + +# Plot projections of the contours for each dimension. By choosing offsets +# that match the appropriate axes limits, the projected contours will sit on +# the 'walls' of the graph cset = ax.contour(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm) cset = ax.contour(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm) cset = ax.contour(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm) -ax.set_xlabel('X') ax.set_xlim(-40, 40) -ax.set_ylabel('Y') ax.set_ylim(-40, 40) -ax.set_zlabel('Z') ax.set_zlim(-100, 100) +ax.set_xlabel('X') +ax.set_ylabel('Y') +ax.set_zlabel('Z') + plt.show() diff --git a/examples/mplot3d/contourf3d_demo.py b/examples/mplot3d/contourf3d_demo.py index 4811ecd72360..fc1178b9ff69 100644 --- a/examples/mplot3d/contourf3d_demo.py +++ b/examples/mplot3d/contourf3d_demo.py @@ -1,3 +1,11 @@ +''' +contourf differs from contour in that it creates filled contours, ie. +a discrete number of colours are used to shade the domain. + +This is like a contourf plot in 2D except that the shaded region corresponding +to the level c is graphed on the plane z=c. +''' + from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt from matplotlib import cm @@ -5,7 +13,9 @@ fig = plt.figure() ax = fig.gca(projection='3d') X, Y, Z = axes3d.get_test_data(0.05) + cset = ax.contourf(X, Y, Z, cmap=cm.coolwarm) + ax.clabel(cset, fontsize=9, inline=1) plt.show() diff --git a/examples/mplot3d/contourf3d_demo2.py b/examples/mplot3d/contourf3d_demo2.py index 21bae939dc12..62e3db785979 100644 --- a/examples/mplot3d/contourf3d_demo2.py +++ b/examples/mplot3d/contourf3d_demo2.py @@ -1,7 +1,9 @@ -""" -.. versionadded:: 1.1.0 - This demo depends on new features added to contourf3d. -""" +''' +Demonstrates displaying a 3D surface while also projecting filled contour +'profiles' onto the 'walls' of the graph. + +See contour3d_demo2 for the unfilled version. +''' from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt @@ -10,16 +12,23 @@ fig = plt.figure() ax = fig.gca(projection='3d') X, Y, Z = axes3d.get_test_data(0.05) + +# Plot the 3D surface ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3) + +# Plot projections of the contours for each dimension. By choosing offsets +# that match the appropriate axes limits, the projected contours will sit on +# the 'walls' of the graph cset = ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap=cm.coolwarm) cset = ax.contourf(X, Y, Z, zdir='x', offset=-40, cmap=cm.coolwarm) cset = ax.contourf(X, Y, Z, zdir='y', offset=40, cmap=cm.coolwarm) -ax.set_xlabel('X') ax.set_xlim(-40, 40) -ax.set_ylabel('Y') ax.set_ylim(-40, 40) -ax.set_zlabel('Z') ax.set_zlim(-100, 100) +ax.set_xlabel('X') +ax.set_ylabel('Y') +ax.set_zlabel('Z') + plt.show() From 74f000c85e9aa666d66470fe7e82e3cdeecf9475 Mon Sep 17 00:00:00 2001 From: Trish Gillett-Kawamoto Date: Thu, 14 Apr 2016 13:33:53 -0400 Subject: [PATCH 6/7] Documentation and touch ups to mixed_subplots_demo and pathpatch3d_demo --- examples/mplot3d/mixed_subplots_demo.py | 33 ++++++++++++++----------- examples/mplot3d/pathpatch3d_demo.py | 22 ++++++++++++++--- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/examples/mplot3d/mixed_subplots_demo.py b/examples/mplot3d/mixed_subplots_demo.py index ffcb23c01c21..f7788e0add78 100644 --- a/examples/mplot3d/mixed_subplots_demo.py +++ b/examples/mplot3d/mixed_subplots_demo.py @@ -1,6 +1,7 @@ """ -Demonstrate the mixing of 2d and 3d subplots +Demonstrate the mixing of 2d and 3d subplots. """ + from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np @@ -12,38 +13,42 @@ def f(t): return np.multiply(s1, e1) -################ +############################################# +# Set up a figure twice as tall as it is wide +############################################# +fig = plt.figure(figsize=plt.figaspect(2.)) +fig.suptitle('A tale of 2 subplots') + + +############################################# # First subplot -################ +############################################# +ax = fig.add_subplot(2, 1, 1) + t1 = np.arange(0.0, 5.0, 0.1) t2 = np.arange(0.0, 5.0, 0.02) t3 = np.arange(0.0, 2.0, 0.01) -# Twice as tall as it is wide. -fig = plt.figure(figsize=plt.figaspect(2.)) -fig.suptitle('A tale of 2 subplots') -ax = fig.add_subplot(2, 1, 1) -l = ax.plot(t1, f(t1), 'bo', - t2, f(t2), 'k--', markerfacecolor='green') +ax.plot(t1, f(t1), 'bo', + t2, f(t2), 'k--', markerfacecolor='green') ax.grid(True) ax.set_ylabel('Damped oscillation') -################# +############################################# # Second subplot -################# +############################################# ax = fig.add_subplot(2, 1, 2, projection='3d') + X = np.arange(-5, 5, 0.25) -xlen = len(X) Y = np.arange(-5, 5, 0.25) -ylen = len(Y) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, linewidth=0, antialiased=False) +ax.set_zlim(-1, 1) -ax.set_zlim3d(-1, 1) plt.show() diff --git a/examples/mplot3d/pathpatch3d_demo.py b/examples/mplot3d/pathpatch3d_demo.py index 9be590f333f3..efc99bb9303e 100644 --- a/examples/mplot3d/pathpatch3d_demo.py +++ b/examples/mplot3d/pathpatch3d_demo.py @@ -1,3 +1,7 @@ +''' +Demonstrate using pathpatch_2d_to_3d to 'draw' shapes and text on a 3D plot. +''' + import matplotlib.pyplot as plt from matplotlib.patches import Circle, PathPatch # register Axes3D class with matplotlib by importing Axes3D @@ -8,7 +12,15 @@ def text3d(ax, xyz, s, zdir="z", size=None, angle=0, usetex=False, **kwargs): + ''' + Plots the string 's' on the axes 'ax', with position 'xyz', size 'size', + and rotation angle 'angle'. 'zdir' gives the axis which is to be treated + as the third dimension. usetex is a boolean indicating whether the string + should be interpreted as latex or not. Any additional keyword arguments + are passed on to transform_path. + Note: zdir affects the interpretation of xyz. + ''' x, y, z = xyz if zdir == "y": xy1, z1 = (x, z), y @@ -28,11 +40,12 @@ def text3d(ax, xyz, s, zdir="z", size=None, angle=0, usetex=False, **kwargs): fig = plt.figure() ax = fig.add_subplot(111, projection='3d') +# Draw a circle on the x=0 'wall' p = Circle((5, 5), 3) ax.add_patch(p) art3d.pathpatch_2d_to_3d(p, z=0, zdir="x") - +# Manually label the axes text3d(ax, (4, -2, 0), "X-axis", zdir="z", size=.5, usetex=False, ec="none", fc="k") text3d(ax, (12, 4, 0), "Y-axis", zdir="z", size=.5, usetex=False, @@ -40,14 +53,15 @@ def text3d(ax, xyz, s, zdir="z", size=None, angle=0, usetex=False, **kwargs): text3d(ax, (12, 10, 4), "Z-axis", zdir="y", size=.5, usetex=False, angle=.5*3.14159, ec="none", fc="k") +# Write a Latex formula on the z=0 'floor' text3d(ax, (1, 5, 0), r"$\displaystyle G_{\mu\nu} + \Lambda g_{\mu\nu} = " r"\frac{8\pi G}{c^4} T_{\mu\nu} $", zdir="z", size=1, usetex=True, ec="none", fc="k") -ax.set_xlim3d(0, 10) -ax.set_ylim3d(0, 10) -ax.set_zlim3d(0, 10) +ax.set_xlim(0, 10) +ax.set_ylim(0, 10) +ax.set_zlim(0, 10) plt.show() From ab0d48c5383219e84fe00106a1803d737838d032 Mon Sep 17 00:00:00 2001 From: Trish Gillett-Kawamoto Date: Thu, 14 Apr 2016 13:45:41 -0400 Subject: [PATCH 7/7] Documentation and tweaks to polys3d_demo: add two extra zero vertices instead of zeroing out the first and last elements of the random data --- examples/mplot3d/polys3d_demo.py | 47 ++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/examples/mplot3d/polys3d_demo.py b/examples/mplot3d/polys3d_demo.py index f9f6b97ed7e2..304c310e682a 100644 --- a/examples/mplot3d/polys3d_demo.py +++ b/examples/mplot3d/polys3d_demo.py @@ -1,3 +1,8 @@ +''' +Demonstrate how to create semi-transparent polygons which fill the space +under a line graph, creating a sort of 'jagged stained glass' effect. +''' + from mpl_toolkits.mplot3d import Axes3D from matplotlib.collections import PolyCollection from matplotlib.colors import colorConverter @@ -5,31 +10,45 @@ import numpy as np +def cc(arg): + ''' + Shorthand to convert 'named' colors to rgba format at 60% opacity. + ''' + return colorConverter.to_rgba(arg, alpha=0.6) + + +def polygon_under_graph(xlist, ylist): + ''' + Construct the vertex list which defines the polygon filling the space under + the (xlist, ylist) line graph. Assumes the xs are in ascending order. + ''' + return [(xlist[0], 0.)] + list(zip(xlist, ylist)) + [(xlist[-1], 0.)] + + fig = plt.figure() ax = fig.gca(projection='3d') +# Make verts a list, verts[i] will be a list of (x,y) pairs defining polygon i +verts = [] -def cc(arg): - return colorConverter.to_rgba(arg, alpha=0.6) +# Set up the x sequence +xs = np.linspace(0., 10., 26) -xs = np.arange(0, 10, 0.4) -verts = [] -zs = [0.0, 1.0, 2.0, 3.0] -for z in zs: +# The ith polygon will appear on the plane y = zs[i] +zs = range(4) + +for i in zs: ys = np.random.rand(len(xs)) - ys[0], ys[-1] = 0, 0 - verts.append(list(zip(xs, ys))) + verts.append(polygon_under_graph(xs, ys)) -poly = PolyCollection(verts, facecolors=[cc('r'), cc('g'), cc('b'), - cc('y')]) -poly.set_alpha(0.7) +poly = PolyCollection(verts, facecolors=[cc('r'), cc('g'), cc('b'), cc('y')]) ax.add_collection3d(poly, zs=zs, zdir='y') ax.set_xlabel('X') -ax.set_xlim3d(0, 10) ax.set_ylabel('Y') -ax.set_ylim3d(-1, 4) ax.set_zlabel('Z') -ax.set_zlim3d(0, 1) +ax.set_xlim(0, 10) +ax.set_ylim(-1, 4) +ax.set_zlim(0, 1) plt.show()