From 31c4b57245ca20931a27868e7c2b0896087cf3f2 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 19:57:30 -0500 Subject: [PATCH 01/35] STY: Refactor string formatting/templating --- doc/sphinxext/gen_gallery.py | 81 ++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/doc/sphinxext/gen_gallery.py b/doc/sphinxext/gen_gallery.py index 609829262933..91b350c08a30 100644 --- a/doc/sphinxext/gen_gallery.py +++ b/doc/sphinxext/gen_gallery.py @@ -1,37 +1,62 @@ # -*- coding: UTF-8 -*- +import os +import re +import glob +import warnings + +import matplotlib.image as image + +multiimage = re.compile('(.*?)(_\d\d){1,2}') + # generate a thumbnail gallery of examples -template = """\ -{%% extends "layout.html" %%} -{%% set title = "Thumbnail gallery" %%} +gallery_template = """\ +{{% extends "layout.html" %}} +{{% set title = "Thumbnail gallery" %}} -{%% block body %%} +{{% block body %}}

Click on any image to see full size image and source code


-
  • Gallery +
  • Gallery +
  • -%s -{%% endblock %%} +{gallery} + +{{% endblock %}} """ -import os, glob, re, sys, warnings -import matplotlib.image as image +header_template = """\ +
    +

    + {title} +

    """ + +link_template = """\ +{basename} +""" + +toc_template = """\ +
  • {section}
  • """ + + +custom_titles = {'pylab_examples' : 'pylab examples'} -multiimage = re.compile('(.*?)(_\d\d){1,2}') def make_thumbnail(args): image.thumbnail(args[0], args[1], 0.3) + def out_of_date(original, derived): return (not os.path.exists(derived) or os.stat(derived).st_mtime < os.stat(original).st_mtime) + def gen_gallery(app, doctree): if app.builder.name != 'html': return @@ -52,22 +77,12 @@ def gen_gallery(app, doctree): thumbnails = {} rows = [] toc_rows = [] - - link_template = """\ - %s - """ - - header_template = """
    \ -

    %s

    """ - - toc_template = """\ -
  • %s
  • """ - dirs = ('api', 'pylab_examples', 'mplot3d', 'widgets', 'axes_grid' ) for subdir in dirs : - rows.append(header_template % (subdir, subdir, subdir)) - toc_rows.append(toc_template % (subdir, subdir)) + title = custom_titles.get(subdir, subdir) + rows.append(header_template.format(title=title, section=subdir)) + toc_rows.append(toc_template.format(section=subdir)) origdir = os.path.join('build', rootdir, subdir) thumbdir = os.path.join(outdir, rootdir, subdir, 'thumbnails') @@ -99,13 +114,12 @@ def gen_gallery(app, doctree): data.append((subdir, basename, os.path.join(rootdir, subdir, 'thumbnails', filename))) - - - for (subdir, basename, thumbfile) in data: if thumbfile is not None: link = 'examples/%s/%s.html'%(subdir, basename) - rows.append(link_template%(link, thumbfile, basename)) + rows.append(link_template.format(link=link, + thumb=thumbfile, + basename=basename)) if len(data) == 0: warnings.warn("No thumbnails were found in %s" % subdir) @@ -113,19 +127,21 @@ def gen_gallery(app, doctree): # Close out the
    opened up at the top of this loop rows.append("
    ") - content = template % ('\n'.join(toc_rows), - '\n'.join(rows)) + content = gallery_template.format(toc='\n'.join(toc_rows), + gallery='\n'.join(rows)) # Only write out the file if the contents have actually changed. # Otherwise, this triggers a full rebuild of the docs - gallery_path = os.path.join(app.builder.srcdir, '_templates', 'gallery.html') + gallery_path = os.path.join(app.builder.srcdir, + '_templates', 'gallery.html') if os.path.exists(gallery_path): fh = file(gallery_path, 'r') regenerate = fh.read() != content fh.close() else: regenerate = True + if regenerate: fh = file(gallery_path, 'w') fh.write(content) @@ -136,5 +152,6 @@ def gen_gallery(app, doctree): length=len(thumbnails)): image.thumbnail(key, thumbnails[key], 0.3) + def setup(app): app.connect('env-updated', gen_gallery) From a16e7934584cd9c7b5c686bdb6bad58729d47367 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 20:25:14 -0500 Subject: [PATCH 02/35] Clean-up and move scatter_demo --- examples/pylab_examples/scatter_demo.py | 10 ---------- examples/shapes_and_collections/scatter_demo.py | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 10 deletions(-) delete mode 100644 examples/pylab_examples/scatter_demo.py create mode 100644 examples/shapes_and_collections/scatter_demo.py diff --git a/examples/pylab_examples/scatter_demo.py b/examples/pylab_examples/scatter_demo.py deleted file mode 100644 index 3adf52b1dd1f..000000000000 --- a/examples/pylab_examples/scatter_demo.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python -from pylab import * - -N = 30 -x = 0.9*rand(N) -y = 0.9*rand(N) -area = pi*(10 * rand(N))**2 # 0 to 10 point radiuses -scatter(x,y,s=area, marker='^', c='r') - -show() diff --git a/examples/shapes_and_collections/scatter_demo.py b/examples/shapes_and_collections/scatter_demo.py new file mode 100644 index 000000000000..317b647ce94c --- /dev/null +++ b/examples/shapes_and_collections/scatter_demo.py @@ -0,0 +1,14 @@ +""" +Simple demo of a scatter plot. +""" +import numpy as np +import matplotlib.pyplot as plt + + +N = 50 +x = np.random.rand(N) +y = np.random.rand(N) +area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radiuses + +plt.scatter(x, y, s=area, alpha=0.5) +plt.show() From a22ed532ed129343c82916363fb7bef716046940 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 20:31:09 -0500 Subject: [PATCH 03/35] Cleanup and move fill_demo --- examples/lines_bars_and_markers/fill_demo.py | 13 +++++++++++++ examples/pylab_examples/fill_demo.py | 10 ---------- 2 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 examples/lines_bars_and_markers/fill_demo.py delete mode 100644 examples/pylab_examples/fill_demo.py diff --git a/examples/lines_bars_and_markers/fill_demo.py b/examples/lines_bars_and_markers/fill_demo.py new file mode 100644 index 000000000000..fff88f2e503a --- /dev/null +++ b/examples/lines_bars_and_markers/fill_demo.py @@ -0,0 +1,13 @@ +""" +Simple demo of the fill function. +""" +import numpy as np +import matplotlib.pyplot as plt + + +x = np.linspace(0, 1) +y = np.sin(4 * np.pi * x) * np.exp(-5 * x) + +plt.fill(x, y, 'r') +plt.grid(True) +plt.show() diff --git a/examples/pylab_examples/fill_demo.py b/examples/pylab_examples/fill_demo.py deleted file mode 100644 index 1cfded4d60cb..000000000000 --- a/examples/pylab_examples/fill_demo.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python -import numpy as np -import matplotlib.pyplot as plt - -t = np.arange(0.0, 1.01, 0.01) -s = np.sin(2*2*np.pi*t) - -plt.fill(t, s*np.exp(-5*t), 'r') -plt.grid(True) -plt.show() From 48caac8c1c81c9e57892e8a8dd5effe086954bd1 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 21:13:55 -0500 Subject: [PATCH 04/35] Cleanup and move pie_demo --- .../pie_and_polar_charts/pie_demo_features.py | 32 +++++++++++++++++++ examples/pylab_examples/pie_demo.py | 30 ----------------- 2 files changed, 32 insertions(+), 30 deletions(-) create mode 100644 examples/pie_and_polar_charts/pie_demo_features.py delete mode 100644 examples/pylab_examples/pie_demo.py diff --git a/examples/pie_and_polar_charts/pie_demo_features.py b/examples/pie_and_polar_charts/pie_demo_features.py new file mode 100644 index 000000000000..2d3647730f4b --- /dev/null +++ b/examples/pie_and_polar_charts/pie_demo_features.py @@ -0,0 +1,32 @@ +""" +Demo of a basic pie chart plus a few additional features. + +In addition to the basic pie chart, this demo shows a few optional features: + + * slice labels + * auto-labeling the percentage + * offsetting a slice with "explode" + * drop-shadow + * custom start angle + + +Note about the custom start angle: + +The default ``startangle`` is 0, which would start the "Frogs" slice on the +x-axis. This example sets ``startangle = 90`` such that everything is rotated +counter-clockwise by 90 degrees, the frog slice starts on the positive y-axis. +""" +import matplotlib.pyplot as plt + + +# The slices will be ordered and plotted counter-clockwise. +labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' +sizes = [15, 30, 45, 10] +colors = ['yellowgreen', 'gold', 'lightskyblue', 'lightcoral'] +explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs') + +plt.pie(sizes, explode=explode, labels=labels, colors=colors, + autopct='%1.1f%%', shadow=True, startangle=90) +# Set aspect ratio to be equal so that pie is drawn as a circle. +plt.axis('equal') +plt.show() diff --git a/examples/pylab_examples/pie_demo.py b/examples/pylab_examples/pie_demo.py deleted file mode 100644 index 0b0e9a3b8a7c..000000000000 --- a/examples/pylab_examples/pie_demo.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Make a pie chart - see -http://matplotlib.sf.net/matplotlib.pylab.html#-pie for the docstring. - -This example shows a basic pie chart with labels optional features, -like autolabeling the percentage, offsetting a slice with "explode", -adding a shadow, and changing the starting angle. - -""" -from pylab import * - -# make a square figure and axes -figure(1, figsize=(6,6)) -ax = axes([0.1, 0.1, 0.8, 0.8]) - -# The slices will be ordered and plotted counter-clockwise. -labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' -fracs = [15, 30, 45, 10] -explode=(0, 0.05, 0, 0) - -pie(fracs, explode=explode, labels=labels, - autopct='%1.1f%%', shadow=True, startangle=90) - # The default startangle is 0, which would start - # the Frogs slice on the x-axis. With startangle=90, - # everything is rotated counter-clockwise by 90 degrees, - # so the plotting starts on the positive y-axis. - -title('Raining Hogs and Dogs', bbox={'facecolor':'0.8', 'pad':5}) - -show() From 7f1887b916ee21f96a49fed60d73b5e306e2287c Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 21:55:36 -0500 Subject: [PATCH 05/35] Cleanup and move errorbar_demo. Split demo in to two different examples --- examples/pylab_examples/errorbar_demo.py | 48 ------------------- examples/statistics/errorbar_demo.py | 13 +++++ examples/statistics/errorbar_demo_features.py | 39 +++++++++++++++ 3 files changed, 52 insertions(+), 48 deletions(-) delete mode 100644 examples/pylab_examples/errorbar_demo.py create mode 100644 examples/statistics/errorbar_demo.py create mode 100644 examples/statistics/errorbar_demo_features.py diff --git a/examples/pylab_examples/errorbar_demo.py b/examples/pylab_examples/errorbar_demo.py deleted file mode 100644 index dbe6bdb2cd64..000000000000 --- a/examples/pylab_examples/errorbar_demo.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -import numpy as np -import matplotlib.pyplot as plt - -# example data -x = np.arange(0.1, 4, 0.5) -y = np.exp(-x) - -# example variable error bar values -yerr = 0.1 + 0.2*np.sqrt(x) -xerr = 0.1 + yerr - -# First illustrate basic pyplot interface, using defaults where possible. -plt.figure() -plt.errorbar(x, y, xerr=0.2, yerr=0.4) -plt.title("Simplest errorbars, 0.2 in x, 0.4 in y") - -# Now switch to a more OO interface to exercise more features. -fig, axs = plt.subplots(nrows=2, ncols=2, sharex=True) -ax = axs[0,0] -ax.errorbar(x, y, yerr=yerr, fmt='o') -ax.set_title('Vert. symmetric') - -# With 4 subplots, reduce the number of axis ticks to avoid crowding. -ax.locator_params(nbins=4) - -ax = axs[0,1] -ax.errorbar(x, y, xerr=xerr, fmt='o') -ax.set_title('Hor. symmetric') - -ax = axs[1,0] -ax.errorbar(x, y, yerr=[yerr, 2*yerr], xerr=[xerr, 2*xerr], fmt='--o') -ax.set_title('H, V asymmetric') - -ax = axs[1,1] -ax.set_yscale('log') -# Here we have to be careful to keep all y values positive: -ylower = np.maximum(1e-2, y - yerr) -yerr_lower = y - ylower - -ax.errorbar(x, y, yerr=[yerr_lower, 2*yerr], xerr=xerr, - fmt='o', ecolor='g', capthick=2) -ax.set_title('Mixed sym., log y') - -fig.suptitle('Variable errorbars') - -plt.show() - diff --git a/examples/statistics/errorbar_demo.py b/examples/statistics/errorbar_demo.py new file mode 100644 index 000000000000..4801f46a8218 --- /dev/null +++ b/examples/statistics/errorbar_demo.py @@ -0,0 +1,13 @@ +""" +Demo of the errorbar function. +""" +import numpy as np +import matplotlib.pyplot as plt + +# example data +x = np.arange(0.1, 4, 0.5) +y = np.exp(-x) + +plt.errorbar(x, y, xerr=0.2, yerr=0.4) +plt.show() + diff --git a/examples/statistics/errorbar_demo_features.py b/examples/statistics/errorbar_demo_features.py new file mode 100644 index 000000000000..2252d1fb4a8c --- /dev/null +++ b/examples/statistics/errorbar_demo_features.py @@ -0,0 +1,39 @@ +""" +Demo of errorbar function with different ways of specifying error bars. + +Errors can be specified as a constant value (as shown in `errorbar_demo.py`), +or as demonstrated in this example, they can be specified by an N x 1 or 2 x N, +where N is the number of data points. + +N x 1: + Error varies for each point, but the error values are symmetric (i.e. the + lower and upper values are equal). + +2 x N: + Error varies for each point, and the lower and upper limits (in that order) + are different (asymmetric case) + +In addition, this example demonstrates how to use log scale with errorbar. +""" +import numpy as np +import matplotlib.pyplot as plt + +# example data +x = np.arange(0.1, 4, 0.5) +y = np.exp(-x) +# example error bar values that vary with x-position +error = 0.1 + 0.2 * x +# error bar values w/ different -/+ errors +lower_error = 0.4 * error +upper_error = error +asymmetric_error = [lower_error, upper_error] + +fig, (ax0, ax1) = plt.subplots(nrows=2, sharex=True) +ax0.errorbar(x, y, yerr=error, fmt='-o') +ax0.set_title('variable, symmetric error') + +ax1.errorbar(x, y, xerr=asymmetric_error, fmt='o') +ax1.set_title('variable, asymmetric error') +ax1.set_yscale('log') +plt.show() + From b10a877a999158b45ba0ec336e9feee6465b9b77 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 22:07:50 -0500 Subject: [PATCH 06/35] Cleanup and move fill_demo2 Rename fill_demo2 to fill_demo_features to clarify purpose --- .../fill_demo_features.py | 17 +++++++++++++++++ examples/pylab_examples/fill_demo2.py | 10 ---------- 2 files changed, 17 insertions(+), 10 deletions(-) create mode 100644 examples/lines_bars_and_markers/fill_demo_features.py delete mode 100644 examples/pylab_examples/fill_demo2.py diff --git a/examples/lines_bars_and_markers/fill_demo_features.py b/examples/lines_bars_and_markers/fill_demo_features.py new file mode 100644 index 000000000000..230f1631c0ad --- /dev/null +++ b/examples/lines_bars_and_markers/fill_demo_features.py @@ -0,0 +1,17 @@ +""" +Demo of the fill function with a few features. + +In addition to the basic fill plot, this demo shows a few optional features: + + * Multiple curves with a single command. + * Setting the fill color. + * Setting the opacity (alpha value). +""" +import numpy as np +import matplotlib.pyplot as plt + +x = np.linspace(0, 2 * np.pi, 100) +y1 = np.sin(x) +y2 = np.sin(3 * x) +plt.fill(x, y1, 'b', x, y2, 'r', alpha=0.3) +plt.show() diff --git a/examples/pylab_examples/fill_demo2.py b/examples/pylab_examples/fill_demo2.py deleted file mode 100644 index 77b86d79017e..000000000000 --- a/examples/pylab_examples/fill_demo2.py +++ /dev/null @@ -1,10 +0,0 @@ -from matplotlib.pyplot import figure, show -from numpy import arange, sin, pi - -fig = figure() -ax = fig.add_subplot(111) -t = arange(0.0,3.01,0.01) -s = sin(2*pi*t) -c = sin(4*pi*t) -ax.fill(t, s, 'b', t, c, 'g', alpha=0.2) -show() From 6995e5468a4de10c5402afa2a6940647eb802253 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 22:29:51 -0500 Subject: [PATCH 07/35] Cleanup and move histogram_demo --- examples/pylab_examples/histogram_demo.py | 22 -------------- .../statistics/histogram_demo_features.py | 30 +++++++++++++++++++ 2 files changed, 30 insertions(+), 22 deletions(-) delete mode 100644 examples/pylab_examples/histogram_demo.py create mode 100644 examples/statistics/histogram_demo_features.py diff --git a/examples/pylab_examples/histogram_demo.py b/examples/pylab_examples/histogram_demo.py deleted file mode 100644 index 00919f78ea67..000000000000 --- a/examples/pylab_examples/histogram_demo.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -import numpy as np -import matplotlib.mlab as mlab -import matplotlib.pyplot as plt - -mu, sigma = 100, 15 -x = mu + sigma*np.random.randn(10000) - -# the histogram of the data -n, bins, patches = plt.hist(x, 50, normed=1, facecolor='green', alpha=0.75) - -# add a 'best fit' line -y = mlab.normpdf( bins, mu, sigma) -l = plt.plot(bins, y, 'r--', linewidth=1) - -plt.xlabel('Smarts') -plt.ylabel('Probability') -plt.title(r'$\mathrm{Histogram\ of\ IQ:}\ \mu=100,\ \sigma=15$') -plt.axis([40, 160, 0, 0.03]) -plt.grid(True) - -plt.show() diff --git a/examples/statistics/histogram_demo_features.py b/examples/statistics/histogram_demo_features.py new file mode 100644 index 000000000000..566e7ed69aa2 --- /dev/null +++ b/examples/statistics/histogram_demo_features.py @@ -0,0 +1,30 @@ +""" +Demo of the histogram (hist) function with a few features. + +In addition to the basic histogram, this demo shows a few optional features: + + * Setting the number of data bins + * The ``normed`` flag, which normalizes bin heights so that the integral of + the histogram is 1. The resulting histogram is a probability density. + * Setting the face color of the bars + * Setting the opacity (alpha value). + +""" +import numpy as np +import matplotlib.mlab as mlab +import matplotlib.pyplot as plt + + +# example data +mu = 100 # mean of distribution +sigma = 15 # standard deviation of distribution +x = mu + sigma * np.random.randn(10000) + +num_bins = 50 +# the histogram of the data +n, bins, patches = plt.hist(x, num_bins, normed=1, facecolor='green', alpha=0.5) +# add a 'best fit' line +y = mlab.normpdf(bins, mu, sigma) +plt.plot(bins, y, 'r--') + +plt.show() From 48fab58af7581917b7d1d36a794acd887830583a Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 22:49:51 -0500 Subject: [PATCH 08/35] Cleanup and move hinton_demo --- examples/api/hinton_demo.py | 60 ------------------------- examples/specialty_plots/hinton_demo.py | 41 +++++++++++++++++ 2 files changed, 41 insertions(+), 60 deletions(-) delete mode 100644 examples/api/hinton_demo.py create mode 100644 examples/specialty_plots/hinton_demo.py diff --git a/examples/api/hinton_demo.py b/examples/api/hinton_demo.py deleted file mode 100644 index 700e13c1bb65..000000000000 --- a/examples/api/hinton_demo.py +++ /dev/null @@ -1,60 +0,0 @@ -#Initial idea from David Warde-Farley on the SciPy Cookbook -import numpy as np -import matplotlib.pyplot as plt -from matplotlib.patches import Rectangle -from matplotlib.ticker import NullLocator -#from matplotlib.collections import RegularPolyCollection -#from matplotlib.colors import BoundaryNorm, ListedColormap - -def hinton(W, maxWeight=None, ax=None): - """ - Draws a Hinton diagram for visualizing a weight matrix. - """ - if not ax: - fig = plt.figure() - ax = fig.add_subplot(1, 1, 1) - - if not maxWeight: - maxWeight = 2**np.ceil(np.log(np.abs(W).max())/np.log(2)) - - ax.patch.set_facecolor('gray') - ax.set_aspect('equal', 'box') - ax.xaxis.set_major_locator(NullLocator()) - ax.yaxis.set_major_locator(NullLocator()) - - for (x,y),w in np.ndenumerate(W): - if w > 0: color = 'white' - else: color = 'black' - size = np.sqrt(np.abs(w)) - rect = Rectangle([x - size / 2, y - size / 2], size, size, - facecolor=color, edgecolor=color) - ax.add_patch(rect) - ax.autoscale_view() - - # Reverse the yaxis limits - ax.set_ylim(*ax.get_ylim()[::-1]) - -## Potential way using polygon collections that just has an issue with -## easily getting the squares scaled by the data. - -# height,width = W.shape -# x = np.arange(width) -# y = np.arange(height) -# X,Y = np.meshgrid(x, y) -# xy = np.array([X.flatten(),Y.flatten()]).T -# scaled_data = W.flatten() / maxWeight -# cmap = ListedColormap(['black', 'white']) -# norm = BoundaryNorm([-1., 0., 1.], cmap.N) - -# rect_col = RegularPolyCollection(4, rotation=np.pi/4, -# sizes=np.abs(scaled_data) * 72 / ax.figure.get_dpi(), offsets=xy, -# transOffset=ax.transData, norm=norm, cmap=cmap, edgecolor='none') -# ax.add_collection(rect_col) -# rect_col.set_array(scaled_data) -# ax.autoscale_view() - -if __name__ == '__main__': - hinton(np.random.rand(20, 20) - 0.5) - plt.title('Hinton Example') - plt.show() - diff --git a/examples/specialty_plots/hinton_demo.py b/examples/specialty_plots/hinton_demo.py new file mode 100644 index 000000000000..201b321283c1 --- /dev/null +++ b/examples/specialty_plots/hinton_demo.py @@ -0,0 +1,41 @@ +""" +Demo of a function to create Hinton diagrams. + +Hinton diagrams are useful for visualizing the values of a 2D array (e.g. +a weight matrix): Positive and negative values are represented by white and +black squares, respectively, and the size of each square represents the +magnitude of each value. + +Initial idea from David Warde-Farley on the SciPy Cookbook +""" +import numpy as np +import matplotlib.pyplot as plt + + +def hinton(matrix, max_weight=None, ax=None): + """Draw Hinton diagram for visualizing a weight matrix.""" + ax = ax if ax is not None else plt.gca() + + if not max_weight: + max_weight = 2**np.ceil(np.log(np.abs(matrix).max())/np.log(2)) + + ax.patch.set_facecolor('gray') + ax.set_aspect('equal', 'box') + ax.xaxis.set_major_locator(plt.NullLocator()) + ax.yaxis.set_major_locator(plt.NullLocator()) + + for (x,y),w in np.ndenumerate(matrix): + color = 'white' if w > 0 else 'black' + size = np.sqrt(np.abs(w)) + rect = plt.Rectangle([x - size / 2, y - size / 2], size, size, + facecolor=color, edgecolor=color) + ax.add_patch(rect) + + ax.autoscale_view() + ax.invert_yaxis() + + +if __name__ == '__main__': + hinton(np.random.rand(20, 20) - 0.5) + plt.show() + From e9bfbb99b0e1c330117b6ebae23379d588805f11 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 17 Dec 2012 23:09:02 -0500 Subject: [PATCH 09/35] Cleanup and move image_demo3.py * Rename to imshow_demo * Add smaller version of lena image saved as a numpy binary so that use doesn't require PIL --- .../images_contours_and_fields/imshow_demo.py | 14 ++++++++++++ examples/pylab_examples/image_demo3.py | 21 ------------------ lib/matplotlib/mpl-data/sample_data/lena.npy | Bin 0 -> 196688 bytes 3 files changed, 14 insertions(+), 21 deletions(-) create mode 100644 examples/images_contours_and_fields/imshow_demo.py delete mode 100644 examples/pylab_examples/image_demo3.py create mode 100644 lib/matplotlib/mpl-data/sample_data/lena.npy diff --git a/examples/images_contours_and_fields/imshow_demo.py b/examples/images_contours_and_fields/imshow_demo.py new file mode 100644 index 000000000000..6b73458153e4 --- /dev/null +++ b/examples/images_contours_and_fields/imshow_demo.py @@ -0,0 +1,14 @@ +""" +Simple demo of the imshow function. +""" +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.cbook as cbook + +image_file = cbook.get_sample_data('lena.npy') +image = np.load(image_file) + +plt.imshow(image) +plt.axis('off') # clear x- and y-axes +plt.show() + diff --git a/examples/pylab_examples/image_demo3.py b/examples/pylab_examples/image_demo3.py deleted file mode 100644 index a469b48cf79d..000000000000 --- a/examples/pylab_examples/image_demo3.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python -from pylab import * -try: - from PIL import Image -except ImportError: - raise SystemExit("PIL must be installed to run this example") - -import matplotlib.cbook as cbook - -datafile = cbook.get_sample_data('lena.jpg') -lena = Image.open(datafile) -dpi = rcParams['figure.dpi'] -figsize = lena.size[0]/dpi, lena.size[1]/dpi - -figure(figsize=figsize) -ax = axes([0,0,1,1], frameon=False) -ax.set_axis_off() -im = imshow(lena) - -show() - diff --git a/lib/matplotlib/mpl-data/sample_data/lena.npy b/lib/matplotlib/mpl-data/sample_data/lena.npy new file mode 100644 index 0000000000000000000000000000000000000000..39f4fb1f07f8029a0a24ca1f6f7236c4d79277a8 GIT binary patch literal 196688 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⁣kz-LlV&a=y^~eND~} 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�x#`$!~MMCV*x(fI|l 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 Date: Thu, 20 Dec 2012 22:15:17 -0800 Subject: [PATCH 10/35] DOC: Minor rewording --- examples/pie_and_polar_charts/pie_demo_features.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/pie_and_polar_charts/pie_demo_features.py b/examples/pie_and_polar_charts/pie_demo_features.py index 2d3647730f4b..763d38461aee 100644 --- a/examples/pie_and_polar_charts/pie_demo_features.py +++ b/examples/pie_and_polar_charts/pie_demo_features.py @@ -9,12 +9,12 @@ * drop-shadow * custom start angle - Note about the custom start angle: The default ``startangle`` is 0, which would start the "Frogs" slice on the -x-axis. This example sets ``startangle = 90`` such that everything is rotated -counter-clockwise by 90 degrees, the frog slice starts on the positive y-axis. +positive x-axis. This example sets ``startangle = 90`` such that everything is +rotated counter-clockwise by 90 degrees, and the frog slice starts on the +positive y-axis. """ import matplotlib.pyplot as plt From c0f42d78b6f94e1a4fe4df08c661cd79955b8a8b Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Thu, 20 Dec 2012 22:18:03 -0800 Subject: [PATCH 11/35] Fix doc build to search in new example sections. Add new sphinx config variable `mpl_example_sections` and use this list in both `gen_gallery.py` and `gen_rst.py`. --- doc/conf.py | 17 +++++++++++ doc/sphinxext/gen_gallery.py | 16 ++++++++-- doc/sphinxext/gen_rst.py | 30 +++++++++++------- doc/users/screenshots.rst | 6 ++-- examples/tests/backend_driver.py | 52 ++++++++++++++++++++++++++------ lib/matplotlib/axes.py | 6 ++-- 6 files changed, 99 insertions(+), 28 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 445ced4c048b..bc8e58b3077b 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -82,6 +82,23 @@ plot_formats = [('png', 80), ('hires.png', 200), ('pdf', 50)] +# Subdirectories in 'examples/' directory of package +mpl_example_sections = ('lines_bars_and_markers', + 'shapes_and_collections', + 'statistics', + 'images_contours_and_fields', + 'pie_and_polar_charts', + 'text_labels_and_annotations', + 'ticks_and_spines', + 'subplots_axes_and_figures', + 'specialty_plots', + 'showcase', + 'reference', + 'api', 'pylab_examples', + 'mplot3d', 'axes_grid', + 'units', 'widgets') + + # Github extension github_project_url = "http://github.com/matplotlib/matplotlib/" diff --git a/doc/sphinxext/gen_gallery.py b/doc/sphinxext/gen_gallery.py index 91b350c08a30..41182d1a2b02 100644 --- a/doc/sphinxext/gen_gallery.py +++ b/doc/sphinxext/gen_gallery.py @@ -4,8 +4,12 @@ import glob import warnings +import sphinx.errors + import matplotlib.image as image + +exclude_example_sections = ['units'] multiimage = re.compile('(.*?)(_\d\d){1,2}') @@ -64,6 +68,10 @@ def gen_gallery(app, doctree): outdir = app.builder.outdir rootdir = 'plot_directive/mpl_examples' + example_sections = list(app.builder.config.mpl_example_sections) + for section in exclude_example_sections: + example_sections.remove(section) + # images we want to skip for the gallery because they are an unusual # size that doesn't layout well in a table, or because they may be # redundant with other images or uninteresting @@ -77,9 +85,8 @@ def gen_gallery(app, doctree): thumbnails = {} rows = [] toc_rows = [] - dirs = ('api', 'pylab_examples', 'mplot3d', 'widgets', 'axes_grid' ) - for subdir in dirs : + for subdir in example_sections: title = custom_titles.get(subdir, subdir) rows.append(header_template.format(title=title, section=subdir)) toc_rows.append(toc_template.format(section=subdir)) @@ -155,3 +162,8 @@ def gen_gallery(app, doctree): def setup(app): app.connect('env-updated', gen_gallery) + + try: # multiple plugins may use mpl_example_sections + app.add_config_value('mpl_example_sections', [], True) + except sphinx.errors.ExtensionError: + pass # mpl_example_sections already defined diff --git a/doc/sphinxext/gen_rst.py b/doc/sphinxext/gen_rst.py index e8135bf4abdb..4294f4e4787b 100644 --- a/doc/sphinxext/gen_rst.py +++ b/doc/sphinxext/gen_rst.py @@ -2,12 +2,17 @@ generate the rst files for the examples by iterating over the pylab examples """ from __future__ import print_function -import os, glob import os import re import sys -fileList = [] + +import sphinx.errors + + +exclude_example_sections = ['widgets'] +noplot_regex = re.compile(r"#\s*-\*-\s*noplot\s*-\*-") + def out_of_date(original, derived): """ @@ -21,14 +26,17 @@ def out_of_date(original, derived): return (not os.path.exists(derived) or os.stat(derived).st_mtime < os.stat(original).st_mtime) -noplot_regex = re.compile(r"#\s*-\*-\s*noplot\s*-\*-") - def generate_example_rst(app): rootdir = os.path.join(app.builder.srcdir, 'mpl_examples') exampledir = os.path.join(app.builder.srcdir, 'examples') if not os.path.exists(exampledir): os.makedirs(exampledir) + example_sections = list(app.builder.config.mpl_example_sections) + for section in exclude_example_sections: + example_sections.remove(section) + + datad = {} for root, subFolders, files in os.walk(rootdir): for fname in files: @@ -114,13 +122,8 @@ def generate_example_rst(app): fhsubdirIndex.write(' %s <%s>\n'%(os.path.basename(basename),rstfile)) - do_plot = (subdir in ('api', - 'pylab_examples', - 'units', - 'mplot3d', - 'axes_grid', - ) and - not noplot_regex.search(contents)) + do_plot = (subdir in example_sections + and not noplot_regex.search(contents)) if not do_plot: fhstatic = file(outputfile, 'w') fhstatic.write(contents) @@ -157,3 +160,8 @@ def generate_example_rst(app): def setup(app): app.connect('builder-inited', generate_example_rst) + + try: # multiple plugins may use mpl_example_sections + app.add_config_value('mpl_example_sections', [], True) + except sphinx.errors.ExtensionError: + pass # mpl_example_sections already defined diff --git a/doc/users/screenshots.rst b/doc/users/screenshots.rst index 86f6c2687c30..0fee2ab43bd4 100644 --- a/doc/users/screenshots.rst +++ b/doc/users/screenshots.rst @@ -32,7 +32,7 @@ Histograms The :func:`~matplotlib.pyplot.hist` command automatically generates histograms and will return the bin counts or probabilities -.. plot:: mpl_examples/pylab_examples/histogram_demo.py +.. plot:: mpl_examples/statistics/histogram_demo_features.py .. _screenshots_path_demo: @@ -103,7 +103,7 @@ or more wedges out from the center of the pie, and a shadow effect. Take a close look at the attached code that produced this figure; nine lines of code. -.. plot:: mpl_examples/pylab_examples/pie_demo.py +.. plot:: mpl_examples/pie_and_polar_charts/pie_demo_features.py .. _screenshots_table_demo: @@ -153,7 +153,7 @@ The :func:`~matplotlib.pyplot.fill` command lets you plot filled polygons. Thanks to Andrew Straw for providing this function -.. plot:: mpl_examples/pylab_examples/fill_demo.py +.. plot:: mpl_examples/lines_bars_and_markers/fill_demo.py .. _screenshots_date_demo: diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index 9f1c28bb7606..f7aee615efc5 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -20,21 +20,62 @@ switches with a --. """ -import os, time, sys, glob, string +import os +import time +import sys +import glob from optparse import OptionParser + import matplotlib.rcsetup as rcsetup from matplotlib.cbook import Bunch, dedent + all_backends = list(rcsetup.all_backends) # to leave the original list alone # actual physical directory for each dir -dirs = dict(pylab = os.path.join('..', 'pylab_examples'), +dirs = dict(files=os.path.join('..', 'lines_bars_and_markers'), + shapes=os.path.join('..', 'shapes_and_collections'), + images=os.path.join('..', 'images_contours_and_fields'), + pie=os.path.join('..', 'pie_and_polar_charts'), + text=os.path.join('..', 'text_labels_and_annotations'), + ticks=os.path.join('..', 'ticks_and_spines'), + subplots=os.path.join('..', 'subplots_axes_and_figures'), + specialty=os.path.join('..', 'specialty_plots'), + showcase=os.path.join('..', 'showcase'), + reference=os.path.join('..', 'reference'), + pylab = os.path.join('..', 'pylab_examples'), api = os.path.join('..', 'api'), units = os.path.join('..', 'units'), mplot3d = os.path.join('..', 'mplot3d')) + # files in each dir files = dict() + +files['lines'] = [ + 'fill_demo.py', + 'fill_demo_features.py', + ] + +files['shapes'] = [ + 'scatter_demo.py', + ] + +files['images'] = [ + 'imshow_demo.py', + ] + + +files['statistics'] = [ + 'errorbar_demo.py', + 'errorbar_demo_features.py', + 'histogram_demo_features.py', + ] + +files['pie'] = [ + 'pie_demo.py', + ] + files['pylab'] = [ 'accented_text.py', 'alignment_test.py', @@ -86,7 +127,6 @@ 'ellipse_demo.py', 'ellipse_rotated.py', 'equal_aspect_ratio.py', - 'errorbar_demo.py', 'errorbar_limits.py', 'fancyarrow_demo.py', 'fancybox_demo.py', @@ -96,8 +136,6 @@ 'figlegend_demo.py', 'figure_title.py', 'fill_between_demo.py', - 'fill_demo.py', - 'fill_demo2.py', 'fill_spiral.py', 'finance_demo.py', 'findobj_demo.py', @@ -111,14 +149,12 @@ 'hexbin_demo.py', 'hexbin_demo2.py', 'hist_colormapped.py', - 'histogram_demo.py', 'histogram_demo_extended.py', 'hline_demo.py', 'image_clip_path.py', 'image_demo.py', 'image_demo2.py', - 'image_demo3.py', 'image_interp.py', 'image_masked.py', 'image_nonuniform.py', @@ -158,7 +194,6 @@ 'pcolor_demo2.py', 'pcolor_log.py', 'pcolor_small.py', - 'pie_demo.py', 'pie_demo2.py', 'plotfile_demo.py', 'polar_bar.py', @@ -172,7 +207,6 @@ 'quadmesh_demo.py', 'quiver_demo.py', 'scatter_custom_symbol.py', - 'scatter_demo.py', 'scatter_demo2.py', 'scatter_masked.py', 'scatter_profile.py', diff --git a/lib/matplotlib/axes.py b/lib/matplotlib/axes.py index c2f294ce9d73..1f3342921d4a 100644 --- a/lib/matplotlib/axes.py +++ b/lib/matplotlib/axes.py @@ -5367,7 +5367,7 @@ def errorbar(self, x, y, yerr=None, xerr=None, **Example:** - .. plot:: mpl_examples/pylab_examples/errorbar_demo.py + .. plot:: mpl_examples/statistics/errorbar_demo.py """ @@ -6697,7 +6697,7 @@ def fill(self, *args, **kwargs): **Example:** - .. plot:: mpl_examples/pylab_examples/fill_demo.py + .. plot:: mpl_examples/lines_bars_and_markers/fill_demo.py """ if not self._hold: @@ -7976,7 +7976,7 @@ def hist(self, x, bins=10, range=None, normed=False, weights=None, **Example:** - .. plot:: mpl_examples/pylab_examples/histogram_demo.py + .. plot:: mpl_examples/statistics/histogram_demo_features.py """ if not self._hold: From e244d9bbeea28fbc4bbc27c449460e0d18178ae1 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Thu, 20 Dec 2012 23:02:17 -0800 Subject: [PATCH 12/35] Cleanup and move subplot_demo --- doc/users/screenshots.rst | 2 +- examples/pylab_examples/subplot_demo.py | 39 +++++++++---------- .../subplots_axes_and_figures/subplot_demo.py | 24 ++++++++++++ examples/tests/backend_driver.py | 5 ++- lib/matplotlib/pyplot.py | 2 +- 5 files changed, 49 insertions(+), 23 deletions(-) create mode 100644 examples/subplots_axes_and_figures/subplot_demo.py diff --git a/doc/users/screenshots.rst b/doc/users/screenshots.rst index 0fee2ab43bd4..0a9145d60a8d 100644 --- a/doc/users/screenshots.rst +++ b/doc/users/screenshots.rst @@ -22,7 +22,7 @@ Subplot demo Multiple regular axes (numrows by numcolumns) are created with the :func:`~matplotlib.pyplot.subplot` command. -.. plot:: mpl_examples/pylab_examples/subplot_demo.py +.. plot:: mpl_examples/subplots_axes_and_figures/subplot_demo.py .. _screenshots_histogram_demo: diff --git a/examples/pylab_examples/subplot_demo.py b/examples/pylab_examples/subplot_demo.py index 509b7f1db2b8..6e9598eab725 100644 --- a/examples/pylab_examples/subplot_demo.py +++ b/examples/pylab_examples/subplot_demo.py @@ -1,25 +1,24 @@ -#!/usr/bin/env python -from pylab import * +""" +Simple demo with multiple subplots. +""" +import numpy as np +import matplotlib.pyplot as plt -def f(t): - s1 = cos(2*pi*t) - e1 = exp(-t) - return multiply(s1,e1) -t1 = arange(0.0, 5.0, 0.1) -t2 = arange(0.0, 5.0, 0.02) -t3 = arange(0.0, 2.0, 0.01) +x1 = np.linspace(0.0, 5.0) +x2 = np.linspace(0.0, 2.0) -subplot(211) -l = plot(t1, f(t1), 'bo', t2, f(t2), 'k--', markerfacecolor='green') -grid(True) -title('A tale of 2 subplots') -ylabel('Damped oscillation') +y1 = np.cos(2 * np.pi * x1) * np.exp(-x1) +y2 = np.cos(2 * np.pi * x2) -subplot(212) -plot(t3, cos(2*pi*t3), 'r.') -grid(True) -xlabel('time (s)') -ylabel('Undamped') -show() +plt.subplot(2, 1, 1) +plt.plot(x1, y1, 'ko-') +plt.title('A tale of 2 subplots') +plt.ylabel('Damped oscillation') +plt.subplot(2, 1, 2) +plt.plot(x2, y2, 'r.-') +plt.xlabel('time (s)') +plt.ylabel('Undamped') + +plt.show() diff --git a/examples/subplots_axes_and_figures/subplot_demo.py b/examples/subplots_axes_and_figures/subplot_demo.py new file mode 100644 index 000000000000..b90b53d899e9 --- /dev/null +++ b/examples/subplots_axes_and_figures/subplot_demo.py @@ -0,0 +1,24 @@ +""" +Simple demo with multiple subplots. +""" +import numpy as np +import matplotlib.pyplot as plt + + +x1 = np.linspace(0.0, 5.0) +x2 = np.linspace(0.0, 2.0) + +y1 = np.cos(2 * np.pi * x1) * np.exp(-x1) +y2 = np.cos(2 * np.pi * x2) + +plt.subplot(2, 1, 1) +plt.plot(x1, y1, 'yo-') +plt.title('A tale of 2 subplots') +plt.ylabel('Damped oscillation') + +plt.subplot(2, 1, 2) +plt.plot(x2, y2, 'r.-') +plt.xlabel('time (s)') +plt.ylabel('Undamped') + +plt.show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index f7aee615efc5..bc48262f0dd2 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -76,6 +76,10 @@ 'pie_demo.py', ] +files['subplots_axes_and_figures'] = [ + 'subplot_demo.py', + ] + files['pylab'] = [ 'accented_text.py', 'alignment_test.py', @@ -222,7 +226,6 @@ 'step_demo.py', 'stix_fonts_demo.py', 'stock_demo.py', - 'subplot_demo.py', 'subplots_adjust.py', 'symlog_demo.py', 'table_demo.py', diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 493d95b9d4df..49754f4606a5 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -768,7 +768,7 @@ def subplot(*args, **kwargs): **Example:** - .. plot:: mpl_examples/pylab_examples/subplot_demo.py + .. plot:: mpl_examples/subplots_axes_and_figures/subplot_demo.py """ # if subplot called without arguments, create subplot(1,1,1) From 002ca7a6cdb1b7318902cdc3719aa15545feac3c Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Fri, 21 Dec 2012 12:10:13 -0800 Subject: [PATCH 13/35] Update example section titles --- doc/conf.py | 1 - doc/sphinxext/gen_gallery.py | 21 +++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index bc8e58b3077b..57da9709f3c0 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -93,7 +93,6 @@ 'subplots_axes_and_figures', 'specialty_plots', 'showcase', - 'reference', 'api', 'pylab_examples', 'mplot3d', 'axes_grid', 'units', 'widgets') diff --git a/doc/sphinxext/gen_gallery.py b/doc/sphinxext/gen_gallery.py index 41182d1a2b02..4311dd745418 100644 --- a/doc/sphinxext/gen_gallery.py +++ b/doc/sphinxext/gen_gallery.py @@ -11,7 +11,19 @@ exclude_example_sections = ['units'] multiimage = re.compile('(.*?)(_\d\d){1,2}') - +custom_titles = {'pylab_examples' : 'pylab examples', + 'lines_bars_and_markers': 'Lines, bars, and markers', + 'shapes_and_collections': 'Shapes and collections', + 'statistics': 'Statistical plots', + 'images_contours_and_fields': 'Images, contours, and fields', + 'pie_and_polar_charts': 'Pie and polar charts', + 'text_labels_and_annotations': 'Text, labels, and annotations', + 'ticks_and_spines': 'Ticks and spines', + 'subplots_axes_and_figures': 'Subplots, axes, and figures', + 'specialty_plots': 'Specialty plots', + 'showcase': 'Showcase', + 'api': 'API', + } # generate a thumbnail gallery of examples gallery_template = """\ @@ -46,10 +58,7 @@ """ toc_template = """\ -""" - - -custom_titles = {'pylab_examples' : 'pylab examples'} +
  • {title}
  • """ def make_thumbnail(args): @@ -89,7 +98,7 @@ def gen_gallery(app, doctree): for subdir in example_sections: title = custom_titles.get(subdir, subdir) rows.append(header_template.format(title=title, section=subdir)) - toc_rows.append(toc_template.format(section=subdir)) + toc_rows.append(toc_template.format(title=title, section=subdir)) origdir = os.path.join('build', rootdir, subdir) thumbdir = os.path.join(outdir, rootdir, subdir, 'thumbnails') From 402b3014885054ce67b86e834807d0480093ef60 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Fri, 21 Dec 2012 12:11:42 -0800 Subject: [PATCH 14/35] Cleanup and move unicode_demo --- examples/pylab_examples/unicode_demo.py | 15 --------------- examples/tests/backend_driver.py | 6 ++++-- .../text_labels_and_annotations/unicode_demo.py | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 17 deletions(-) delete mode 100755 examples/pylab_examples/unicode_demo.py create mode 100644 examples/text_labels_and_annotations/unicode_demo.py diff --git a/examples/pylab_examples/unicode_demo.py b/examples/pylab_examples/unicode_demo.py deleted file mode 100755 index bba623482a26..000000000000 --- a/examples/pylab_examples/unicode_demo.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -import pylab - -pylab.plot([1, 2, 4]) -pylab.title('Développés et fabriqués') -pylab.xlabel("réactivité nous permettent d'être sélectionnés et adoptés") -pylab.ylabel('André was here!') -pylab.text( 0.5, 2.5, 'Institut für Festkörperphysik', rotation=45) -pylab.text( 1, 1.5, 'AVA (check kerning)') - -pylab.show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index bc48262f0dd2..4e31c7a43426 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -42,7 +42,6 @@ subplots=os.path.join('..', 'subplots_axes_and_figures'), specialty=os.path.join('..', 'specialty_plots'), showcase=os.path.join('..', 'showcase'), - reference=os.path.join('..', 'reference'), pylab = os.path.join('..', 'pylab_examples'), api = os.path.join('..', 'api'), units = os.path.join('..', 'units'), @@ -76,6 +75,10 @@ 'pie_demo.py', ] +files['text_labels_and_annotations'] = [ + 'unicode_demo.py', + ] + files['subplots_axes_and_figures'] = [ 'subplot_demo.py', ] @@ -234,7 +237,6 @@ 'text_rotation_relative_to_line.py', 'text_themes.py', 'transoffset.py', - 'unicode_demo.py', 'vertical_ticklabels.py', 'vline_demo.py', 'xcorr_demo.py', diff --git a/examples/text_labels_and_annotations/unicode_demo.py b/examples/text_labels_and_annotations/unicode_demo.py new file mode 100644 index 000000000000..295b3c4aa5fd --- /dev/null +++ b/examples/text_labels_and_annotations/unicode_demo.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +Demo of unicode support in text and labels. +""" +from __future__ import unicode_literals + +import matplotlib.pyplot as plt + + +plt.title('Développés et fabriqués') +plt.xlabel("réactivité nous permettent d'être sélectionnés et adoptés") +plt.ylabel('André was here!') +plt.text( 0.2, 0.8, 'Institut für Festkörperphysik', rotation=45) +plt.text( 0.4, 0.2, 'AVA (check kerning)') + +plt.show() From 529d9f787ca21c99469e0f64b38a91a0c3173d02 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Fri, 21 Dec 2012 23:13:56 -0800 Subject: [PATCH 15/35] Consolidate histogram examples --- examples/api/histogram_demo.py | 34 ------------------- .../statistics/histogram_demo_features.py | 3 ++ examples/tests/backend_driver.py | 1 - 3 files changed, 3 insertions(+), 35 deletions(-) delete mode 100644 examples/api/histogram_demo.py diff --git a/examples/api/histogram_demo.py b/examples/api/histogram_demo.py deleted file mode 100644 index 11c4b0adaba1..000000000000 --- a/examples/api/histogram_demo.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Make a histogram of normally distributed random numbers and plot the -analytic PDF over it -""" -import numpy as np -import matplotlib.pyplot as plt -import matplotlib.mlab as mlab - -mu, sigma = 100, 15 -x = mu + sigma * np.random.randn(10000) - -fig = plt.figure() -ax = fig.add_subplot(111) - -# the histogram of the data -n, bins, patches = ax.hist(x, 50, normed=1, facecolor='green', alpha=0.75) - -# hist uses np.histogram under the hood to create 'n' and 'bins'. -# np.histogram returns the bin edges, so there will be 50 probability -# density values in n, 51 bin edges in bins and 50 patches. To get -# everything lined up, we'll compute the bin centers -bincenters = 0.5*(bins[1:]+bins[:-1]) -# add a 'best fit' line for the normal PDF -y = mlab.normpdf( bincenters, mu, sigma) -l = ax.plot(bincenters, y, 'r--', linewidth=1) - -ax.set_xlabel('Smarts') -ax.set_ylabel('Probability') -#ax.set_title(r'$\mathrm{Histogram\ of\ IQ:}\ \mu=100,\ \sigma=15$') -ax.set_xlim(40, 160) -ax.set_ylim(0, 0.03) -ax.grid(True) - -plt.show() diff --git a/examples/statistics/histogram_demo_features.py b/examples/statistics/histogram_demo_features.py index 566e7ed69aa2..d81278fcc9ae 100644 --- a/examples/statistics/histogram_demo_features.py +++ b/examples/statistics/histogram_demo_features.py @@ -26,5 +26,8 @@ # add a 'best fit' line y = mlab.normpdf(bins, mu, sigma) plt.plot(bins, y, 'r--') +plt.xlabel('Smarts') +plt.ylabel('Probability') +plt.title(r'Histogram of IQ: $\mu=100$, $\sigma=15$') plt.show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index 4e31c7a43426..a7a7ba1773d7 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -257,7 +257,6 @@ 'date_index_formatter.py', 'donut_demo.py', 'font_family_rc.py', - 'histogram_demo.py', 'image_zcoord.py', 'joinstyle.py', 'legend_demo.py', From 6acc43ae043ccef385021f5f6526085d852c5516 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 10:28:51 -0800 Subject: [PATCH 16/35] Cleanup and move vertical_ticklabels demo --- examples/pylab_examples/vertical_ticklabels.py | 7 ------- examples/tests/backend_driver.py | 5 ++++- .../ticks_and_spines/ticklabels_demo_rotation.py | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 8 deletions(-) delete mode 100644 examples/pylab_examples/vertical_ticklabels.py create mode 100644 examples/ticks_and_spines/ticklabels_demo_rotation.py diff --git a/examples/pylab_examples/vertical_ticklabels.py b/examples/pylab_examples/vertical_ticklabels.py deleted file mode 100644 index 2416a785bfc1..000000000000 --- a/examples/pylab_examples/vertical_ticklabels.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -from pylab import * - -plot([1,2,3,4], [1,4,9,16]) -locs, labels = xticks([1,2,3,4], ['Frogs', 'Hogs', 'Bogs', 'Slogs']) -setp(labels, 'rotation', 'vertical') -show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index a7a7ba1773d7..cca0a3f08cc0 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -79,6 +79,10 @@ 'unicode_demo.py', ] +files['ticks_and_spines'] = [ + 'ticklabels_demo_rotation.py', + ] + files['subplots_axes_and_figures'] = [ 'subplot_demo.py', ] @@ -237,7 +241,6 @@ 'text_rotation_relative_to_line.py', 'text_themes.py', 'transoffset.py', - 'vertical_ticklabels.py', 'vline_demo.py', 'xcorr_demo.py', 'zorder_demo.py', diff --git a/examples/ticks_and_spines/ticklabels_demo_rotation.py b/examples/ticks_and_spines/ticklabels_demo_rotation.py new file mode 100644 index 000000000000..0f926fe79c4a --- /dev/null +++ b/examples/ticks_and_spines/ticklabels_demo_rotation.py @@ -0,0 +1,16 @@ +""" +Demo of custom tick-labels with user-defined rotation. +""" +import matplotlib.pyplot as plt + + +x = [1, 2, 3, 4] +y = [1, 4, 9, 6] +labels = ['Frogs', 'Hogs', 'Bogs', 'Slogs'] + +plt.plot(x, y, 'ro') +# You can specify a rotation for the tick labels in degrees or with keywords. +plt.xticks(x, labels, rotation='vertical') +# Pad margins so that markers don't get clipped by the axes +plt.margins(0.2) +plt.show() From 7f7c01345b4c43828796c5d205a56f315943bd9b Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 16:39:34 -0800 Subject: [PATCH 17/35] Cleanup and move clippath_demo --- examples/api/clippath_demo.py | 19 ------------------- .../image_demo_clip_path.py | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 examples/api/clippath_demo.py create mode 100644 examples/images_contours_and_fields/image_demo_clip_path.py diff --git a/examples/api/clippath_demo.py b/examples/api/clippath_demo.py deleted file mode 100644 index 7a07467524ba..000000000000 --- a/examples/api/clippath_demo.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Clipping to arbitrary patches and paths -""" -import numpy as np -import matplotlib.pyplot as plt -import matplotlib.patches as patches - - -fig = plt.figure() -ax = fig.add_subplot(111, frameon=False, xticks=[], yticks=[]) - -im = ax.imshow(np.random.rand(10,10)) - -patch = patches.Circle((300,300), radius=100) -im.set_clip_path(patch) - -plt.show() - - diff --git a/examples/images_contours_and_fields/image_demo_clip_path.py b/examples/images_contours_and_fields/image_demo_clip_path.py new file mode 100644 index 000000000000..ac61d4f0b8cd --- /dev/null +++ b/examples/images_contours_and_fields/image_demo_clip_path.py @@ -0,0 +1,19 @@ +""" +Demo of image that's been clipped by a circular patch. +""" +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.patches as patches +import matplotlib.cbook as cbook + + +image_file = cbook.get_sample_data('lena.npy') +image = np.load(image_file) + +fig, ax = plt.subplots() +im = ax.imshow(image) +patch = patches.Circle((130, 130), radius=100, transform=ax.transData) +im.set_clip_path(patch) + +plt.axis('off') +plt.show() From ab417eb4045a55abcf9432b4e1951218776e5236 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 16:40:42 -0800 Subject: [PATCH 18/35] Rename imshow_demo to image_demo --- .../images_contours_and_fields/{imshow_demo.py => image_demo.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/images_contours_and_fields/{imshow_demo.py => image_demo.py} (100%) diff --git a/examples/images_contours_and_fields/imshow_demo.py b/examples/images_contours_and_fields/image_demo.py similarity index 100% rename from examples/images_contours_and_fields/imshow_demo.py rename to examples/images_contours_and_fields/image_demo.py From 5a77ad87ae2ff6ccc488b4af5e3efb74b0663cfa Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 17:05:28 -0800 Subject: [PATCH 19/35] Cleanup and move polar_bar demo --- .../pie_and_polar_charts/polar_bar_demo.py | 21 +++++++++++++++++++ examples/pylab_examples/polar_bar.py | 21 ------------------- examples/tests/backend_driver.py | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) create mode 100644 examples/pie_and_polar_charts/polar_bar_demo.py delete mode 100644 examples/pylab_examples/polar_bar.py diff --git a/examples/pie_and_polar_charts/polar_bar_demo.py b/examples/pie_and_polar_charts/polar_bar_demo.py new file mode 100644 index 000000000000..459dd6f958f1 --- /dev/null +++ b/examples/pie_and_polar_charts/polar_bar_demo.py @@ -0,0 +1,21 @@ +""" +Demo of bar plot on a polar axis. +""" +import numpy as np +import matplotlib.pyplot as plt + + +N = 20 +theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False) +radii = 10 * np.random.rand(N) +width = np.pi / 4 * np.random.rand(N) + +ax = plt.subplot(111, polar=True) +bars = ax.bar(theta, radii, width=width, bottom=0.0) + +# Use custom colors and opacity +for r, bar in zip(radii, bars): + bar.set_facecolor(plt.cm.jet(r / 10.)) + bar.set_alpha(0.5) + +plt.show() diff --git a/examples/pylab_examples/polar_bar.py b/examples/pylab_examples/polar_bar.py deleted file mode 100644 index 14d8d7de0b43..000000000000 --- a/examples/pylab_examples/polar_bar.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python - -import numpy as np -import matplotlib.cm as cm -from matplotlib.pyplot import figure, show, rc - - -# force square figure and square axes looks better for polar, IMO -fig = figure(figsize=(8,8)) -ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True) - -N = 20 -theta = np.arange(0.0, 2*np.pi, 2*np.pi/N) -radii = 10*np.random.rand(N) -width = np.pi/4*np.random.rand(N) -bars = ax.bar(theta, radii, width=width, bottom=0.0) -for r,bar in zip(radii, bars): - bar.set_facecolor( cm.jet(r/10.)) - bar.set_alpha(0.5) - -show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index cca0a3f08cc0..09e8e607b8bc 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -73,6 +73,7 @@ files['pie'] = [ 'pie_demo.py', + 'polar_bar_demo.py', ] files['text_labels_and_annotations'] = [ @@ -207,7 +208,6 @@ 'pcolor_small.py', 'pie_demo2.py', 'plotfile_demo.py', - 'polar_bar.py', 'polar_demo.py', 'polar_legend.py', 'polar_scatter.py', From e4dce4e46fe7c63b60b39b08e6d3f60b08d06f47 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 17:13:44 -0800 Subject: [PATCH 20/35] Cleanup and move polar scatter demo --- .../polar_scatter_demo.py | 21 +++++++++++++++++++ examples/pylab_examples/polar_scatter.py | 17 --------------- examples/tests/backend_driver.py | 2 +- lib/matplotlib/pyplot.py | 2 +- 4 files changed, 23 insertions(+), 19 deletions(-) create mode 100644 examples/pie_and_polar_charts/polar_scatter_demo.py delete mode 100644 examples/pylab_examples/polar_scatter.py diff --git a/examples/pie_and_polar_charts/polar_scatter_demo.py b/examples/pie_and_polar_charts/polar_scatter_demo.py new file mode 100644 index 000000000000..90eea4e2b3a8 --- /dev/null +++ b/examples/pie_and_polar_charts/polar_scatter_demo.py @@ -0,0 +1,21 @@ +""" +Demo of scatter plot on a polar axis. + +Size increases radially in this example and color increases with angle (just to +verify the symbols are being scattered correctly). +""" +import numpy as np +import matplotlib.pyplot as plt + + +N = 150 +r = 2 * np.random.rand(N) +theta = 2 * np.pi * np.random.rand(N) +area = 200 * r**2 * np.random.rand(N) +colors = theta + +ax = plt.subplot(111, polar=True) +c = plt.scatter(theta, r, c=colors, s=area, cmap=plt.cm.hsv) +c.set_alpha(0.75) + +plt.show() diff --git a/examples/pylab_examples/polar_scatter.py b/examples/pylab_examples/polar_scatter.py deleted file mode 100644 index 196f6e847290..000000000000 --- a/examples/pylab_examples/polar_scatter.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python -# a polar scatter plot; size increases radially in this example and -# color increases with angle (just to verify the symbols are being -# scattered correctly). In a real example, this would be wasting -# dimensionality of the plot -from pylab import * - -N = 150 -r = 2*rand(N) -theta = 2*pi*rand(N) -area = 200*r**2*rand(N) -colors = theta -ax = subplot(111, polar=True) -c = scatter(theta, r, c=colors, s=area, cmap=cm.hsv) -c.set_alpha(0.75) - -show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index 09e8e607b8bc..9ae60d0691af 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -74,6 +74,7 @@ files['pie'] = [ 'pie_demo.py', 'polar_bar_demo.py', + 'polar_scatter_demo.py', ] files['text_labels_and_annotations'] = [ @@ -210,7 +211,6 @@ 'plotfile_demo.py', 'polar_demo.py', 'polar_legend.py', - 'polar_scatter.py', 'poormans_contour.py', 'psd_demo.py', 'psd_demo2.py', diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 49754f4606a5..20e6d2eb2d60 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -763,7 +763,7 @@ def subplot(*args, **kwargs): For additional information on :func:`axes` and :func:`subplot` keyword arguments. - :file:`examples/pylab_examples/polar_scatter.py` + :file:`examples/pie_and_polar_charts/polar_scatter_demo.py` For an example **Example:** From cc1850142d2b0bd0412dc882735fe4c917d6981f Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 17:45:44 -0800 Subject: [PATCH 21/35] Cleanup and move text themes demo --- examples/pylab_examples/text_themes.py | 24 ------------------- examples/tests/backend_driver.py | 2 +- .../text_demo_fontdict.py | 23 ++++++++++++++++++ 3 files changed, 24 insertions(+), 25 deletions(-) delete mode 100644 examples/pylab_examples/text_themes.py create mode 100644 examples/text_labels_and_annotations/text_demo_fontdict.py diff --git a/examples/pylab_examples/text_themes.py b/examples/pylab_examples/text_themes.py deleted file mode 100644 index 43dfc39064f8..000000000000 --- a/examples/pylab_examples/text_themes.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -from pylab import * - -font = {'family' : 'serif', - 'color' : 'r', - 'weight' : 'normal', - 'size' : 12, - } - -def f(t): - s1 = cos(2*pi*t) - e1 = exp(-t) - return multiply(s1,e1) - -t1 = arange(0.0, 5.0, 0.1) -t2 = arange(0.0, 5.0, 0.02) - -plot(t1, f(t1), 'bo', t2, f(t2), 'k') -title('Damped exponential decay', font, size='large', color='r') -text(2, 0.65, r'$\cos(2 \pi t) \exp(-t)$', color='k') -xlabel('time (s)', font, style='italic') -ylabel('voltage (mV)', font) - -show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index 9ae60d0691af..ac91b85354e6 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -78,6 +78,7 @@ ] files['text_labels_and_annotations'] = [ + 'text_demo_fontdict.py', 'unicode_demo.py', ] @@ -239,7 +240,6 @@ 'text_handles.py', 'text_rotation.py', 'text_rotation_relative_to_line.py', - 'text_themes.py', 'transoffset.py', 'vline_demo.py', 'xcorr_demo.py', diff --git a/examples/text_labels_and_annotations/text_demo_fontdict.py b/examples/text_labels_and_annotations/text_demo_fontdict.py new file mode 100644 index 000000000000..7924c4cefb0e --- /dev/null +++ b/examples/text_labels_and_annotations/text_demo_fontdict.py @@ -0,0 +1,23 @@ +""" +Demo using fontdict to control style of text and labels. +""" +import numpy as np +import matplotlib.pyplot as plt + + +font = {'family' : 'serif', + 'color' : 'darkred', + 'weight' : 'normal', + 'size' : 16, + } + +x = np.linspace(0.0, 5.0, 100) +y = np.cos(2 * np.pi * x) * np.exp(-x) + +plt.plot(x, y, 'k') +plt.title('Damped exponential decay', fontdict=font) +plt.text(2, 0.65, r'$\cos(2 \pi t) \exp(-t)$', fontdict=font) +plt.xlabel('time (s)', fontdict=font) +plt.ylabel('voltage (mV)', fontdict=font) + +plt.show() From d02d560fdf9b98591d99cd03e51034af9a2d6931 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 20:21:07 -0800 Subject: [PATCH 22/35] Cleanup and move path_patch demo --- doc/users/screenshots.rst | 2 +- .../path_patch_demo.py | 24 +++++++++---------- examples/tests/backend_driver.py | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) rename examples/{api => shapes_and_collections}/path_patch_demo.py (68%) diff --git a/doc/users/screenshots.rst b/doc/users/screenshots.rst index 0a9145d60a8d..e56f31d656ee 100644 --- a/doc/users/screenshots.rst +++ b/doc/users/screenshots.rst @@ -43,7 +43,7 @@ Path demo You can add arbitrary paths in matplotlib as of release 0.98. See the :mod:`matplotlib.path`. -.. plot:: mpl_examples/api/path_patch_demo.py +.. plot:: mpl_examples/shapes_and_collections/path_patch_demo.py .. _screenshots_mplot3d_surface: diff --git a/examples/api/path_patch_demo.py b/examples/shapes_and_collections/path_patch_demo.py similarity index 68% rename from examples/api/path_patch_demo.py rename to examples/shapes_and_collections/path_patch_demo.py index d28fa2c37015..fb0c8aa47592 100644 --- a/examples/api/path_patch_demo.py +++ b/examples/shapes_and_collections/path_patch_demo.py @@ -1,14 +1,15 @@ -import numpy as np +""" +Demo of a PathPatch object. +""" import matplotlib.path as mpath import matplotlib.patches as mpatches import matplotlib.pyplot as plt -Path = mpath.Path -fig = plt.figure() -ax = fig.add_subplot(111) +fig, ax = plt.subplots() -pathdata = [ +Path = mpath.Path +path_data = [ (Path.MOVETO, (1.58, -2.57)), (Path.CURVE4, (0.35, -1.1)), (Path.CURVE4, (-1.75, 2.0)), @@ -19,18 +20,15 @@ (Path.CURVE4, (2.0, -0.5)), (Path.CLOSEPOLY, (1.58, -2.57)), ] - -codes, verts = zip(*pathdata) +codes, verts = zip(*path_data) path = mpath.Path(verts, codes) -patch = mpatches.PathPatch(path, facecolor='red', edgecolor='yellow', alpha=0.5) +patch = mpatches.PathPatch(path, facecolor='r', alpha=0.5) ax.add_patch(patch) +# plot control points and connecting lines x, y = zip(*path.vertices) line, = ax.plot(x, y, 'go-') + ax.grid() -ax.set_xlim(-3,4) -ax.set_ylim(-3,4) -ax.set_title('spline paths') +ax.axis('equal') plt.show() - - diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index ac91b85354e6..7a76ceee3f0b 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -57,6 +57,7 @@ ] files['shapes'] = [ + 'path_patch_demo.py', 'scatter_demo.py', ] @@ -267,7 +268,6 @@ 'logo2.py', 'mathtext_asarray.py', 'patch_collection.py', - 'path_patch_demo.py', 'quad_bezier.py', 'scatter_piecharts.py', 'span_regions.py', From ec8a4875ebbddab3d93a9d1355259d5b52e6f861 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 20:38:01 -0800 Subject: [PATCH 23/35] Clean up and move integral demo --- examples/pylab_examples/integral_demo.py | 34 --------------------- examples/showcase/integral_demo.py | 39 ++++++++++++++++++++++++ examples/tests/backend_driver.py | 5 ++- 3 files changed, 43 insertions(+), 35 deletions(-) delete mode 100644 examples/pylab_examples/integral_demo.py create mode 100644 examples/showcase/integral_demo.py diff --git a/examples/pylab_examples/integral_demo.py b/examples/pylab_examples/integral_demo.py deleted file mode 100644 index 436482ce189a..000000000000 --- a/examples/pylab_examples/integral_demo.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python - -# implement the example graphs/integral from pyx -from pylab import * -from matplotlib.patches import Polygon - -def func(x): - return (x-3)*(x-5)*(x-7)+85 - -ax = subplot(111) - -a, b = 2, 9 # integral area -x = arange(0, 10, 0.01) -y = func(x) -plot(x, y, linewidth=1) - -# make the shaded region -ix = arange(a, b, 0.01) -iy = func(ix) -verts = [(a,0)] + list(zip(ix,iy)) + [(b,0)] -poly = Polygon(verts, facecolor='0.8', edgecolor='k') -ax.add_patch(poly) - -text(0.5 * (a + b), 30, - r"$\int_a^b f(x)\mathrm{d}x$", horizontalalignment='center', - fontsize=20) - -axis([0,10, 0, 180]) -figtext(0.9, 0.05, 'x') -figtext(0.1, 0.9, 'y') -ax.set_xticks((a,b)) -ax.set_xticklabels(('a','b')) -ax.set_yticks([]) -show() diff --git a/examples/showcase/integral_demo.py b/examples/showcase/integral_demo.py new file mode 100644 index 000000000000..9549b132b61e --- /dev/null +++ b/examples/showcase/integral_demo.py @@ -0,0 +1,39 @@ +""" +Plot demonstrating the integral as the area under a curve. +""" +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.patches import Polygon + +def func(x): + return (x-3)*(x-5)*(x-7)+85 + +fig, ax = plt.subplots() + +a, b = 2, 9 # integral area +x = np.linspace(0, 10) +y = func(x) +plt.plot(x, y, 'r', linewidth=2) + +# make the shaded region +ix = np.linspace(a, b) +iy = func(ix) +verts = [(a,0)] + list(zip(ix,iy)) + [(b,0)] +poly = Polygon(verts, facecolor='0.9', edgecolor='0.5') +ax.add_patch(poly) + +plt.text(0.5 * (a + b), 30, + r"$\int_a^b f(x)\mathrm{d}x$", horizontalalignment='center', + fontsize=20) + +plt.axis([0,10, 0, 180]) +plt.figtext(0.9, 0.05, '$x$') +plt.figtext(0.1, 0.9, '$y$') + +ax.spines['right'].set_visible(False) +ax.spines['top'].set_visible(False) +ax.set_xticks((a,b)) +ax.set_xticklabels(('$a$','$b$')) +ax.set_yticks([]) + +plt.show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index 7a76ceee3f0b..497408a70405 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -91,6 +91,10 @@ 'subplot_demo.py', ] +files['showcase'] = [ + 'integral_demo.py', + ] + files['pylab'] = [ 'accented_text.py', 'alignment_test.py', @@ -175,7 +179,6 @@ 'image_nonuniform.py', 'image_origin.py', 'image_slices_viewer.py', - 'integral_demo.py', 'interp_demo.py', 'invert_axes.py', 'layer_images.py', From acc69cced1a0cd25bd11020ed25fc1d4aa5215d3 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 21:47:52 -0800 Subject: [PATCH 24/35] Extract spines_demo_bounds from spine_placement_demo --- .../pylab_examples/spine_placement_demo.py | 37 ------------------- examples/tests/backend_driver.py | 1 + .../ticks_and_spines/spines_demo_bounds.py | 32 ++++++++++++++++ 3 files changed, 33 insertions(+), 37 deletions(-) create mode 100644 examples/ticks_and_spines/spines_demo_bounds.py diff --git a/examples/pylab_examples/spine_placement_demo.py b/examples/pylab_examples/spine_placement_demo.py index 2e80f68f7601..cac90f10278e 100644 --- a/examples/pylab_examples/spine_placement_demo.py +++ b/examples/pylab_examples/spine_placement_demo.py @@ -1,4 +1,3 @@ -import sys import matplotlib.pyplot as plt import numpy as np from matplotlib.pyplot import show @@ -122,40 +121,4 @@ def adjust_spines(ax,spines): ax.plot(x,y) adjust_spines(ax,['bottom']) -# ---------------------------------------------------- - -fig = plt.figure() - -x = np.linspace(0,2*np.pi,50) -y = np.sin(x) -y2 = y + 0.1*np.random.normal( size=x.shape ) - -# plot data -ax = fig.add_subplot(1,1,1) -line1,=ax.plot(x,y,'--') -line2,=ax.plot(x,y2,'bo') - -# adjust the spines -adjust_spines(ax,['left','bottom']) - -# set ticks and tick labels -# x -ax.set_xlim((0,2*np.pi)) -ax.set_xticks([0,np.pi,2*np.pi]) -if sys.version_info[0] < 3: - pichr = unichr(0x03C0) -else: - pichr = chr(0x03C0) -ax.set_xticklabels(['0',pichr,'2 '+pichr]) - -# y -ax.set_yticks([-1,0,1]) - -# disable clipping of data points by axes range -for artist in (line1,line2): - artist.set_clip_on(False) - -# adjust spine to be within ticks -ax.spines['left'].set_bounds( -1, 1 ) - show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index 497408a70405..07afc5bff165 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -84,6 +84,7 @@ ] files['ticks_and_spines'] = [ + 'spines_demo_bounds.py', 'ticklabels_demo_rotation.py', ] diff --git a/examples/ticks_and_spines/spines_demo_bounds.py b/examples/ticks_and_spines/spines_demo_bounds.py new file mode 100644 index 000000000000..9db2591abcae --- /dev/null +++ b/examples/ticks_and_spines/spines_demo_bounds.py @@ -0,0 +1,32 @@ +""" +Demo of spines using custom bounds to limit the extent of the spine. +""" +import numpy as np +import matplotlib.pyplot as plt + + +x = np.linspace(0, 2*np.pi, 50) +y = np.sin(x) +y2 = y + 0.1 * np.random.normal(size=x.shape) + +fig, ax = plt.subplots() +ax.plot(x, y, 'k--') +ax.plot(x, y2, 'ro') + +# set ticks and tick labels +ax.set_xlim((0, 2*np.pi)) +ax.set_xticks([0, np.pi, 2*np.pi]) +ax.set_xticklabels(['0', '$\pi$','2$\pi$']) +ax.set_ylim((-1.5, 1.5)) +ax.set_yticks([-1, 0, 1]) + +# Only draw spine between the y-ticks +ax.spines['left'].set_bounds(-1, 1) +# Hide the right and top spines +ax.spines['right'].set_visible(False) +ax.spines['top'].set_visible(False) +# Only show ticks on the left and bottom spines +ax.yaxis.set_ticks_position('left') +ax.xaxis.set_ticks_position('bottom') + +plt.show() From 800deb4baa13102208dd31c1a9055c2b35a46d34 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 22:07:55 -0800 Subject: [PATCH 25/35] Extract spines_demo from spine_placement_demo --- .../pylab_examples/spine_placement_demo.py | 28 ++---------------- examples/ticks_and_spines/spines_demo.py | 29 +++++++++++++++++++ .../ticks_and_spines/spines_demo_dropped.py | 24 +++++++++++++++ 3 files changed, 55 insertions(+), 26 deletions(-) create mode 100644 examples/ticks_and_spines/spines_demo.py create mode 100644 examples/ticks_and_spines/spines_demo_dropped.py diff --git a/examples/pylab_examples/spine_placement_demo.py b/examples/pylab_examples/spine_placement_demo.py index cac90f10278e..42f925371c43 100644 --- a/examples/pylab_examples/spine_placement_demo.py +++ b/examples/pylab_examples/spine_placement_demo.py @@ -1,30 +1,6 @@ -import matplotlib.pyplot as plt import numpy as np -from matplotlib.pyplot import show - -fig = plt.figure() -x = np.linspace(0,2*np.pi,100) -y = 2*np.sin(x) -ax = fig.add_subplot(1,2,1) -ax.set_title('dropped spines') -ax.plot(x,y) -for loc, spine in ax.spines.items(): - if loc in ['left','bottom']: - spine.set_position(('outward',10)) # outward by 10 points - elif loc in ['right','top']: - spine.set_color('none') # don't draw spine - else: - raise ValueError('unknown spine location: %s'%loc) - -# turn off ticks where there is no spine -ax.xaxis.set_ticks_position('bottom') -ax.yaxis.set_ticks_position('left') - -ax = fig.add_subplot(1,2,2,sharex=ax) -ax.plot(x,y) -ax.set_title('normal spines') +import matplotlib.pyplot as plt -# ---------------------------------------------------- fig = plt.figure() x = np.linspace(-np.pi,np.pi,100) @@ -121,4 +97,4 @@ def adjust_spines(ax,spines): ax.plot(x,y) adjust_spines(ax,['bottom']) -show() +plt.show() diff --git a/examples/ticks_and_spines/spines_demo.py b/examples/ticks_and_spines/spines_demo.py new file mode 100644 index 000000000000..b7b8ad193a89 --- /dev/null +++ b/examples/ticks_and_spines/spines_demo.py @@ -0,0 +1,29 @@ +""" +Basic demo of axis spines. + +This demo compares a normal axes, with spines on all four sides, and an axes +with spines only on the left and bottom. +""" +import numpy as np +import matplotlib.pyplot as plt + + +x = np.linspace(0, 2 * np.pi, 100) +y = 2 * np.sin(x) + +fig, (ax0, ax1) = plt.subplots(ncols=2) + +ax0.plot(x, y) +ax0.set_title('normal spines') + +ax1.plot(x, y) +ax1.set_title('bottom-left spines') + +# Hide the right and top spines +ax1.spines['right'].set_visible(False) +ax1.spines['top'].set_visible(False) +# Only show ticks on the left and bottom spines +ax1.yaxis.set_ticks_position('left') +ax1.xaxis.set_ticks_position('bottom') + +plt.show() diff --git a/examples/ticks_and_spines/spines_demo_dropped.py b/examples/ticks_and_spines/spines_demo_dropped.py new file mode 100644 index 000000000000..1a11e8f58f59 --- /dev/null +++ b/examples/ticks_and_spines/spines_demo_dropped.py @@ -0,0 +1,24 @@ +""" +Demo of spines offset from the axes (a.k.a. "dropped spines"). +""" +import numpy as np +import matplotlib.pyplot as plt + + +fig, ax = plt.subplots() + +image = np.random.uniform(size=(10, 10)) +ax.imshow(image, cmap=plt.cm.gray, interpolation='nearest') +ax.set_title('dropped spines') + +# Move left and bottom spines outward by 10 points +ax.spines['left'].set_position(('outward', 10)) +ax.spines['bottom'].set_position(('outward', 10)) +# Hide the right and top spines +ax.spines['right'].set_visible(False) +ax.spines['top'].set_visible(False) +# Only show ticks on the left and bottom spines +ax.yaxis.set_ticks_position('left') +ax.xaxis.set_ticks_position('bottom') + +plt.show() From edce62b97de206607a40bb9cb3682456ce7c984c Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 22:51:02 -0800 Subject: [PATCH 26/35] Cleanup integral_demo --- examples/showcase/integral_demo.py | 34 ++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/examples/showcase/integral_demo.py b/examples/showcase/integral_demo.py index 9549b132b61e..d55f551fab80 100644 --- a/examples/showcase/integral_demo.py +++ b/examples/showcase/integral_demo.py @@ -1,39 +1,51 @@ """ Plot demonstrating the integral as the area under a curve. + +Although this is a simple example, it demonstrates some important tweaks: + + * A simple line plot with custom color and line width. + * A shaded region created using a Polygon patch. + * A text label with mathtext rendering. + * figtext calls to label the x- and y-axes. + * Use of axis spines to hide the top and right spines. + * Custom tick placement and labels. """ import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Polygon + def func(x): - return (x-3)*(x-5)*(x-7)+85 + return (x - 3) * (x - 5) * (x - 7) + 85 -fig, ax = plt.subplots() -a, b = 2, 9 # integral area +a, b = 2, 9 # integral limits x = np.linspace(0, 10) y = func(x) + +fig, ax = plt.subplots() plt.plot(x, y, 'r', linewidth=2) +plt.ylim(ymin=0) -# make the shaded region +# Make the shaded region ix = np.linspace(a, b) iy = func(ix) -verts = [(a,0)] + list(zip(ix,iy)) + [(b,0)] +verts = [(a, 0)] + list(zip(ix, iy)) + [(b, 0)] poly = Polygon(verts, facecolor='0.9', edgecolor='0.5') ax.add_patch(poly) -plt.text(0.5 * (a + b), 30, - r"$\int_a^b f(x)\mathrm{d}x$", horizontalalignment='center', - fontsize=20) +plt.text(0.5 * (a + b), 30, r"$\int_a^b f(x)\mathrm{d}x$", + horizontalalignment='center', fontsize=20) -plt.axis([0,10, 0, 180]) plt.figtext(0.9, 0.05, '$x$') plt.figtext(0.1, 0.9, '$y$') ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) -ax.set_xticks((a,b)) -ax.set_xticklabels(('$a$','$b$')) +ax.xaxis.set_ticks_position('bottom') + +ax.set_xticks((a, b)) +ax.set_xticklabels(('$a$', '$b$')) ax.set_yticks([]) plt.show() From 405cbc5e6fb92d9c0bcfbca4a5ee2f9352da18fe Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 22 Dec 2012 23:20:56 -0800 Subject: [PATCH 27/35] Cleanup and move dash_control demo --- .../line_demo_dash_control.py | 17 +++++++++++++++++ examples/pylab_examples/dash_control.py | 14 -------------- examples/tests/backend_driver.py | 2 +- 3 files changed, 18 insertions(+), 15 deletions(-) create mode 100644 examples/lines_bars_and_markers/line_demo_dash_control.py delete mode 100644 examples/pylab_examples/dash_control.py diff --git a/examples/lines_bars_and_markers/line_demo_dash_control.py b/examples/lines_bars_and_markers/line_demo_dash_control.py new file mode 100644 index 000000000000..b884c7e28675 --- /dev/null +++ b/examples/lines_bars_and_markers/line_demo_dash_control.py @@ -0,0 +1,17 @@ +""" +Demo of a simple plot with a custom dashed line. + +A Line object's ``set_dashes`` method allows you to specify dashes with +a series of on/off lengths (in points). +""" +import numpy as np +import matplotlib.pyplot as plt + + +x = np.linspace(0, 10) +line, = plt.plot(x, np.sin(x), '--', linewidth=2) + +dashes = [10, 5, 100, 5] # 10 points on, 5 off, 100 on, 5 off +line.set_dashes(dashes) + +plt.show() diff --git a/examples/pylab_examples/dash_control.py b/examples/pylab_examples/dash_control.py deleted file mode 100644 index 1100882b8873..000000000000 --- a/examples/pylab_examples/dash_control.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python - -""" -You can precisely specify dashes with an on/off ink rect sequence in -points. -""" -from pylab import * - -dashes = [5,2,10,5] # 5 points on, 2 off, 3 on, 1 off - -l, = plot(arange(20), '--') -l.set_dashes(dashes) - -show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index 07afc5bff165..73b2c195d780 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -54,6 +54,7 @@ files['lines'] = [ 'fill_demo.py', 'fill_demo_features.py', + 'line_demo_dash_control.py', ] files['shapes'] = [ @@ -135,7 +136,6 @@ 'custom_figure_class.py', 'custom_ticker1.py', 'customize_rc.py', - 'dash_control.py', 'dashpointlabel.py', 'date_demo1.py', 'date_demo2.py', From 30a85ba22246884573f572b758fca25c367bc55c Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sun, 23 Dec 2012 18:25:21 -0800 Subject: [PATCH 28/35] Clean up and move color_cycle demo --- doc/conf.py | 1 + doc/sphinxext/gen_gallery.py | 1 + examples/api/color_cycle.py | 28 ------------------------ examples/color/color_cycle_demo.py | 34 ++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 28 deletions(-) delete mode 100644 examples/api/color_cycle.py create mode 100644 examples/color/color_cycle_demo.py diff --git a/doc/conf.py b/doc/conf.py index 57da9709f3c0..414bddd81812 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -88,6 +88,7 @@ 'statistics', 'images_contours_and_fields', 'pie_and_polar_charts', + 'color', 'text_labels_and_annotations', 'ticks_and_spines', 'subplots_axes_and_figures', diff --git a/doc/sphinxext/gen_gallery.py b/doc/sphinxext/gen_gallery.py index 4311dd745418..967cd8f9b8f6 100644 --- a/doc/sphinxext/gen_gallery.py +++ b/doc/sphinxext/gen_gallery.py @@ -22,6 +22,7 @@ 'subplots_axes_and_figures': 'Subplots, axes, and figures', 'specialty_plots': 'Specialty plots', 'showcase': 'Showcase', + 'color': 'Color', 'api': 'API', } diff --git a/examples/api/color_cycle.py b/examples/api/color_cycle.py deleted file mode 100644 index 6b2abe873cd2..000000000000 --- a/examples/api/color_cycle.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -Illustrate the API for changing the cycle of colors used -when plotting multiple lines on a single Axes. -""" - -import numpy as np -import matplotlib.pyplot as plt -import matplotlib as mpl - -yy = np.arange(24) -yy.shape = 6,4 - -mpl.rc('lines', linewidth=4) - -fig = plt.figure() -mpl.rcParams['axes.color_cycle'] = ['r', 'g', 'b', 'c'] -ax = fig.add_subplot(2,1,1) -ax.plot(yy) -ax.set_title('Changed default color cycle to rgbc') - -ax = fig.add_subplot(2,1,2) -ax.set_color_cycle(['c', 'm', 'y', 'k']) -ax.plot(yy) -ax.set_title('This axes only, cycle is cmyk') - -plt.show() - - diff --git a/examples/color/color_cycle_demo.py b/examples/color/color_cycle_demo.py new file mode 100644 index 000000000000..b453de4c1aed --- /dev/null +++ b/examples/color/color_cycle_demo.py @@ -0,0 +1,34 @@ +""" +Demo of custom color-cycle settings to control colors for multi-line plots. + +This example demonstrates two different APIs: + + 1. Setting the default rc-parameter specifying the color cycle. + This affects all subsequent plots. + 2. Setting the color cycle for a specific axes. This only affects a single + axes. +""" +import numpy as np +import matplotlib.pyplot as plt + +x = np.linspace(0, 2 * np.pi) +offsets = np.linspace(0, 2*np.pi, 4, endpoint=False) +# Create array with shifted-sine curve along each column +yy = np.transpose([np.sin(x + phi) for phi in offsets]) + +plt.rc('lines', linewidth=4) +fig, (ax0, ax1) = plt.subplots(nrows=2) + +plt.rc('axes', color_cycle=['r', 'g', 'b', 'y']) +ax0.plot(yy) +ax0.set_title('Set default color cycle to rgby') + +ax1.set_color_cycle(['c', 'm', 'y', 'k']) +ax1.plot(yy) +ax1.set_title('Set axes color cycle to cmyk') + +# Tweak spacing between subplots to prevent labels from overlapping +plt.subplots_adjust(hspace=0.3) +plt.show() + + From 7175e061cd5f98ca2a0e9097fa456224f59d3397 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sun, 23 Dec 2012 19:56:25 -0800 Subject: [PATCH 29/35] Tweak subplot layout to prevent label clipping --- examples/statistics/histogram_demo_features.py | 2 ++ examples/text_labels_and_annotations/text_demo_fontdict.py | 2 ++ examples/ticks_and_spines/spines_demo.py | 4 +++- examples/ticks_and_spines/ticklabels_demo_rotation.py | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/statistics/histogram_demo_features.py b/examples/statistics/histogram_demo_features.py index d81278fcc9ae..299f9bfeb70c 100644 --- a/examples/statistics/histogram_demo_features.py +++ b/examples/statistics/histogram_demo_features.py @@ -30,4 +30,6 @@ plt.ylabel('Probability') plt.title(r'Histogram of IQ: $\mu=100$, $\sigma=15$') +# Tweak spacing to prevent clipping of ylabel +plt.subplots_adjust(left=0.15) plt.show() diff --git a/examples/text_labels_and_annotations/text_demo_fontdict.py b/examples/text_labels_and_annotations/text_demo_fontdict.py index 7924c4cefb0e..a0dcf3f48d3a 100644 --- a/examples/text_labels_and_annotations/text_demo_fontdict.py +++ b/examples/text_labels_and_annotations/text_demo_fontdict.py @@ -20,4 +20,6 @@ plt.xlabel('time (s)', fontdict=font) plt.ylabel('voltage (mV)', fontdict=font) +# Tweak spacing to prevent clipping of ylabel +plt.subplots_adjust(left=0.15) plt.show() diff --git a/examples/ticks_and_spines/spines_demo.py b/examples/ticks_and_spines/spines_demo.py index b7b8ad193a89..a720131e845c 100644 --- a/examples/ticks_and_spines/spines_demo.py +++ b/examples/ticks_and_spines/spines_demo.py @@ -11,7 +11,7 @@ x = np.linspace(0, 2 * np.pi, 100) y = 2 * np.sin(x) -fig, (ax0, ax1) = plt.subplots(ncols=2) +fig, (ax0, ax1) = plt.subplots(nrows=2) ax0.plot(x, y) ax0.set_title('normal spines') @@ -26,4 +26,6 @@ ax1.yaxis.set_ticks_position('left') ax1.xaxis.set_ticks_position('bottom') +# Tweak spacing between subplots to prevent labels from overlapping +plt.subplots_adjust(hspace=0.5) plt.show() diff --git a/examples/ticks_and_spines/ticklabels_demo_rotation.py b/examples/ticks_and_spines/ticklabels_demo_rotation.py index 0f926fe79c4a..9c1c49b2e4d6 100644 --- a/examples/ticks_and_spines/ticklabels_demo_rotation.py +++ b/examples/ticks_and_spines/ticklabels_demo_rotation.py @@ -13,4 +13,6 @@ plt.xticks(x, labels, rotation='vertical') # Pad margins so that markers don't get clipped by the axes plt.margins(0.2) +# Tweak spacing to prevent clipping of tick-labels +plt.subplots_adjust(bottom=0.15) plt.show() From 502095221d9ac00ff7eb91709236fedac93fdc0f Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sun, 23 Dec 2012 21:56:14 -0800 Subject: [PATCH 30/35] Add colormap references based on show_colormaps --- .../color/colormaps_reference_diverging.py | 32 +++++++++++++++++ .../colormaps_reference_miscellaneous.py | 27 +++++++++++++++ .../color/colormaps_reference_qualitative.py | 34 +++++++++++++++++++ .../color/colormaps_reference_sequential.py | 32 +++++++++++++++++ .../color/colormaps_reference_sequential2.py | 32 +++++++++++++++++ examples/pylab_examples/show_colormaps.py | 4 +++ 6 files changed, 161 insertions(+) create mode 100644 examples/color/colormaps_reference_diverging.py create mode 100644 examples/color/colormaps_reference_miscellaneous.py create mode 100644 examples/color/colormaps_reference_qualitative.py create mode 100644 examples/color/colormaps_reference_sequential.py create mode 100644 examples/color/colormaps_reference_sequential2.py diff --git a/examples/color/colormaps_reference_diverging.py b/examples/color/colormaps_reference_diverging.py new file mode 100644 index 000000000000..5e6b7c9985f0 --- /dev/null +++ b/examples/color/colormaps_reference_diverging.py @@ -0,0 +1,32 @@ +""" +Reference for "diverging" colormaps. + +Diverging colormaps have a median value (usually light in color) and vary +smoothly to two different color tones at high and low values. Diverging +colormaps are ideal when your data has a median value that is significant (e.g. +0, such that positive and negative values are represented by different colors +of the colormap). +""" +import numpy as np +import matplotlib.pyplot as plt + + +gradient = np.linspace(0, 1, 256) +gradient = np.vstack((gradient, gradient)) + +# Note that any of these colormaps can be reversed by appending '_r'. +cmaps = ['BrBG', 'bwr', 'coolwarm', 'PiYG', 'PRGn', 'PuOr', 'RdBu', 'RdGy', + 'RdYlBu', 'RdYlGn', 'seismic'] + +fig, axes = plt.subplots(nrows=len(cmaps)) +fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) + +for ax, m in zip(axes, cmaps): + ax.set_axis_off() + ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) + pos = list(ax.get_position().bounds) + x_text = pos[0] - 0.01 + y_text = pos[1] + pos[3]/2. + fig.text(x_text, y_text, m, va='center', ha='right') + +plt.show() diff --git a/examples/color/colormaps_reference_miscellaneous.py b/examples/color/colormaps_reference_miscellaneous.py new file mode 100644 index 000000000000..f7c1cb6fba35 --- /dev/null +++ b/examples/color/colormaps_reference_miscellaneous.py @@ -0,0 +1,27 @@ +""" +Reference for "miscellaneous" colormaps. +""" +import numpy as np +import matplotlib.pyplot as plt + + +gradient = np.linspace(0, 1, 256) +gradient = np.vstack((gradient, gradient)) + +# Note that any of these colormaps can be reversed by appending '_r'. +cmaps = ['flag', 'gist_earth', 'gist_ncar', 'gist_rainbow', 'gist_stern', + 'jet', 'prism', 'brg', 'CMRmap', 'cubehelix', 'gnuplot', 'gnuplot2', + 'ocean', 'rainbow', 'terrain'] + +fig, axes = plt.subplots(nrows=len(cmaps)) +fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) + +for ax, m in zip(axes, cmaps): + ax.set_axis_off() + ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) + pos = list(ax.get_position().bounds) + x_text = pos[0] - 0.01 + y_text = pos[1] + pos[3]/2. + fig.text(x_text, y_text, m, va='center', ha='right') + +plt.show() diff --git a/examples/color/colormaps_reference_qualitative.py b/examples/color/colormaps_reference_qualitative.py new file mode 100644 index 000000000000..eb63bfa94841 --- /dev/null +++ b/examples/color/colormaps_reference_qualitative.py @@ -0,0 +1,34 @@ +""" +Reference for "qualitative" colormaps. + +Qualitative colormaps vary rapidly in color. These colormaps are useful for +choosing a set of discrete colors. For example:: + + color_list = plt.cm.Set3(np.linspace(0, 1, 12)) + +gives a list of RGB colors that are good for plotting a series of lines on +a dark background. +""" +import numpy as np +import matplotlib.pyplot as plt + + +gradient = np.linspace(0, 1, 256) +gradient = np.vstack((gradient, gradient)) + +# Note that any of these colormaps can be reversed by appending '_r'. +cmaps = ['Accent', 'Dark2', 'hsv', 'Paired', 'Pastel1', 'Pastel2', 'Set1', + 'Set2', 'Set3', 'spectral'] + +fig, axes = plt.subplots(nrows=len(cmaps)) +fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) + +for ax, m in zip(axes, cmaps): + ax.set_axis_off() + ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) + pos = list(ax.get_position().bounds) + x_text = pos[0] - 0.01 + y_text = pos[1] + pos[3]/2. + fig.text(x_text, y_text, m, va='center', ha='right') + +plt.show() diff --git a/examples/color/colormaps_reference_sequential.py b/examples/color/colormaps_reference_sequential.py new file mode 100644 index 000000000000..515471db36bb --- /dev/null +++ b/examples/color/colormaps_reference_sequential.py @@ -0,0 +1,32 @@ +""" +Reference for "sequential" colormaps. + +Sequential colormaps are approximately monochromatic colormaps going from low +saturation (e.g. white) to high saturation (e.g. a bright blue). Sequential +colormaps are ideal for representing most scientific data since they show +a clear progression from low-to-high values. +""" +import numpy as np +import matplotlib.pyplot as plt + + +gradient = np.linspace(0, 1, 256) +gradient = np.vstack((gradient, gradient)) + +# Note that any of these colormaps can be reversed by appending '_r'. +cmaps = ['binary', 'Blues', 'BuGn', 'BuPu', 'gist_yarg', 'GnBu', 'Greens', + 'Greys', 'Oranges', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'Purples', + 'RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd'] + +fig, axes = plt.subplots(nrows=len(cmaps)) +fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) + +for ax, m in zip(axes, cmaps): + ax.set_axis_off() + ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) + pos = list(ax.get_position().bounds) + x_text = pos[0] - 0.01 + y_text = pos[1] + pos[3]/2. + fig.text(x_text, y_text, m, va='center', ha='right') + +plt.show() diff --git a/examples/color/colormaps_reference_sequential2.py b/examples/color/colormaps_reference_sequential2.py new file mode 100644 index 000000000000..7bf354fcd1ce --- /dev/null +++ b/examples/color/colormaps_reference_sequential2.py @@ -0,0 +1,32 @@ +""" +Reference for "sequential" colormaps. + +These are sequential colormaps, which vary smoothly between two color tones. +Unlike the sequential colormaps in the first example, these either vary between +two saturated tones (instead of being nearly monochromatic) or have a reversed +progression (decreasing in saturation for increasing value). Note, however, +that any colormap can be reversed by appending "_r" (e.g., "pink_r"). +""" +import numpy as np +import matplotlib.pyplot as plt + + +gradient = np.linspace(0, 1, 256) +gradient = np.vstack((gradient, gradient)) + +# Note that any of these colormaps can be reversed by appending '_r'. +cmaps = ['afmhot', 'autumn', 'bone', 'cool', 'copper', 'gist_gray', + 'gist_heat', 'gray', 'hot', 'pink', 'spring', 'summer', 'winter'] + +fig, axes = plt.subplots(nrows=len(cmaps)) +fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) + +for ax, m in zip(axes, cmaps): + ax.set_axis_off() + ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) + pos = list(ax.get_position().bounds) + x_text = pos[0] - 0.01 + y_text = pos[1] + pos[3]/2. + fig.text(x_text, y_text, m, va='center', ha='right') + +plt.show() diff --git a/examples/pylab_examples/show_colormaps.py b/examples/pylab_examples/show_colormaps.py index 0146a93c07ed..c2066b579bd7 100644 --- a/examples/pylab_examples/show_colormaps.py +++ b/examples/pylab_examples/show_colormaps.py @@ -1,3 +1,7 @@ +# NOTE: This example has been superseded by examples in +# 'color/colormaps_reference_*, but this example is referenced in the +# "What's New" page, and the image tutorial. + # This example comes from the Cookbook on www.scipy.org. According to the # history, Andrew Straw did the conversion from an old page, but it is # unclear who the original author is. From fae23d66d3519403f5ae466812f48b5743042ba9 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sun, 23 Dec 2012 23:30:45 -0800 Subject: [PATCH 31/35] Clean up and move artist demo --- examples/api/artist_demo.py | 119 ------------------ .../artist_reference.py | 104 +++++++++++++++ 2 files changed, 104 insertions(+), 119 deletions(-) delete mode 100644 examples/api/artist_demo.py create mode 100644 examples/shapes_and_collections/artist_reference.py diff --git a/examples/api/artist_demo.py b/examples/api/artist_demo.py deleted file mode 100644 index 35dc77759c63..000000000000 --- a/examples/api/artist_demo.py +++ /dev/null @@ -1,119 +0,0 @@ -""" -Show examples of matplotlib artists -http://matplotlib.org/api/artist_api.html - -Several examples of standard matplotlib graphics primitives (artists) -are drawn using matplotlib API. Full list of artists and the -documentation is available at -http://matplotlib.org/api/artist_api.html - -Copyright (c) 2010, Bartosz Telenczuk - -License: This work is licensed under the BSD. A copy should be -included with this source code, and is also available at -http://www.opensource.org/licenses/bsd-license.php -""" - - -import numpy as np -import matplotlib.pyplot as plt -import matplotlib -from matplotlib.collections import PatchCollection -import matplotlib.path as mpath -import matplotlib.patches as mpatches -import matplotlib.lines as mlines - -font = "sans-serif" -fig = plt.figure(figsize=(5,5)) -ax = plt.axes([0,0,1,1]) - -# create 3x3 grid to plot the artists -pos = np.mgrid[0.2:0.8:3j, 0.2:0.8:3j].reshape(2, -1) - -patches = [] - -# add a circle -art = mpatches.Circle(pos[:,0], 0.1,ec="none") -patches.append(art) -plt.text(pos[0,0], pos[1,0]-0.15, "Circle", ha="center", - family=font, size=14) - -# add a rectangle -art = mpatches.Rectangle(pos[:,1] - np.array([0.025, 0.05]), 0.05, 0.1, - ec="none") -patches.append(art) -plt.text(pos[0,1], pos[1,1]-0.15, "Rectangle", ha="center", - family=font, size=14) - -# add a wedge -wedge = mpatches.Wedge(pos[:,2], 0.1, 30, 270, ec="none") -patches.append(wedge) -plt.text(pos[0,2], pos[1,2]-0.15, "Wedge", ha="center", - family=font, size=14) - -# add a Polygon -polygon = mpatches.RegularPolygon(pos[:,3], 5, 0.1) -patches.append(polygon) -plt.text(pos[0,3], pos[1,3]-0.15, "Polygon", ha="center", - family=font, size=14) - -#add an ellipse -ellipse = mpatches.Ellipse(pos[:,4], 0.2, 0.1) -patches.append(ellipse) -plt.text(pos[0,4], pos[1,4]-0.15, "Ellipse", ha="center", - family=font, size=14) - -#add an arrow -arrow = mpatches.Arrow(pos[0,5]-0.05, pos[1,5]-0.05, 0.1, 0.1, width=0.1) -patches.append(arrow) -plt.text(pos[0,5], pos[1,5]-0.15, "Arrow", ha="center", - family=font, size=14) - -# add a path patch -Path = mpath.Path -verts = np.array([ - (0.158, -0.257), - (0.035, -0.11), - (-0.175, 0.20), - (0.0375, 0.20), - (0.085, 0.115), - (0.22, 0.32), - (0.3, 0.005), - (0.20, -0.05), - (0.158, -0.257), - ]) -verts = verts-verts.mean(0) -codes = [Path.MOVETO, - Path.CURVE4, Path.CURVE4, Path.CURVE4, Path.LINETO, - Path.CURVE4, Path.CURVE4, Path.CURVE4, Path.CLOSEPOLY] - -path = mpath.Path(verts/2.5+pos[:,6], codes) -patch = mpatches.PathPatch(path) -patches.append(patch) -plt.text(pos[0,6], pos[1,6]-0.15, "PathPatch", ha="center", - family=font, size=14) - -# add a fancy box -fancybox = mpatches.FancyBboxPatch( - pos[:,7]-np.array([0.025, 0.05]), 0.05, 0.1, - boxstyle=mpatches.BoxStyle("Round", pad=0.02)) -patches.append(fancybox) -plt.text(pos[0,7], pos[1,7]-0.15, "FancyBoxPatch", ha="center", - family=font, size=14) - -# add a line -x,y = np.array([[-0.06, 0.0, 0.1], [0.05,-0.05, 0.05]]) -line = mlines.Line2D(x+pos[0,8], y+pos[1,8], lw=5., - alpha=0.4) -plt.text(pos[0,8], pos[1,8]-0.15, "Line2D", ha="center", - family=font, size=14) - -colors = 100*np.random.rand(len(patches)) -collection = PatchCollection(patches, cmap=matplotlib.cm.jet, alpha=0.4) -collection.set_array(np.array(colors)) -ax.add_collection(collection) -ax.add_line(line) -ax.set_xticks([]) -ax.set_yticks([]) - -plt.show() diff --git a/examples/shapes_and_collections/artist_reference.py b/examples/shapes_and_collections/artist_reference.py new file mode 100644 index 000000000000..a9016de58949 --- /dev/null +++ b/examples/shapes_and_collections/artist_reference.py @@ -0,0 +1,104 @@ +""" +Reference for matplotlib artists + +This example displays several of matplotlib's graphics primitives (artists) +drawn using matplotlib API. A full list of artists and the documentation is +available at http://matplotlib.org/api/artist_api.html. + +Copyright (c) 2010, Bartosz Telenczuk +BSD License +""" +import matplotlib.pyplot as plt; plt.rcdefaults() +from mpltools import style; style.use('gallery') + +import numpy as np +import matplotlib.pyplot as plt +import matplotlib.path as mpath +import matplotlib.lines as mlines +import matplotlib.patches as mpatches +from matplotlib.collections import PatchCollection + + +def label(xy, text): + y = xy[1] - 0.15 # shift y-value for label so that it's below the artist + plt.text(xy[0], y, text, ha="center", family='sans-serif', size=14) + + +fig, ax = plt.subplots() +# create 3x3 grid to plot the artists +grid = np.mgrid[0.2:0.8:3j, 0.2:0.8:3j].reshape(2, -1).T + +patches = [] + +# add a circle +circle = mpatches.Circle(grid[0], 0.1,ec="none") +patches.append(circle) +label(grid[0], "Circle") + +# add a rectangle +rect = mpatches.Rectangle(grid[1] - [0.025, 0.05], 0.05, 0.1, ec="none") +patches.append(rect) +label(grid[1], "Rectangle") + +# add a wedge +wedge = mpatches.Wedge(grid[2], 0.1, 30, 270, ec="none") +patches.append(wedge) +label(grid[2], "Wedge") + +# add a Polygon +polygon = mpatches.RegularPolygon(grid[3], 5, 0.1) +patches.append(polygon) +label(grid[3], "Polygon") + +#add an ellipse +ellipse = mpatches.Ellipse(grid[4], 0.2, 0.1) +patches.append(ellipse) +label(grid[4], "Ellipse") + +#add an arrow +arrow = mpatches.Arrow(grid[5, 0]-0.05, grid[5, 1]-0.05, 0.1, 0.1, width=0.1) +patches.append(arrow) +label(grid[5], "Arrow") + +# add a path patch +Path = mpath.Path +path_data = [ + (Path.MOVETO, [ 0.018, -0.11 ]), + (Path.CURVE4, [-0.031, -0.051]), + (Path.CURVE4, [-0.115, 0.073]), + (Path.CURVE4, [-0.03 , 0.073]), + (Path.LINETO, [-0.011, 0.039]), + (Path.CURVE4, [ 0.043, 0.121]), + (Path.CURVE4, [ 0.075, -0.005]), + (Path.CURVE4, [ 0.035, -0.027]), + (Path.CLOSEPOLY, [0.018, -0.11]) + ] +codes, verts = zip(*path_data) +path = mpath.Path(verts + grid[6], codes) +patch = mpatches.PathPatch(path) +patches.append(patch) +label(grid[6], "PathPatch") + +# add a fancy box +fancybox = mpatches.FancyBboxPatch( + grid[7] - [0.025, 0.05], 0.05, 0.1, + boxstyle=mpatches.BoxStyle("Round", pad=0.02)) +patches.append(fancybox) +label(grid[7], "FancyBoxPatch") + +# add a line +x,y = np.array([[-0.06, 0.0, 0.1], [0.05, -0.05, 0.05]]) +line = mlines.Line2D(x + grid[8, 0], y + grid[8, 1], lw=5., alpha=0.3) +label(grid[8], "Line2D") + +colors = np.linspace(0, 1, len(patches)) +collection = PatchCollection(patches, cmap=plt.cm.hsv, alpha=0.3) +collection.set_array(np.array(colors)) +ax.add_collection(collection) +ax.add_line(line) + +plt.subplots_adjust(left=0, right=1, bottom=0, top=1) +plt.axis('equal') +plt.axis('off') + +plt.show() From abfdea4979ccad76255ac535ccf2bb92b9bb0efa Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sun, 23 Dec 2012 23:31:55 -0800 Subject: [PATCH 32/35] Clean up and move streamplot demos --- doc/users/whats_new.rst | 2 +- .../streamplot_demo_features.py} | 10 ++++++++++ .../streamplot_demo_masking.py} | 10 +++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) rename examples/{pylab_examples/streamplot_demo.py => images_contours_and_fields/streamplot_demo_features.py} (57%) rename examples/{pylab_examples/streamplot_with_mask.py => images_contours_and_fields/streamplot_demo_masking.py} (55%) diff --git a/doc/users/whats_new.rst b/doc/users/whats_new.rst index 5ba32223fae4..8f243e7e93fc 100644 --- a/doc/users/whats_new.rst +++ b/doc/users/whats_new.rst @@ -195,7 +195,7 @@ In addition to simply plotting the streamlines of the vector field, line widths of the streamlines to a separate parameter, such as the speed or local intensity of the vector field. -.. plot:: mpl_examples/pylab_examples/streamplot_demo.py +.. plot:: mpl_examples/images_contours_and_fields/streamplot_demo_features.py New hist functionality diff --git a/examples/pylab_examples/streamplot_demo.py b/examples/images_contours_and_fields/streamplot_demo_features.py similarity index 57% rename from examples/pylab_examples/streamplot_demo.py rename to examples/images_contours_and_fields/streamplot_demo_features.py index f67e3515c908..2cc10bf877e8 100644 --- a/examples/pylab_examples/streamplot_demo.py +++ b/examples/images_contours_and_fields/streamplot_demo_features.py @@ -1,3 +1,13 @@ +""" +Demo of the `streamplot` function. + +A streamplot, or streamline plot, is used to display 2D vector fields. This +example shows a few features of the stream plot function: + + * Varying the color along a streamline. + * Varying the density of streamlines. + * Varying the line width along a stream line. +""" import numpy as np import matplotlib.pyplot as plt diff --git a/examples/pylab_examples/streamplot_with_mask.py b/examples/images_contours_and_fields/streamplot_demo_masking.py similarity index 55% rename from examples/pylab_examples/streamplot_with_mask.py rename to examples/images_contours_and_fields/streamplot_demo_masking.py index c989b0060620..ce0ac99b9410 100644 --- a/examples/pylab_examples/streamplot_with_mask.py +++ b/examples/images_contours_and_fields/streamplot_demo_masking.py @@ -1,6 +1,8 @@ """ -Demonstrate the use of the `streamplot` function using a masked array -and NaN values. +Demo of the streamplot function with masking. + +This example shows how streamlines created by the streamplot function skips +masked regions and NaN values. """ import numpy as np import matplotlib.pyplot as plt @@ -17,7 +19,9 @@ U[:20, :20] = np.nan plt.streamplot(X, Y, U, V, color='r') -plt.imshow(~mask, extent=(-w, w, -w, w), alpha=0.5, interpolation='nearest') + +plt.imshow(~mask, extent=(-w, w, -w, w), alpha=0.5, + interpolation='nearest', cmap=plt.cm.gray) plt.show() From 8f4be5bdffecb37bda6d8208d33cce83252ae3c3 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 24 Dec 2012 11:27:12 -0800 Subject: [PATCH 33/35] Combine colormap reference examples --- doc/users/image_tutorial.rst | 2 +- doc/users/whats_new.rst | 2 +- examples/color/colormaps_reference.py | 79 +++++++++++++++++++ .../color/colormaps_reference_diverging.py | 32 -------- .../colormaps_reference_miscellaneous.py | 27 ------- .../color/colormaps_reference_qualitative.py | 34 -------- .../color/colormaps_reference_sequential.py | 32 -------- .../color/colormaps_reference_sequential2.py | 32 -------- examples/pylab_examples/show_colormaps.py | 29 ------- 9 files changed, 81 insertions(+), 188 deletions(-) create mode 100644 examples/color/colormaps_reference.py delete mode 100644 examples/color/colormaps_reference_diverging.py delete mode 100644 examples/color/colormaps_reference_miscellaneous.py delete mode 100644 examples/color/colormaps_reference_qualitative.py delete mode 100644 examples/color/colormaps_reference_sequential.py delete mode 100644 examples/color/colormaps_reference_sequential2.py delete mode 100644 examples/pylab_examples/show_colormaps.py diff --git a/doc/users/image_tutorial.rst b/doc/users/image_tutorial.rst index 1ccfb5a8a395..bcc21132c450 100644 --- a/doc/users/image_tutorial.rst +++ b/doc/users/image_tutorial.rst @@ -228,7 +228,7 @@ object: There are many other colormap schemes available. See the `list and images of the colormaps -`_. +`_. .. _`Color Bars`: diff --git a/doc/users/whats_new.rst b/doc/users/whats_new.rst index 8f243e7e93fc..e54dc4f1af7d 100644 --- a/doc/users/whats_new.rst +++ b/doc/users/whats_new.rst @@ -442,7 +442,7 @@ Other improvements * Pim Schellart added a new colormap called "cubehelix". Sameer Grover also added a colormap called "coolwarm". See it and all - other colormaps :ref:`here `. + other colormaps :ref:`here `. * Many bug fixes and documentation improvements. diff --git a/examples/color/colormaps_reference.py b/examples/color/colormaps_reference.py new file mode 100644 index 000000000000..1c433794e4e1 --- /dev/null +++ b/examples/color/colormaps_reference.py @@ -0,0 +1,79 @@ +""" +Reference for colormaps included with Matplotlib. + +This reference example shows all colormaps included with Matplotlib. Note that +any colormap listed here can be reversed by appending "_r" (e.g., "pink_r"). +These colormaps are divided into the following categories: + +Sequential: + These colormaps are approximately monochromatic colormaps varying smoothly + between two color tones---usually from low saturation (e.g. white) to high + saturation (e.g. a bright blue). Sequential colormaps are ideal for + representing most scientific data since they show a clear progression from + low-to-high values. + +Diverging: + These colormaps have a median value (usually light in color) and vary + smoothly to two different color tones at high and low values. Diverging + colormaps are ideal when your data has a median value that is significant + (e.g. 0, such that positive and negative values are represented by + different colors of the colormap). + +Qualitative: + These colormaps vary rapidly in color. Qualitative colormaps are useful for + choosing a set of discrete colors. For example:: + + color_list = plt.cm.Set3(np.linspace(0, 1, 12)) + + gives a list of RGB colors that are good for plotting a series of lines on + a dark background. + +Miscellaneous: + Colormaps that don't fit into the categories above. + +""" +import numpy as np +import matplotlib.pyplot as plt + + +cmaps = [('Sequential', ['binary', 'Blues', 'BuGn', 'BuPu', 'gist_yarg', + 'GnBu', 'Greens', 'Greys', 'Oranges', 'OrRd', + 'PuBu', 'PuBuGn', 'PuRd', 'Purples', 'RdPu', + 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd']), + ('Sequential (2)', ['afmhot', 'autumn', 'bone', 'cool', 'copper', + 'gist_gray', 'gist_heat', 'gray', 'hot', 'pink', + 'spring', 'summer', 'winter']), + ('Diverging', ['BrBG', 'bwr', 'coolwarm', 'PiYG', 'PRGn', 'PuOr', + 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn', 'seismic']), + ('Qualitative', ['Accent', 'Dark2', 'hsv', 'Paired', 'Pastel1', + 'Pastel2', 'Set1', 'Set2', 'Set3', 'spectral']), + ('Miscellaneous', ['gist_earth', 'gist_ncar', 'gist_rainbow', + 'gist_stern', 'jet', 'brg', 'CMRmap', 'cubehelix', + 'gnuplot', 'gnuplot2', 'ocean', 'rainbow', + 'terrain', 'flag', 'prism'])] + + +nrows = max(len(cmap_list) for cmap_category, cmap_list in cmaps) +gradient = np.linspace(0, 1, 256) +gradient = np.vstack((gradient, gradient)) + +def plot_color_gradients(cmap_category, cmap_list): + fig, axes = plt.subplots(nrows=nrows) + fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99) + axes[0].set_title(cmap_category + ' colormaps', fontsize=14) + + for ax, name in zip(axes, cmap_list): + ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(name)) + pos = list(ax.get_position().bounds) + x_text = pos[0] - 0.01 + y_text = pos[1] + pos[3]/2. + fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10) + + # Turn off *all* ticks & spines, not just the ones with colormaps. + for ax in axes: + ax.set_axis_off() + +for cmap_category, cmap_list in cmaps: + plot_color_gradients(cmap_category, cmap_list) + +plt.show() diff --git a/examples/color/colormaps_reference_diverging.py b/examples/color/colormaps_reference_diverging.py deleted file mode 100644 index 5e6b7c9985f0..000000000000 --- a/examples/color/colormaps_reference_diverging.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Reference for "diverging" colormaps. - -Diverging colormaps have a median value (usually light in color) and vary -smoothly to two different color tones at high and low values. Diverging -colormaps are ideal when your data has a median value that is significant (e.g. -0, such that positive and negative values are represented by different colors -of the colormap). -""" -import numpy as np -import matplotlib.pyplot as plt - - -gradient = np.linspace(0, 1, 256) -gradient = np.vstack((gradient, gradient)) - -# Note that any of these colormaps can be reversed by appending '_r'. -cmaps = ['BrBG', 'bwr', 'coolwarm', 'PiYG', 'PRGn', 'PuOr', 'RdBu', 'RdGy', - 'RdYlBu', 'RdYlGn', 'seismic'] - -fig, axes = plt.subplots(nrows=len(cmaps)) -fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) - -for ax, m in zip(axes, cmaps): - ax.set_axis_off() - ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) - pos = list(ax.get_position().bounds) - x_text = pos[0] - 0.01 - y_text = pos[1] + pos[3]/2. - fig.text(x_text, y_text, m, va='center', ha='right') - -plt.show() diff --git a/examples/color/colormaps_reference_miscellaneous.py b/examples/color/colormaps_reference_miscellaneous.py deleted file mode 100644 index f7c1cb6fba35..000000000000 --- a/examples/color/colormaps_reference_miscellaneous.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Reference for "miscellaneous" colormaps. -""" -import numpy as np -import matplotlib.pyplot as plt - - -gradient = np.linspace(0, 1, 256) -gradient = np.vstack((gradient, gradient)) - -# Note that any of these colormaps can be reversed by appending '_r'. -cmaps = ['flag', 'gist_earth', 'gist_ncar', 'gist_rainbow', 'gist_stern', - 'jet', 'prism', 'brg', 'CMRmap', 'cubehelix', 'gnuplot', 'gnuplot2', - 'ocean', 'rainbow', 'terrain'] - -fig, axes = plt.subplots(nrows=len(cmaps)) -fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) - -for ax, m in zip(axes, cmaps): - ax.set_axis_off() - ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) - pos = list(ax.get_position().bounds) - x_text = pos[0] - 0.01 - y_text = pos[1] + pos[3]/2. - fig.text(x_text, y_text, m, va='center', ha='right') - -plt.show() diff --git a/examples/color/colormaps_reference_qualitative.py b/examples/color/colormaps_reference_qualitative.py deleted file mode 100644 index eb63bfa94841..000000000000 --- a/examples/color/colormaps_reference_qualitative.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Reference for "qualitative" colormaps. - -Qualitative colormaps vary rapidly in color. These colormaps are useful for -choosing a set of discrete colors. For example:: - - color_list = plt.cm.Set3(np.linspace(0, 1, 12)) - -gives a list of RGB colors that are good for plotting a series of lines on -a dark background. -""" -import numpy as np -import matplotlib.pyplot as plt - - -gradient = np.linspace(0, 1, 256) -gradient = np.vstack((gradient, gradient)) - -# Note that any of these colormaps can be reversed by appending '_r'. -cmaps = ['Accent', 'Dark2', 'hsv', 'Paired', 'Pastel1', 'Pastel2', 'Set1', - 'Set2', 'Set3', 'spectral'] - -fig, axes = plt.subplots(nrows=len(cmaps)) -fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) - -for ax, m in zip(axes, cmaps): - ax.set_axis_off() - ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) - pos = list(ax.get_position().bounds) - x_text = pos[0] - 0.01 - y_text = pos[1] + pos[3]/2. - fig.text(x_text, y_text, m, va='center', ha='right') - -plt.show() diff --git a/examples/color/colormaps_reference_sequential.py b/examples/color/colormaps_reference_sequential.py deleted file mode 100644 index 515471db36bb..000000000000 --- a/examples/color/colormaps_reference_sequential.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Reference for "sequential" colormaps. - -Sequential colormaps are approximately monochromatic colormaps going from low -saturation (e.g. white) to high saturation (e.g. a bright blue). Sequential -colormaps are ideal for representing most scientific data since they show -a clear progression from low-to-high values. -""" -import numpy as np -import matplotlib.pyplot as plt - - -gradient = np.linspace(0, 1, 256) -gradient = np.vstack((gradient, gradient)) - -# Note that any of these colormaps can be reversed by appending '_r'. -cmaps = ['binary', 'Blues', 'BuGn', 'BuPu', 'gist_yarg', 'GnBu', 'Greens', - 'Greys', 'Oranges', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'Purples', - 'RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd'] - -fig, axes = plt.subplots(nrows=len(cmaps)) -fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) - -for ax, m in zip(axes, cmaps): - ax.set_axis_off() - ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) - pos = list(ax.get_position().bounds) - x_text = pos[0] - 0.01 - y_text = pos[1] + pos[3]/2. - fig.text(x_text, y_text, m, va='center', ha='right') - -plt.show() diff --git a/examples/color/colormaps_reference_sequential2.py b/examples/color/colormaps_reference_sequential2.py deleted file mode 100644 index 7bf354fcd1ce..000000000000 --- a/examples/color/colormaps_reference_sequential2.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Reference for "sequential" colormaps. - -These are sequential colormaps, which vary smoothly between two color tones. -Unlike the sequential colormaps in the first example, these either vary between -two saturated tones (instead of being nearly monochromatic) or have a reversed -progression (decreasing in saturation for increasing value). Note, however, -that any colormap can be reversed by appending "_r" (e.g., "pink_r"). -""" -import numpy as np -import matplotlib.pyplot as plt - - -gradient = np.linspace(0, 1, 256) -gradient = np.vstack((gradient, gradient)) - -# Note that any of these colormaps can be reversed by appending '_r'. -cmaps = ['afmhot', 'autumn', 'bone', 'cool', 'copper', 'gist_gray', - 'gist_heat', 'gray', 'hot', 'pink', 'spring', 'summer', 'winter'] - -fig, axes = plt.subplots(nrows=len(cmaps)) -fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) - -for ax, m in zip(axes, cmaps): - ax.set_axis_off() - ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(m)) - pos = list(ax.get_position().bounds) - x_text = pos[0] - 0.01 - y_text = pos[1] + pos[3]/2. - fig.text(x_text, y_text, m, va='center', ha='right') - -plt.show() diff --git a/examples/pylab_examples/show_colormaps.py b/examples/pylab_examples/show_colormaps.py deleted file mode 100644 index c2066b579bd7..000000000000 --- a/examples/pylab_examples/show_colormaps.py +++ /dev/null @@ -1,29 +0,0 @@ -# NOTE: This example has been superseded by examples in -# 'color/colormaps_reference_*, but this example is referenced in the -# "What's New" page, and the image tutorial. - -# This example comes from the Cookbook on www.scipy.org. According to the -# history, Andrew Straw did the conversion from an old page, but it is -# unclear who the original author is. -import numpy as np -import matplotlib.pyplot as plt - -a = np.linspace(0, 1, 256).reshape(1,-1) -a = np.vstack((a,a)) - -# Get a list of the colormaps in matplotlib. Ignore the ones that end with -# '_r' because these are simply reversed versions of ones that don't end -# with '_r' -maps = sorted(m for m in plt.cm.datad if not m.endswith("_r")) -nmaps = len(maps) + 1 - -fig = plt.figure(figsize=(5,10)) -fig.subplots_adjust(top=0.99, bottom=0.01, left=0.2, right=0.99) -for i,m in enumerate(maps): - ax = plt.subplot(nmaps, 1, i+1) - plt.axis("off") - plt.imshow(a, aspect='auto', cmap=plt.get_cmap(m), origin='lower') - pos = list(ax.get_position().bounds) - fig.text(pos[0] - 0.01, pos[1], m, fontsize=10, horizontalalignment='right') - -plt.show() From 917c329a74b209fe0880b9545f9ba4272d476f83 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Mon, 24 Dec 2012 11:44:33 -0800 Subject: [PATCH 34/35] Clean up and move barh_demo --- examples/lines_bars_and_markers/barh_demo.py | 21 ++++++++++++++++++++ examples/pylab_examples/barh_demo.py | 20 ------------------- examples/tests/backend_driver.py | 2 +- 3 files changed, 22 insertions(+), 21 deletions(-) create mode 100644 examples/lines_bars_and_markers/barh_demo.py delete mode 100644 examples/pylab_examples/barh_demo.py diff --git a/examples/lines_bars_and_markers/barh_demo.py b/examples/lines_bars_and_markers/barh_demo.py new file mode 100644 index 000000000000..b0087acb1eb3 --- /dev/null +++ b/examples/lines_bars_and_markers/barh_demo.py @@ -0,0 +1,21 @@ +""" +Simple demo of a horizontal bar chart. +""" +import matplotlib.pyplot as plt; plt.rcdefaults() +from mpltools import style; style.use('gallery') +import numpy as np +import matplotlib.pyplot as plt + + +# Example data +people = ('Tom', 'Dick', 'Harry', 'Slim', 'Jim') +y_pos = np.arange(len(people)) +performance = 3 + 10 * np.random.rand(len(people)) +error = np.random.rand(len(people)) + +plt.barh(y_pos, performance, xerr=error, align='center', alpha=0.4) +plt.yticks(y_pos, people) +plt.xlabel('Performance') +plt.title('How fast do you want to go today?') + +plt.show() diff --git a/examples/pylab_examples/barh_demo.py b/examples/pylab_examples/barh_demo.py deleted file mode 100644 index 0daef263fd37..000000000000 --- a/examples/pylab_examples/barh_demo.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -# make a horizontal bar chart - -from pylab import * -val = 3+10*rand(5) # the bar lengths -pos = arange(5)+.5 # the bar centers on the y axis - -figure(1) -barh(pos,val, align='center') -yticks(pos, ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')) -xlabel('Performance') -title('How fast do you want to go today?') -grid(True) - -figure(2) -barh(pos,val, xerr=rand(5), ecolor='r', align='center') -yticks(pos, ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')) -xlabel('Performance') - -show() diff --git a/examples/tests/backend_driver.py b/examples/tests/backend_driver.py index 73b2c195d780..8b18d73f461a 100755 --- a/examples/tests/backend_driver.py +++ b/examples/tests/backend_driver.py @@ -52,6 +52,7 @@ files = dict() files['lines'] = [ + 'barh_demo.py', 'fill_demo.py', 'fill_demo_features.py', 'line_demo_dash_control.py', @@ -115,7 +116,6 @@ 'barb_demo.py', 'barchart_demo.py', 'barcode_demo.py', - 'barh_demo.py', 'boxplot_demo.py', 'broken_barh.py', 'clippedline.py', From 1e579d822b4b0b46f44b246cc8a53cc0ec206860 Mon Sep 17 00:00:00 2001 From: Tony S Yu Date: Sat, 29 Dec 2012 19:47:58 -0500 Subject: [PATCH 35/35] STY: Combine declarations of example directories --- doc/conf.py | 36 +++++++++++++++++++++--------------- doc/sphinxext/gen_gallery.py | 22 ++++------------------ doc/sphinxext/gen_rst.py | 9 +++++---- 3 files changed, 30 insertions(+), 37 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 414bddd81812..b2bc7118323a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -82,21 +82,27 @@ plot_formats = [('png', 80), ('hires.png', 200), ('pdf', 50)] -# Subdirectories in 'examples/' directory of package -mpl_example_sections = ('lines_bars_and_markers', - 'shapes_and_collections', - 'statistics', - 'images_contours_and_fields', - 'pie_and_polar_charts', - 'color', - 'text_labels_and_annotations', - 'ticks_and_spines', - 'subplots_axes_and_figures', - 'specialty_plots', - 'showcase', - 'api', 'pylab_examples', - 'mplot3d', 'axes_grid', - 'units', 'widgets') +# Subdirectories in 'examples/' directory of package and titles for gallery +# TODO: Change to OrderedDict when Matplotlib drops support for Python < 2.7 +mpl_example_sections = ( + ('lines_bars_and_markers', 'Lines, bars, and markers'), + ('shapes_and_collections', 'Shapes and collections'), + ('statistics', 'Statistical plots'), + ('images_contours_and_fields', 'Images, contours, and fields'), + ('pie_and_polar_charts', 'Pie and polar charts'), + ('color', 'Color'), + ('text_labels_and_annotations', 'Text, labels, and annotations'), + ('ticks_and_spines', 'Ticks and spines'), + ('subplots_axes_and_figures', 'Subplots, axes, and figures'), + ('specialty_plots', 'Specialty plots'), + ('showcase', 'Showcase'), + ('api', 'API'), + ('pylab_examples', 'pylab examples'), + ('mplot3d', 'mplot3d toolkit'), + ('axes_grid', 'axes_grid toolkit'), + ('units', 'units'), + ('widgets', 'widgets'), + ) # Github extension diff --git a/doc/sphinxext/gen_gallery.py b/doc/sphinxext/gen_gallery.py index 967cd8f9b8f6..51e9a7b82ed5 100644 --- a/doc/sphinxext/gen_gallery.py +++ b/doc/sphinxext/gen_gallery.py @@ -11,20 +11,6 @@ exclude_example_sections = ['units'] multiimage = re.compile('(.*?)(_\d\d){1,2}') -custom_titles = {'pylab_examples' : 'pylab examples', - 'lines_bars_and_markers': 'Lines, bars, and markers', - 'shapes_and_collections': 'Shapes and collections', - 'statistics': 'Statistical plots', - 'images_contours_and_fields': 'Images, contours, and fields', - 'pie_and_polar_charts': 'Pie and polar charts', - 'text_labels_and_annotations': 'Text, labels, and annotations', - 'ticks_and_spines': 'Ticks and spines', - 'subplots_axes_and_figures': 'Subplots, axes, and figures', - 'specialty_plots': 'Specialty plots', - 'showcase': 'Showcase', - 'color': 'Color', - 'api': 'API', - } # generate a thumbnail gallery of examples gallery_template = """\ @@ -79,8 +65,9 @@ def gen_gallery(app, doctree): rootdir = 'plot_directive/mpl_examples' example_sections = list(app.builder.config.mpl_example_sections) - for section in exclude_example_sections: - example_sections.remove(section) + for i, (subdir, title) in enumerate(example_sections): + if subdir in exclude_example_sections: + example_sections.pop(i) # images we want to skip for the gallery because they are an unusual # size that doesn't layout well in a table, or because they may be @@ -96,8 +83,7 @@ def gen_gallery(app, doctree): rows = [] toc_rows = [] - for subdir in example_sections: - title = custom_titles.get(subdir, subdir) + for subdir, title in example_sections: rows.append(header_template.format(title=title, section=subdir)) toc_rows.append(toc_template.format(title=title, section=subdir)) diff --git a/doc/sphinxext/gen_rst.py b/doc/sphinxext/gen_rst.py index 4294f4e4787b..1ea5c2286120 100644 --- a/doc/sphinxext/gen_rst.py +++ b/doc/sphinxext/gen_rst.py @@ -33,9 +33,10 @@ def generate_example_rst(app): os.makedirs(exampledir) example_sections = list(app.builder.config.mpl_example_sections) - for section in exclude_example_sections: - example_sections.remove(section) - + for i, (subdir, title) in enumerate(example_sections): + if subdir in exclude_example_sections: + example_sections.pop(i) + example_subdirs, titles = zip(*example_sections) datad = {} for root, subFolders, files in os.walk(rootdir): @@ -122,7 +123,7 @@ def generate_example_rst(app): fhsubdirIndex.write(' %s <%s>\n'%(os.path.basename(basename),rstfile)) - do_plot = (subdir in example_sections + do_plot = (subdir in example_subdirs and not noplot_regex.search(contents)) if not do_plot: fhstatic = file(outputfile, 'w')
  • {section}