diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html
index 0b6f475d203d..4480acb408af 100644
--- a/doc/_templates/layout.html
+++ b/doc/_templates/layout.html
@@ -57,6 +57,7 @@
Installation
Documentation
API
+ Plot Types
Examples
Tutorials
Contributing
diff --git a/doc/conf.py b/doc/conf.py
index f67dd662c0bd..24010cf06616 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -151,9 +151,9 @@ def _check_dependencies():
# Sphinx gallery configuration
sphinx_gallery_conf = {
- 'examples_dirs': ['../examples', '../tutorials'],
+ 'examples_dirs': ['../examples', '../tutorials', '../plot_types'],
'filename_pattern': '^((?!sgskip).)*$',
- 'gallery_dirs': ['gallery', 'tutorials'],
+ 'gallery_dirs': ['gallery', 'tutorials', 'plot_types'],
'doc_module': ('matplotlib', 'mpl_toolkits'),
'reference_url': {
'matplotlib': None,
diff --git a/doc/sphinxext/gallery_order.py b/doc/sphinxext/gallery_order.py
index 1c1034ec5819..9c53fff9f131 100644
--- a/doc/sphinxext/gallery_order.py
+++ b/doc/sphinxext/gallery_order.py
@@ -23,7 +23,12 @@
'../examples/showcase',
'../tutorials/introductory',
'../tutorials/intermediate',
- '../tutorials/advanced']
+ '../tutorials/advanced',
+ '../plot_types/basic',
+ '../plot_types/arrays',
+ '../plot_types/stats',
+ '../plot_types/unstructured',
+ ]
class MplExplicitOrder(ExplicitOrder):
@@ -60,6 +65,17 @@ def __call__(self, item):
"color_demo",
# pies
"pie_features", "pie_demo2",
+
+ # **Plot Types
+ # Basic
+ "plot", "scatter_plot", "bar", "stem", "step", "pie", "fill_between",
+ # Arrays
+ "imshow", "pcolormesh", "contourf", "quiver", "streamplot",
+ # Stats
+ "hist_plot", "boxplot_plot", "errorbar_plot", "violin",
+ "barbs", "eventplot", "hist2d", "hexbin",
+ # Unstructured
+ "tricontour", "tripcolor", "triplot",
]
explicit_subsection_order = [item + ".py" for item in list_all]
diff --git a/lib/matplotlib/mpl-data/stylelib/mpl_plot_gallery.mplstyle b/lib/matplotlib/mpl-data/stylelib/mpl_plot_gallery.mplstyle
new file mode 100644
index 000000000000..31aa18ad134e
--- /dev/null
+++ b/lib/matplotlib/mpl-data/stylelib/mpl_plot_gallery.mplstyle
@@ -0,0 +1,19 @@
+# from the Matplotlib cheatsheet as used in our gallery:
+
+axes.grid: True
+axes.axisbelow: True
+
+figure.figsize: 2, 2
+# make it so the axes labels don't show up. Obviously
+# not good style for any quantitative analysis:
+figure.subplot.left: 0.01
+figure.subplot.right: 0.99
+figure.subplot.bottom: 0.01
+figure.subplot.top: 0.99
+
+xtick.major.size: 0.0
+ytick.major.size: 0.0
+
+# colors:
+image.cmap : Blues
+# axes.prop_cycle: cycler('color', ['FF7F0E', '1F77B4', '2CA02C'])
diff --git a/plot_types/README.rst b/plot_types/README.rst
new file mode 100644
index 000000000000..c9ab1071311e
--- /dev/null
+++ b/plot_types/README.rst
@@ -0,0 +1,11 @@
+.. _plot_types:
+
+Plot types
+==========
+
+This gallery lists many of the plotting commands in Matplotlib,
+(but not all of them!).
+
+Note that we have stripped all labels, but they are present by default.
+See the `gallery <../gallery/index.html>`_ for many more examples and
+the `tutorials page <../tutorials/index.html>`_ for longer examples.
\ No newline at end of file
diff --git a/plot_types/arrays/README.rst b/plot_types/arrays/README.rst
new file mode 100644
index 000000000000..a13592dbde9a
--- /dev/null
+++ b/plot_types/arrays/README.rst
@@ -0,0 +1,6 @@
+.. _array_plots:
+
+Plots of arrays and fields
+--------------------------
+
+Plotting for arrays of data ``Z(x, y)`` and fields ``U(x, y), V(x, y)``
\ No newline at end of file
diff --git a/plot_types/arrays/contourf.py b/plot_types/arrays/contourf.py
new file mode 100644
index 000000000000..aba6ec2b06e8
--- /dev/null
+++ b/plot_types/arrays/contourf.py
@@ -0,0 +1,23 @@
+"""
+=====================================
+contour[f]([X, Y], Z, [levels=], ...)
+=====================================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data
+X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
+Z = (1 - X/2. + X**5 + Y**3)*np.exp(-X**2-Y**2)
+Z = Z - Z.min()
+levs = np.linspace(np.min(Z), np.max(Z), 7)
+
+# plot
+fig, ax = plt.subplots()
+
+plt.contourf(X, Y, Z, levels=levs)
+plt.contour(X, Y, Z, levels=levs, colors="white", linewidths=0.5)
+
+plt.show()
diff --git a/plot_types/arrays/imshow.py b/plot_types/arrays/imshow.py
new file mode 100644
index 000000000000..f9c4830d54cb
--- /dev/null
+++ b/plot_types/arrays/imshow.py
@@ -0,0 +1,26 @@
+"""
+=======================
+imshow(Z, [cmap=], ...)
+=======================
+"""
+
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data
+X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
+Z = (1 - X/2. + X**5 + Y**3) * np.exp(-X**2 - Y**2)
+Z = Z - Z.min()
+Z = Z[::16, ::16]
+
+# plot
+fig, ax = plt.subplots()
+
+ax.imshow(Z, extent=[0, 8, 0, 8], interpolation="nearest",
+ cmap=plt.get_cmap('Blues'), vmin=0, vmax=1.6)
+
+ax.set_xticks([])
+ax.set_yticks([])
+plt.show()
diff --git a/plot_types/arrays/pcolormesh.py b/plot_types/arrays/pcolormesh.py
new file mode 100644
index 000000000000..a71637dae09e
--- /dev/null
+++ b/plot_types/arrays/pcolormesh.py
@@ -0,0 +1,33 @@
+"""
+===================================
+pcolormesh([X, Y], Z, [cmap=], ...)
+===================================
+
+`~.axes.Axes.pcolormesh` is more flexible than `~.axes.Axes.imshow` in that
+the x and y vectors need not be equally spaced (indeed they can be skewed).
+
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make full-res data
+X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
+Z = (1 - X/2. + X**5 + Y**3) * np.exp(-X**2 - Y**2)
+Z = Z - Z.min()
+
+# sample unevenly in x:
+dx = np.sqrt((np.arange(16) - 8)**2) + 6
+dx = np.floor(dx / sum(dx) * 255)
+xint = np.cumsum(dx).astype('int')
+X = X[0, xint]
+Y = Y[::8, 0]
+Z = Z[::8, :][:, xint]
+
+# plot
+fig, ax = plt.subplots()
+
+ax.pcolormesh(X, Y, Z, vmin=0, vmax=1.5, shading='nearest')
+
+plt.show()
diff --git a/plot_types/arrays/quiver.py b/plot_types/arrays/quiver.py
new file mode 100644
index 000000000000..29572971a371
--- /dev/null
+++ b/plot_types/arrays/quiver.py
@@ -0,0 +1,27 @@
+"""
+=========================
+quiver([X, Y], U, V, ...)
+=========================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data
+T = np.linspace(0, 2*np.pi, 8)
+X, Y = 4 + 1 * np.cos(T), 4 + 1 * np.sin(T)
+U, V = 1.5 * np.cos(T), 1.5 * np.sin(T)
+
+# plot
+fig, ax = plt.subplots()
+
+plt.quiver(X, Y, U, V, color="C0", angles='xy',
+ scale_units='xy', scale=0.5, width=.05)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+
+plt.show()
diff --git a/plot_types/arrays/streamplot.py b/plot_types/arrays/streamplot.py
new file mode 100644
index 000000000000..789bff2b58df
--- /dev/null
+++ b/plot_types/arrays/streamplot.py
@@ -0,0 +1,26 @@
+"""
+========================
+streamplot([X, Y], U, V)
+========================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make a stream function:
+X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
+Z = (1 - X/2. + X**5 + Y**3) * np.exp(-X**2 - Y**2)
+Z = Z - Z.min()
+# make U and V out of the streamfunction:
+V = np.diff(Z[1:, :], axis=1)
+U = -np.diff(Z[:, 1:], axis=0)
+
+# plot:
+fig, ax = plt.subplots()
+# contour stream function
+ax.contour(X, Y, Z, colors='C1', alpha=0.5, zorder=1, linewidths=3)
+# plot stream plot
+ax.streamplot(X[1:, 1:], Y[1:, 1:], U, V, zorder=2)
+
+plt.show()
diff --git a/plot_types/basic/README.rst b/plot_types/basic/README.rst
new file mode 100644
index 000000000000..45c12220a342
--- /dev/null
+++ b/plot_types/basic/README.rst
@@ -0,0 +1,6 @@
+.. _basic_plots:
+
+Basic
+-----
+
+Basic plot types, usually x versus y.
\ No newline at end of file
diff --git a/plot_types/basic/bar.py b/plot_types/basic/bar.py
new file mode 100644
index 000000000000..560c4d5e25b3
--- /dev/null
+++ b/plot_types/basic/bar.py
@@ -0,0 +1,24 @@
+"""
+======================
+bar[h](x, height, ...)
+======================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+plt.style.use('mpl_plot_gallery')
+
+# make data:
+np.random.seed(3)
+X = 0.5 + np.arange(8)
+Y = np.random.uniform(2, 7, len(X))
+
+# plot
+fig, ax = plt.subplots()
+
+ax.bar(X, Y, width=1, edgecolor="white", linewidth=0.7)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+plt.show()
diff --git a/plot_types/basic/pie.py b/plot_types/basic/pie.py
new file mode 100644
index 000000000000..d139f7ae214d
--- /dev/null
+++ b/plot_types/basic/pie.py
@@ -0,0 +1,31 @@
+"""
+====================
+pie(X, explode, ...)
+====================
+"""
+import matplotlib as mpl
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+
+# make data
+X = [1, 2, 3, 4]
+colors = np.zeros((len(X), 4))
+colors[:] = mpl.colors.to_rgba("C0")
+colors[:, 3] = np.linspace(0.25, 0.75, len(X))
+
+# plot
+fig, ax = plt.subplots()
+ax.pie(X, colors=["white"]*len(X), radius=3, center=(4, 4),
+ wedgeprops={"linewidth": 1, "edgecolor": "white"}, frame=True)
+ax.pie(X, colors=colors, radius=3, center=(4, 4),
+ wedgeprops={"linewidth": 1, "edgecolor": "white"}, frame=True)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+
+plt.show()
diff --git a/plot_types/basic/plot.py b/plot_types/basic/plot.py
new file mode 100644
index 000000000000..d149f12aef72
--- /dev/null
+++ b/plot_types/basic/plot.py
@@ -0,0 +1,25 @@
+"""
+======================
+plot([X], Y, [fmt]...)
+======================
+"""
+
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data
+X = np.linspace(0, 10, 100)
+Y = 4 + 2 * np.sin(2 * X)
+
+# plot
+fig, ax = plt.subplots()
+
+ax.plot(X, Y, linewidth=2.0)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+plt.show()
diff --git a/plot_types/basic/scatter_plot.py b/plot_types/basic/scatter_plot.py
new file mode 100644
index 000000000000..a204025bcf01
--- /dev/null
+++ b/plot_types/basic/scatter_plot.py
@@ -0,0 +1,27 @@
+"""
+==================
+scatter(X, Y, ...)
+==================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make the data
+np.random.seed(3)
+X = 4 + np.random.normal(0, 2, 24)
+Y = 4 + np.random.normal(0, 2, len(X))
+# size and color:
+S = np.random.uniform(15, 80, len(X))
+
+# plot
+fig, ax = plt.subplots()
+
+ax.scatter(X, Y, s=S, c=-S, cmap=plt.get_cmap('Blues'), vmin=-100, vmax=0)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+plt.show()
diff --git a/plot_types/basic/stem.py b/plot_types/basic/stem.py
new file mode 100644
index 000000000000..45a2b7d95669
--- /dev/null
+++ b/plot_types/basic/stem.py
@@ -0,0 +1,25 @@
+"""
+=================
+stem([x], y, ...)
+=================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data
+np.random.seed(3)
+X = 0.5 + np.arange(8)
+Y = np.random.uniform(2, 7, len(X))
+
+# plot
+fig, ax = plt.subplots()
+
+ax.stem(X, Y, bottom=0, linefmt="-", markerfmt="d")
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+plt.show()
diff --git a/plot_types/basic/step.py b/plot_types/basic/step.py
new file mode 100644
index 000000000000..c2150d57ae8c
--- /dev/null
+++ b/plot_types/basic/step.py
@@ -0,0 +1,25 @@
+"""
+=====================
+step(x, y, where=...)
+=====================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data
+np.random.seed(3)
+X = 0.5 + np.arange(8)
+Y = np.random.uniform(2, 7, len(X))
+
+# plot
+fig, ax = plt.subplots()
+
+ax.step(X, Y, linewidth=2.5)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+plt.show()
diff --git a/plot_types/stats/README.rst b/plot_types/stats/README.rst
new file mode 100644
index 000000000000..53af1c3a4a33
--- /dev/null
+++ b/plot_types/stats/README.rst
@@ -0,0 +1,6 @@
+.. _stats_plots:
+
+Specialized statistics plots
+============================
+
+Matplotlib has some specialized plots for statistical analysis.
\ No newline at end of file
diff --git a/plot_types/stats/barbs.py b/plot_types/stats/barbs.py
new file mode 100644
index 000000000000..2ef37a0091ed
--- /dev/null
+++ b/plot_types/stats/barbs.py
@@ -0,0 +1,29 @@
+"""
+========================
+barbs([X, Y], U, V, ...)
+========================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data:
+np.random.seed(1)
+X = [[2, 4, 6]]
+Y = [[1.5, 3, 2]]
+U = -np.ones((1, 3)) * 0
+V = -np.ones((1, 3)) * np.linspace(50, 100, 3)
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.barbs(X, Y, U, V, barbcolor="C0", flagcolor="C0",
+ length=10, linewidth=1.5)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+
+plt.show()
diff --git a/plot_types/stats/boxplot_plot.py b/plot_types/stats/boxplot_plot.py
new file mode 100644
index 000000000000..513e0ba81054
--- /dev/null
+++ b/plot_types/stats/boxplot_plot.py
@@ -0,0 +1,30 @@
+"""
+==============
+boxplot(X,...)
+==============
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data:
+np.random.seed(10)
+D = np.random.normal((3, 5, 4), (1.25, 1.00, 1.25), (100, 3))
+
+# plot
+fig, ax = plt.subplots()
+VP = ax.boxplot(D, positions=[2, 4, 6], widths=1.5, patch_artist=True,
+ showmeans=False, showfliers=False,
+ medianprops={"color": "white", "linewidth": 0.5},
+ boxprops={"facecolor": "C0", "edgecolor": "white",
+ "linewidth": 0.5},
+ whiskerprops={"color": "C0", "linewidth": 1.5},
+ capprops={"color": "C0", "linewidth": 1.5})
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+
+plt.show()
diff --git a/plot_types/stats/errorbar_plot.py b/plot_types/stats/errorbar_plot.py
new file mode 100644
index 000000000000..fc2e5892bf02
--- /dev/null
+++ b/plot_types/stats/errorbar_plot.py
@@ -0,0 +1,27 @@
+"""
+==============================
+errorbar(X, Y, xerr, yerr,...)
+==============================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data:
+np.random.seed(1)
+X = [2, 4, 6]
+Y = [4, 5, 4]
+E = np.random.uniform(0.5, 1.5, 3)
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.errorbar(X, Y, E, linewidth=2, capsize=6)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+
+plt.show()
diff --git a/plot_types/stats/eventplot.py b/plot_types/stats/eventplot.py
new file mode 100644
index 000000000000..535742fa555e
--- /dev/null
+++ b/plot_types/stats/eventplot.py
@@ -0,0 +1,26 @@
+"""
+=================
+eventplot(D, ...)
+=================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data:
+np.random.seed(1)
+X = [2, 4, 6]
+D = np.random.gamma(4, size=(3, 50))
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.eventplot(D, orientation="vertical", lineoffsets=X, linewidth=0.75)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+
+plt.show()
diff --git a/plot_types/stats/hexbin.py b/plot_types/stats/hexbin.py
new file mode 100644
index 000000000000..bf87bfeb0fba
--- /dev/null
+++ b/plot_types/stats/hexbin.py
@@ -0,0 +1,24 @@
+"""
+=================================
+hexbin(x, y, [C], [gridsize],...)
+=================================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data: correlated + noise
+np.random.seed(1)
+x = np.random.randn(5000)
+y = 1.2 * x + np.random.randn(5000)/3
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.hexbin(x, y, gridsize=20)
+
+ax.set_xlim(-2, 2)
+ax.set_ylim(-3, 3)
+
+plt.show()
diff --git a/plot_types/stats/hist2d.py b/plot_types/stats/hist2d.py
new file mode 100644
index 000000000000..894ce5b756f5
--- /dev/null
+++ b/plot_types/stats/hist2d.py
@@ -0,0 +1,24 @@
+"""
+==================================
+hist2d(x, y, [(xbins, ybins)],...)
+==================================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data: correlated + noise
+np.random.seed(1)
+x = np.random.randn(5000)
+y = 1.2 * x + np.random.randn(5000)/3
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.hist2d(x, y, bins=(np.arange(-3, 3, 0.1), np.arange(-3, 3, 0.1)))
+
+ax.set_xlim(-2, 2)
+ax.set_ylim(-3, 3)
+
+plt.show()
diff --git a/plot_types/stats/hist_plot.py b/plot_types/stats/hist_plot.py
new file mode 100644
index 000000000000..c59543fddb16
--- /dev/null
+++ b/plot_types/stats/hist_plot.py
@@ -0,0 +1,25 @@
+"""
+========================
+hist(X, [bins],...)
+========================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data
+np.random.seed(1)
+X = 4 + np.random.normal(0, 1.5, 200)
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.hist(X, bins=8, linewidth=0.5, edgecolor="white")
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 80)
+ax.set_yticks(np.arange(1, 80, 10))
+
+plt.show()
diff --git a/plot_types/stats/violin.py b/plot_types/stats/violin.py
new file mode 100644
index 000000000000..df611a6d4e7c
--- /dev/null
+++ b/plot_types/stats/violin.py
@@ -0,0 +1,29 @@
+"""
+=================
+violinplot(D,...)
+=================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make data:
+np.random.seed(10)
+D = np.random.normal((3, 5, 4), (0.75, 1.00, 0.75), (200, 3))
+
+# plot:
+fig, ax = plt.subplots()
+
+VP = ax.violinplot(D, [2, 4, 6], widths=2,
+ showmeans=False, showmedians=False, showextrema=False)
+#style:
+for body in VP['bodies']:
+ body.set_alpha(0.9)
+
+ax.set_xlim(0, 8)
+ax.set_xticks(np.arange(1, 8))
+ax.set_ylim(0, 8)
+ax.set_yticks(np.arange(1, 8))
+
+plt.show()
diff --git a/plot_types/unstructured/README.rst b/plot_types/unstructured/README.rst
new file mode 100644
index 000000000000..80553f5ee094
--- /dev/null
+++ b/plot_types/unstructured/README.rst
@@ -0,0 +1,9 @@
+.. _unstructured_plots:
+
+Unstructured co-ordinates
+-------------------------
+
+Sometimes we collect data ``z`` at coordinates ``(x,y)`` and want to visualize
+as a contour. Instead of gridding the data and then using
+`~.axes.Axes.contour`, we can use a triangulation algorithm and fill the
+triangles.
\ No newline at end of file
diff --git a/plot_types/unstructured/tricontour.py b/plot_types/unstructured/tricontour.py
new file mode 100644
index 000000000000..1296fe54f058
--- /dev/null
+++ b/plot_types/unstructured/tricontour.py
@@ -0,0 +1,34 @@
+"""
+==============================
+tripcontour(x, y, z, [levels])
+==============================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make structured data
+X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
+Z = (1 - X/2. + X**5 + Y**3)*np.exp(-X**2-Y**2)
+Z = Z - Z.min()
+
+# sample it to make unstructured x, y, z
+np.random.seed(1)
+ysamp = np.random.randint(0, high=256, size=250)
+xsamp = np.random.randint(0, high=256, size=250)
+y = Y[:, 0][ysamp]
+x = X[0, :][xsamp]
+z = Z[ysamp, xsamp]
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.plot(x, y, '.k', alpha=0.5)
+levs = np.linspace(np.min(Z), np.max(Z), 7)
+ax.tricontourf(x, y, z, levels=levs)
+
+ax.set_xlim(-3, 3)
+ax.set_ylim(-3, 3)
+
+plt.show()
diff --git a/plot_types/unstructured/tripcolor.py b/plot_types/unstructured/tripcolor.py
new file mode 100644
index 000000000000..a414da4b7a2e
--- /dev/null
+++ b/plot_types/unstructured/tripcolor.py
@@ -0,0 +1,33 @@
+"""
+==================
+tripcolor(x, y, z)
+==================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make structured data
+X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
+Z = (1 - X/2. + X**5 + Y**3)*np.exp(-X**2-Y**2)
+Z = Z - Z.min()
+
+# sample it to make unstructured x, y, z
+np.random.seed(1)
+ysamp = np.random.randint(0, high=256, size=250)
+xsamp = np.random.randint(0, high=256, size=250)
+y = Y[:, 0][ysamp]
+x = X[0, :][xsamp]
+z = Z[ysamp, xsamp]
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.plot(x, y, '.k', alpha=0.5)
+ax.tripcolor(x, y, z)
+
+ax.set_xlim(-3, 3)
+ax.set_ylim(-3, 3)
+
+plt.show()
diff --git a/plot_types/unstructured/triplot.py b/plot_types/unstructured/triplot.py
new file mode 100644
index 000000000000..d3e74099c8c2
--- /dev/null
+++ b/plot_types/unstructured/triplot.py
@@ -0,0 +1,29 @@
+"""
+=========================
+triplot(x, y, [triangle])
+=========================
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use('mpl_plot_gallery')
+
+# make structured data
+X, Y = np.meshgrid(np.linspace(-3, 3, 256), np.linspace(-3, 3, 256))
+
+# sample it to make x, y, z
+np.random.seed(1)
+ysamp = np.random.randint(0, high=256, size=250)
+xsamp = np.random.randint(0, high=256, size=250)
+y = Y[:, 0][ysamp]
+x = X[0, :][xsamp]
+
+# plot:
+fig, ax = plt.subplots()
+
+ax.triplot(x, y)
+
+ax.set_xlim(-3, 3)
+ax.set_ylim(-3, 3)
+
+plt.show()