PK#JmOI::01_introductory/customizing.py"""
Customizing matplotlib
======================
Tips for customizing the properties and default styles of matplotlib.
Using style sheets
------------------
The ``style`` package adds support for easy-to-switch plotting "styles" with
the same parameters as a matplotlibrc_ file (which is read at startup to
configure matplotlib).
There are a number of pre-defined styles provided by matplotlib. For
example, there's a pre-defined style called "ggplot", which emulates the
aesthetics of ggplot_ (a popular plotting package for R_). To use this style,
just add:
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
plt.style.use('ggplot')
data = np.random.randn(50)
###############################################################################
# To list all available styles, use:
print(plt.style.available)
###############################################################################
# Defining your own style
# -----------------------
#
# You can create custom styles and use them by calling ``style.use`` with the
# path or URL to the style sheet. Additionally, if you add your
# ``.mplstyle`` file to ``mpl_configdir/stylelib``, you can reuse
# your custom style sheet with a call to ``style.use()``. By default
# ``mpl_configdir`` should be ``~/.config/matplotlib``, but you can check where
# yours is with ``matplotlib.get_configdir()``; you may need to create this
# directory. You also can change the directory where matplotlib looks for
# the stylelib/ folder by setting the MPLCONFIGDIR environment variable,
# see :ref:`locating-matplotlib-config-dir`.
#
# Note that a custom style sheet in ``mpl_configdir/stylelib`` will
# override a style sheet defined by matplotlib if the styles have the same name.
#
# For example, you might want to create
# ``mpl_configdir/stylelib/presentation.mplstyle`` with the following::
#
# axes.titlesize : 24
# axes.labelsize : 20
# lines.linewidth : 3
# lines.markersize : 10
# xtick.labelsize : 16
# ytick.labelsize : 16
#
# Then, when you want to adapt a plot designed for a paper to one that looks
# good in a presentation, you can just add::
#
# >>> import matplotlib.pyplot as plt
# >>> plt.style.use('presentation')
#
#
# Composing styles
# ----------------
#
# Style sheets are designed to be composed together. So you can have a style
# sheet that customizes colors and a separate style sheet that alters element
# sizes for presentations. These styles can easily be combined by passing
# a list of styles::
#
# >>> import matplotlib.pyplot as plt
# >>> plt.style.use(['dark_background', 'presentation'])
#
# Note that styles further to the right will overwrite values that are already
# defined by styles on the left.
#
#
# Temporary styling
# -----------------
#
# If you only want to use a style for a specific block of code but don't want
# to change the global styling, the style package provides a context manager
# for limiting your changes to a specific scope. To isolate your styling
# changes, you can write something like the following:
with plt.style.context(('dark_background')):
plt.plot(np.sin(np.linspace(0, 2 * np.pi)), 'r-o')
plt.show()
###############################################################################
# matplotlib rcParams
# ===================
#
# .. _customizing-with-dynamic-rc-settings:
#
# Dynamic rc settings
# -------------------
#
# You can also dynamically change the default rc settings in a python script or
# interactively from the python shell. All of the rc settings are stored in a
# dictionary-like variable called :data:`matplotlib.rcParams`, which is global to
# the matplotlib package. rcParams can be modified directly, for example:
mpl.rcParams['lines.linewidth'] = 2
mpl.rcParams['lines.color'] = 'r'
plt.plot(data)
###############################################################################
# Matplotlib also provides a couple of convenience functions for modifying rc
# settings. The :func:`matplotlib.rc` command can be used to modify multiple
# settings in a single group at once, using keyword arguments:
mpl.rc('lines', linewidth=4, color='g')
plt.plot(data)
###############################################################################
# The :func:`matplotlib.rcdefaults` command will restore the standard matplotlib
# default settings.
#
# There is some degree of validation when setting the values of rcParams, see
# :mod:`matplotlib.rcsetup` for details.
#
# .. _customizing-with-matplotlibrc-files:
#
# The :file:`matplotlibrc` file
# -----------------------------
#
# matplotlib uses :file:`matplotlibrc` configuration files to customize all kinds
# of properties, which we call `rc settings` or `rc parameters`. You can control
# the defaults of almost every property in matplotlib: figure size and dpi, line
# width, color and style, axes, axis and grid properties, text and font
# properties and so on. matplotlib looks for :file:`matplotlibrc` in four
# locations, in the following order:
#
# 1. :file:`matplotlibrc` in the current working directory, usually used for
# specific customizations that you do not want to apply elsewhere.
#
# 2. :file:`$MATPLOTLIBRC` if it is a file, else :file:`$MATPLOTLIBRC/matplotlibrc`.
#
# 3. It next looks in a user-specific place, depending on your platform:
#
# - On Linux and FreeBSD, it looks in :file:`.config/matplotlib/matplotlibrc`
# (or `$XDG_CONFIG_HOME/matplotlib/matplotlibrc`) if you've customized
# your environment.
#
# - On other platforms, it looks in :file:`.matplotlib/matplotlibrc`.
#
# See :ref:`locating-matplotlib-config-dir`.
#
# 4. :file:`{INSTALL}/matplotlib/mpl-data/matplotlibrc`, where
# :file:`{INSTALL}` is something like
# :file:`/usr/lib/python3.5/site-packages` on Linux, and maybe
# :file:`C:\\Python35\\Lib\\site-packages` on Windows. Every time you
# install matplotlib, this file will be overwritten, so if you want
# your customizations to be saved, please move this file to your
# user-specific matplotlib directory.
#
# Once a :file:`matplotlibrc` file has been found, it will *not* search any of
# the other paths.
#
# To display where the currently active :file:`matplotlibrc` file was
# loaded from, one can do the following::
#
# >>> import matplotlib
# >>> matplotlib.matplotlib_fname()
# '/home/foo/.config/matplotlib/matplotlibrc'
#
# See below for a sample :ref:`matplotlibrc file`.
# Although all parameters are optional, you should almost always set the
# `backend` or else matplotlib will choose `Agg`, a *non-interactive* backend.
# This can lead to unexpected behavior, since if you do not have a
# :file:`matplotlibrc` file, it would normally fall back to
# :file:`{INSTALL}/matplotlib/mpl-data/matplotlibrc`, which is often set to an
# interactive backend by the package maintainer.
#
# .. _matplotlibrc-sample:
#
# A sample matplotlibrc file
# ~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# .. htmlonly::
#
# `(download) <../../_static/matplotlibrc>`__
#
# .. literalinclude:: ../../_static/matplotlibrc
#
#
# .. _matplotlibrc: http://matplotlib.org/users/customizing.html
# .. _ggplot: http://ggplot2.org/
# .. _R: https://www.r-project.org/
PK#JBff01_introductory/usage.py"""
***********
Usage Guide
***********
This tutorial covers some basic usage patterns and best-practices to
help you get started with Matplotlib.
.. _general_concepts:
General Concepts
================
:mod:`matplotlib` has an extensive codebase that can be daunting to many
new users. However, most of matplotlib can be understood with a fairly
simple conceptual framework and knowledge of a few important points.
Plotting requires action on a range of levels, from the most general
(e.g., 'contour this 2-D array') to the most specific (e.g., 'color
this screen pixel red'). The purpose of a plotting package is to assist
you in visualizing your data as easily as possible, with all the necessary
control -- that is, by using relatively high-level commands most of
the time, and still have the ability to use the low-level commands when
needed.
Therefore, everything in matplotlib is organized in a hierarchy. At the top
of the hierarchy is the matplotlib "state-machine environment" which is
provided by the :mod:`matplotlib.pyplot` module. At this level, simple
functions are used to add plot elements (lines, images, text, etc.) to
the current axes in the current figure.
.. note::
Pyplot's state-machine environment behaves similarly to MATLAB and
should be most familiar to users with MATLAB experience.
The next level down in the hierarchy is the first level of the object-oriented
interface, in which pyplot is used only for a few functions such as figure
creation, and the user explicitly creates and keeps track of the figure
and axes objects. At this level, the user uses pyplot to create figures,
and through those figures, one or more axes objects can be created. These
axes objects are then used for most plotting actions.
For even more control -- which is essential for things like embedding
matplotlib plots in GUI applications -- the pyplot level may be dropped
completely, leaving a purely object-oriented approach.
"""
# sphinx_gallery_thumbnail_number = 3
import matplotlib.pyplot as plt
import numpy as np
###############################################################################
# .. _figure_parts:
#
# Parts of a Figure
# =================
#
# .. image:: ../../_static/anatomy.png
#
#
# :class:`~matplotlib.figure.Figure`
# ----------------------------------
#
# The **whole** figure. The figure keeps
# track of all the child :class:`~matplotlib.axes.Axes`, a smattering of
# 'special' artists (titles, figure legends, etc), and the **canvas**.
# (Don't worry too much about the canvas, it is crucial as it is the
# object that actually does the drawing to get you your plot, but as the
# user it is more-or-less invisible to you). A figure can have any
# number of :class:`~matplotlib.axes.Axes`, but to be useful should have
# at least one.
#
# The easiest way to create a new figure is with pyplot:
fig = plt.figure() # an empty figure with no axes
fig.suptitle('No axes on this figure') # Add a title so we know which it is
fig, ax_lst = plt.subplots(2, 2) # a figure with a 2x2 grid of Axes
###############################################################################
# :class:`~matplotlib.axes.Axes`
# ------------------------------
#
# This is what you think of as 'a plot', it is the region of the image
# with the data space (marked as the inner blue box). A given figure
# can contain many Axes, but a given :class:`~matplotlib.axes.Axes`
# object can only be in one :class:`~matplotlib.figure.Figure`. The
# Axes contains two (or three in the case of 3D)
# :class:`~matplotlib.axis.Axis` objects (be aware of the difference
# between **Axes** and **Axis**) which take care of the data limits (the
# data limits can also be controlled via set via the
# :meth:`~matplotlib.axes.Axes.set_xlim` and
# :meth:`~matplotlib.axes.Axes.set_ylim` :class:`Axes` methods). Each
# :class:`Axes` has a title (set via
# :meth:`~matplotlib.axes.Axes.set_title`), an x-label (set via
# :meth:`~matplotlib.axes.Axes.set_xlabel`), and a y-label set via
# :meth:`~matplotlib.axes.Axes.set_ylabel`).
#
# The :class:`Axes` class and it's member functions are the primary entry
# point to working with the OO interface.
#
# :class:`~matplotlib.axis.Axis`
# ------------------------------
#
# These are the number-line-like objects (circled in green). They take
# care of setting the graph limits and generating the ticks (the marks
# on the axis) and ticklabels (strings labeling the ticks). The
# location of the ticks is determined by a
# :class:`~matplotlib.ticker.Locator` object and the ticklabel strings
# are formatted by a :class:`~matplotlib.ticker.Formatter`. The
# combination of the correct :class:`Locator` and :class:`Formatter` gives
# very fine control over the tick locations and labels.
#
# :class:`~matplotlib.artist.Artist`
# ----------------------------------
#
# Basically everything you can see on the figure is an artist (even the
# :class:`Figure`, :class:`Axes`, and :class:`Axis` objects). This
# includes :class:`Text` objects, :class:`Line2D` objects,
# :class:`collection` objects, :class:`Patch` objects ... (you get the
# idea). When the figure is rendered, all of the artists are drawn to
# the **canvas**. Most Artists are tied to an Axes; such an Artist
# cannot be shared by multiple Axes, or moved from one to another.
#
# .. _input_types:
#
# Types of inputs to plotting functions
# =====================================
#
# All of plotting functions expect `np.array` or `np.ma.masked_array` as
# input. Classes that are 'array-like' such as `pandas` data objects
# and `np.matrix` may or may not work as intended. It is best to
# convert these to `np.array` objects prior to plotting.
#
# For example, to convert a `pandas.DataFrame` ::
#
# a = pandas.DataFrame(np.random.rand(4,5), columns = list('abcde'))
# a_asndarray = a.values
#
# and to covert a `np.matrix` ::
#
# b = np.matrix([[1,2],[3,4]])
# b_asarray = np.asarray(b)
#
# .. _pylab:
#
# Matplotlib, pyplot and pylab: how are they related?
# ====================================================
#
# Matplotlib is the whole package; :mod:`matplotlib.pyplot`
# is a module in matplotlib; and :mod:`pylab` is a module
# that gets installed alongside :mod:`matplotlib`.
#
# Pyplot provides the state-machine interface to the underlying
# object-oriented plotting library. The state-machine implicitly and
# automatically creates figures and axes to achieve the desired
# plot. For example:
x = np.linspace(0, 2, 100)
plt.plot(x, x, label='linear')
plt.plot(x, x**2, label='quadratic')
plt.plot(x, x**3, label='cubic')
plt.xlabel('x label')
plt.ylabel('y label')
plt.title("Simple Plot")
plt.legend()
plt.show()
###############################################################################
# The first call to ``plt.plot`` will automatically create the necessary
# figure and axes to achieve the desired plot. Subsequent calls to
# ``plt.plot`` re-use the current axes and each add another line.
# Setting the title, legend, and axis labels also automatically use the
# current axes and set the title, create the legend, and label the axis
# respectively.
#
# :mod:`pylab` is a convenience module that bulk imports
# :mod:`matplotlib.pyplot` (for plotting) and :mod:`numpy`
# (for mathematics and working with arrays) in a single name space.
# Although many examples use :mod:`pylab`, it is no longer recommended.
#
# For non-interactive plotting it is suggested
# to use pyplot to create the figures and then the OO interface for
# plotting.
#
# .. _coding_styles:
#
# Coding Styles
# ==================
#
# When viewing this documentation and examples, you will find different
# coding styles and usage patterns. These styles are perfectly valid
# and have their pros and cons. Just about all of the examples can be
# converted into another style and achieve the same results.
# The only caveat is to avoid mixing the coding styles for your own code.
#
# .. note::
# Developers for matplotlib have to follow a specific style and guidelines.
# See :ref:`developers-guide-index`.
#
# Of the different styles, there are two that are officially supported.
# Therefore, these are the preferred ways to use matplotlib.
#
# For the pyplot style, the imports at the top of your
# scripts will typically be::
#
# import matplotlib.pyplot as plt
# import numpy as np
#
# Then one calls, for example, np.arange, np.zeros, np.pi, plt.figure,
# plt.plot, plt.show, etc. Use the pyplot interface
# for creating figures, and then use the object methods for the rest:
x = np.arange(0, 10, 0.2)
y = np.sin(x)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y)
plt.show()
###############################################################################
# So, why all the extra typing instead of the MATLAB-style (which relies
# on global state and a flat namespace)? For very simple things like
# this example, the only advantage is academic: the wordier styles are
# more explicit, more clear as to where things come from and what is
# going on. For more complicated applications, this explicitness and
# clarity becomes increasingly valuable, and the richer and more
# complete object-oriented interface will likely make the program easier
# to write and maintain.
#
#
# Typically one finds oneself making the same plots over and over
# again, but with different data sets, which leads to needing to write
# specialized functions to do the plotting. The recommended function
# signature is something like:
def my_plotter(ax, data1, data2, param_dict):
"""
A helper function to make a graph
Parameters
----------
ax : Axes
The axes to draw to
data1 : array
The x data
data2 : array
The y data
param_dict : dict
Dictionary of kwargs to pass to ax.plot
Returns
-------
out : list
list of artists added
"""
out = ax.plot(data1, data2, **param_dict)
return out
# which you would then use as:
data1, data2, data3, data4 = np.random.randn(4, 100)
fig, ax = plt.subplots(1, 1)
my_plotter(ax, data1, data2, {'marker': 'x'})
###############################################################################
# or if you wanted to have 2 sub-plots:
fig, (ax1, ax2) = plt.subplots(1, 2)
my_plotter(ax1, data1, data2, {'marker': 'x'})
my_plotter(ax2, data3, data4, {'marker': 'o'})
###############################################################################
# Again, for these simple examples this style seems like overkill, however
# once the graphs get slightly more complex it pays off.
#
# .. _what-is-a-backend:
#
# What is a backend?
# ==================
#
# A lot of documentation on the website and in the mailing lists refers
# to the "backend" and many new users are confused by this term.
# matplotlib targets many different use cases and output formats. Some
# people use matplotlib interactively from the python shell and have
# plotting windows pop up when they type commands. Some people embed
# matplotlib into graphical user interfaces like wxpython or pygtk to
# build rich applications. Others use matplotlib in batch scripts to
# generate postscript images from some numerical simulations, and still
# others in web application servers to dynamically serve up graphs.
#
# To support all of these use cases, matplotlib can target different
# outputs, and each of these capabilities is called a backend; the
# "frontend" is the user facing code, i.e., the plotting code, whereas the
# "backend" does all the hard work behind-the-scenes to make the figure.
# There are two types of backends: user interface backends (for use in
# pygtk, wxpython, tkinter, qt4, or macosx; also referred to as
# "interactive backends") and hardcopy backends to make image files
# (PNG, SVG, PDF, PS; also referred to as "non-interactive backends").
#
# There are four ways to configure your backend. If they conflict each other,
# the method mentioned last in the following list will be used, e.g. calling
# :func:`~matplotlib.use()` will override the setting in your ``matplotlibrc``.
#
#
# #. The ``backend`` parameter in your ``matplotlibrc`` file (see
# :ref:`sphx_glr_tutorials_01_introductory_customizing.py`)::
#
# backend : WXAgg # use wxpython with antigrain (agg) rendering
#
# #. Setting the :envvar:`MPLBACKEND` environment
# variable, either for your current shell or for a single script::
#
# > export MPLBACKEND="module://my_backend"
# > python simple_plot.py
#
# > MPLBACKEND="module://my_backend" python simple_plot.py
#
# Setting this environment variable will override the ``backend`` parameter
# in *any* ``matplotlibrc``, even if there is a ``matplotlibrc`` in your
# current working directory. Therefore setting :envvar:`MPLBACKEND`
# globally, e.g. in your ``.bashrc`` or ``.profile``, is discouraged as it
# might lead to counter-intuitive behavior.
#
# #. If your script depends on a specific backend you can use the
# :func:`~matplotlib.use` function::
#
# import matplotlib
# matplotlib.use('PS') # generate postscript output by default
#
# If you use the :func:`~matplotlib.use` function, this must be done before
# importing :mod:`matplotlib.pyplot`. Calling :func:`~matplotlib.use` after
# pyplot has been imported will have no effect. Using
# :func:`~matplotlib.use` will require changes in your code if users want to
# use a different backend. Therefore, you should avoid explicitly calling
# :func:`~matplotlib.use` unless absolutely necessary.
#
# .. note::
# Backend name specifications are not case-sensitive; e.g., 'GTKAgg'
# and 'gtkagg' are equivalent.
#
# With a typical installation of matplotlib, such as from a
# binary installer or a linux distribution package, a good default
# backend will already be set, allowing both interactive work and
# plotting from scripts, with output to the screen and/or to
# a file, so at least initially you will not need to use any of the
# methods given above.
#
# If, however, you want to write graphical user interfaces, or a web
# application server (:ref:`howto-webapp`), or need a better
# understanding of what is going on, read on. To make things a little
# more customizable for graphical user interfaces, matplotlib separates
# the concept of the renderer (the thing that actually does the drawing)
# from the canvas (the place where the drawing goes). The canonical
# renderer for user interfaces is ``Agg`` which uses the `Anti-Grain
# Geometry`_ C++ library to make a raster (pixel) image of the figure.
# All of the user interfaces except ``macosx`` can be used with
# agg rendering, e.g.,
# ``WXAgg``, ``GTKAgg``, ``QT4Agg``, ``QT5Agg``, ``TkAgg``. In
# addition, some of the user interfaces support other rendering engines.
# For example, with GTK, you can also select GDK rendering (backend
# ``GTK`` deprecated in 2.0) or Cairo rendering (backend ``GTKCairo``).
#
# For the rendering engines, one can also distinguish between `vector
# `_ or `raster
# `_ renderers. Vector
# graphics languages issue drawing commands like "draw a line from this
# point to this point" and hence are scale free, and raster backends
# generate a pixel representation of the line whose accuracy depends on a
# DPI setting.
#
# Here is a summary of the matplotlib renderers (there is an eponymous
# backed for each; these are *non-interactive backends*, capable of
# writing to a file):
#
# ============= ============ ================================================
# Renderer Filetypes Description
# ============= ============ ================================================
# :term:`AGG` :term:`png` :term:`raster graphics` -- high quality images
# using the `Anti-Grain Geometry`_ engine
# PS :term:`ps` :term:`vector graphics` -- Postscript_ output
# :term:`eps`
# PDF :term:`pdf` :term:`vector graphics` --
# `Portable Document Format`_
# SVG :term:`svg` :term:`vector graphics` --
# `Scalable Vector Graphics`_
# :term:`Cairo` :term:`png` :term:`vector graphics` --
# :term:`ps` `Cairo graphics`_
# :term:`pdf`
# :term:`svg`
# ...
# :term:`GDK` :term:`png` :term:`raster graphics` --
# :term:`jpg` the `Gimp Drawing Kit`_ Deprecated in 2.0
# :term:`tiff`
# ...
# ============= ============ ================================================
#
# And here are the user interfaces and renderer combinations supported;
# these are *interactive backends*, capable of displaying to the screen
# and of using appropriate renderers from the table above to write to
# a file:
#
# ============ ================================================================
# Backend Description
# ============ ================================================================
# GTKAgg Agg rendering to a :term:`GTK` 2.x canvas (requires PyGTK_ and
# pycairo_ or cairocffi_; Python2 only)
# GTK3Agg Agg rendering to a :term:`GTK` 3.x canvas (requires PyGObject_
# and pycairo_ or cairocffi_)
# GTK GDK rendering to a :term:`GTK` 2.x canvas (not recommended and d
# eprecated in 2.0) (requires PyGTK_ and pycairo_ or cairocffi_;
# Python2 only)
# GTKCairo Cairo rendering to a :term:`GTK` 2.x canvas (requires PyGTK_
# and pycairo_ or cairocffi_; Python2 only)
# GTK3Cairo Cairo rendering to a :term:`GTK` 3.x canvas (requires PyGObject_
# and pycairo_ or cairocffi_)
# WXAgg Agg rendering to a :term:`wxWidgets` canvas
# (requires wxPython_)
# WX Native :term:`wxWidgets` drawing to a :term:`wxWidgets` Canvas
# (not recommended and deprecated in 2.0) (requires wxPython_)
# TkAgg Agg rendering to a :term:`Tk` canvas (requires TkInter_)
# Qt4Agg Agg rendering to a :term:`Qt4` canvas (requires PyQt4_ or ``pyside``)
# Qt5Agg Agg rendering in a :term:`Qt5` canvas (requires PyQt5_)
# macosx Cocoa rendering in OSX windows
# (presently lacks blocking show() behavior when matplotlib
# is in non-interactive mode)
# ============ ================================================================
#
# .. _`Anti-Grain Geometry`: http://antigrain.com/
# .. _Postscript: https://en.wikipedia.org/wiki/PostScript
# .. _`Portable Document Format`: https://en.wikipedia.org/wiki/Portable_Document_Format
# .. _`Scalable Vector Graphics`: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
# .. _`Cairo graphics`: https://en.wikipedia.org/wiki/Cairo_(graphics)
# .. _`Gimp Drawing Kit`: https://en.wikipedia.org/wiki/GDK
# .. _PyGTK: http://www.pygtk.org
# .. _PyGObject: https://wiki.gnome.org/action/show/Projects/PyGObject
# .. _pycairo: https://www.cairographics.org/pycairo/
# .. _cairocffi: https://pythonhosted.org/cairocffi/
# .. _wxPython: https://www.wxpython.org/
# .. _TkInter: https://wiki.python.org/moin/TkInter
# .. _PyQt4: https://riverbankcomputing.com/software/pyqt/intro
# .. _PyQt5: https://riverbankcomputing.com/software/pyqt/intro
#
# WX backends
# ===========
#
# At present the release version of `wxPython` (also known as wxPython classic)
# does not support python3. A work in progress redesigned version known as
# wxPython-Phoenix_ does support python3.
# Matplotlib should work with both versions.
#
# .. _wxPython-Phoenix: https://wxpython.org/Phoenix/docs/html/main.html
#
# GTK and Cairo
# =============
#
# Both `GTK2` and `GTK3` have implicit dependencies on PyCairo regardless of the
# specific Matplotlib backend used. Unfortunatly the latest release of PyCairo
# for Python3 does not implement the Python wrappers needed for the `GTK3Agg`
# backend. `Cairocffi` can be used as a replacement which implements the correct
# wrapper.
#
# How do I select PyQt4 or PySide?
# ========================================
#
# You can choose either PyQt4 or PySide when using the `qt4` backend by setting
# the appropriate value for `backend.qt4` in your :file:`matplotlibrc` file. The
# default value is `PyQt4`.
#
# The setting in your :file:`matplotlibrc` file can be overridden by setting the
# `QT_API` environment variable to either `pyqt` or `pyside` to use `PyQt4` or
# `PySide`, respectively.
#
# Since the default value for the bindings to be used is `PyQt4`,
# :mod:`matplotlib` first tries to import it, if the import fails, it tries to
# import `PySide`.
#
# .. _interactive-mode:
#
# What is interactive mode?
# ===================================
#
# Use of an interactive backend (see :ref:`what-is-a-backend`)
# permits--but does not by itself require or ensure--plotting
# to the screen. Whether and when plotting to the screen occurs,
# and whether a script or shell session continues after a plot
# is drawn on the screen, depends on the functions and methods
# that are called, and on a state variable that determines whether
# matplotlib is in "interactive mode". The default Boolean value is set
# by the :file:`matplotlibrc` file, and may be customized like any other
# configuration parameter (see :ref:`sphx_glr_tutorials_01_introductory_customizing.py`). It
# may also be set via :func:`matplotlib.interactive`, and its
# value may be queried via :func:`matplotlib.is_interactive`. Turning
# interactive mode on and off in the middle of a stream of plotting
# commands, whether in a script or in a shell, is rarely needed
# and potentially confusing, so in the following we will assume all
# plotting is done with interactive mode either on or off.
#
# .. note::
# Major changes related to interactivity, and in particular the
# role and behavior of :func:`~matplotlib.pyplot.show`, were made in the
# transition to matplotlib version 1.0, and bugs were fixed in
# 1.0.1. Here we describe the version 1.0.1 behavior for the
# primary interactive backends, with the partial exception of
# *macosx*.
#
# Interactive mode may also be turned on via :func:`matplotlib.pyplot.ion`,
# and turned off via :func:`matplotlib.pyplot.ioff`.
#
# .. note::
# Interactive mode works with suitable backends in ipython and in
# the ordinary python shell, but it does *not* work in the IDLE IDE.
# If the default backend does not support interactivity, an interactive
# backend can be explicitly activated using any of the methods discussed in `What is a backend?`_.
#
#
# Interactive example
# --------------------
#
# From an ordinary python prompt, or after invoking ipython with no options,
# try this::
#
# import matplotlib.pyplot as plt
# plt.ion()
# plt.plot([1.6, 2.7])
#
# Assuming you are running version 1.0.1 or higher, and you have
# an interactive backend installed and selected by default, you should
# see a plot, and your terminal prompt should also be active; you
# can type additional commands such as::
#
# plt.title("interactive test")
# plt.xlabel("index")
#
# and you will see the plot being updated after each line. This is
# because you are in interactive mode *and* you are using pyplot
# functions. Now try an alternative method of modifying the
# plot. Get a reference to the :class:`~matplotlib.axes.Axes` instance, and
# call a method of that instance::
#
# ax = plt.gca()
# ax.plot([3.1, 2.2])
#
# Nothing changed, because the Axes methods do not include an
# automatic call to :func:`~matplotlib.pyplot.draw_if_interactive`;
# that call is added by the pyplot functions. If you are using
# methods, then when you want to update the plot on the screen,
# you need to call :func:`~matplotlib.pyplot.draw`::
#
# plt.draw()
#
# Now you should see the new line added to the plot.
#
# Non-interactive example
# -----------------------
#
# Start a fresh session as in the previous example, but now
# turn interactive mode off::
#
# import matplotlib.pyplot as plt
# plt.ioff()
# plt.plot([1.6, 2.7])
#
# Nothing happened--or at least nothing has shown up on the
# screen (unless you are using *macosx* backend, which is
# anomalous). To make the plot appear, you need to do this::
#
# plt.show()
#
# Now you see the plot, but your terminal command line is
# unresponsive; the :func:`show()` command *blocks* the input
# of additional commands until you manually kill the plot
# window.
#
# What good is this--being forced to use a blocking function?
# Suppose you need a script that plots the contents of a file
# to the screen. You want to look at that plot, and then end
# the script. Without some blocking command such as show(), the
# script would flash up the plot and then end immediately,
# leaving nothing on the screen.
#
# In addition, non-interactive mode delays all drawing until
# show() is called; this is more efficient than redrawing
# the plot each time a line in the script adds a new feature.
#
# Prior to version 1.0, show() generally could not be called
# more than once in a single script (although sometimes one
# could get away with it); for version 1.0.1 and above, this
# restriction is lifted, so one can write a script like this:
import numpy as np
import matplotlib.pyplot as plt
plt.ioff()
for i in range(3):
plt.plot(np.random.rand(10))
plt.show()
###############################################################################
# which makes three plots, one at a time.
#
# Summary
# -------
#
# In interactive mode, pyplot functions automatically draw
# to the screen.
#
# When plotting interactively, if using
# object method calls in addition to pyplot functions, then
# call :func:`~matplotlib.pyplot.draw` whenever you want to
# refresh the plot.
#
# Use non-interactive mode in scripts in which you want to
# generate one or more figures and display them before ending
# or generating a new set of figures. In that case, use
# :func:`~matplotlib.pyplot.show` to display the figure(s) and
# to block execution until you have manually destroyed them.
PK#J?d,d,01_introductory/images.py"""
==============
Image tutorial
==============
A short tutorial on plotting images with Matplotlib.
.. _imaging_startup:
Startup commands
===================
First, let's start IPython. It is a most excellent enhancement to the
standard Python prompt, and it ties in especially well with
Matplotlib. Start IPython either at a shell, or the IPython Notebook now.
With IPython started, we now need to connect to a GUI event loop. This
tells IPython where (and how) to display plots. To connect to a GUI
loop, execute the **%matplotlib** magic at your IPython prompt. There's more
detail on exactly what this does at `IPython's documentation on GUI
event loops
`_.
If you're using IPython Notebook, the same commands are available, but
people commonly use a specific argument to the %matplotlib magic:
.. sourcecode:: ipython
In [1]: %matplotlib inline
This turns on inline plotting, where plot graphics will appear in your
notebook. This has important implications for interactivity. For inline plotting, commands in
cells below the cell that outputs a plot will not affect the plot. For example,
changing the color map is not possible from cells below the cell that creates a plot.
However, for other backends, such as qt4, that open a separate window,
cells below those that create the plot will change the plot - it is a
live object in memory.
This tutorial will use matplotlib's imperative-style plotting
interface, pyplot. This interface maintains global state, and is very
useful for quickly and easily experimenting with various plot
settings. The alternative is the object-oriented interface, which is also
very powerful, and generally more suitable for large application
development. If you'd like to learn about the object-oriented
interface, a great place to start is our `FAQ on usage
`_. For now, let's get on
with the imperative-style approach:
"""
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
###############################################################################
# .. _importing_data:
#
# Importing image data into Numpy arrays
# ===============================================
#
# Loading image data is supported by the `Pillow
# `_ library. Natively, matplotlib only
# supports PNG images. The commands shown below fall back on Pillow if the
# native read fails.
#
# The image used in this example is a PNG file, but keep that Pillow
# requirement in mind for your own data.
#
# Here's the image we're going to play with:
#
# .. image:: ../../_static/stinkbug.png
#
# It's a 24-bit RGB PNG image (8 bits for each of R, G, B). Depending
# on where you get your data, the other kinds of image that you'll most
# likely encounter are RGBA images, which allow for transparency, or
# single-channel grayscale (luminosity) images. You can right click on
# it and choose "Save image as" to download it to your computer for the
# rest of this tutorial.
#
# And here we go...
img = mpimg.imread('../../doc/_static/stinkbug.png')
print(img)
###############################################################################
# Note the dtype there - float32. Matplotlib has rescaled the 8 bit
# data from each channel to floating point data between 0.0 and 1.0. As
# a side note, the only datatype that Pillow can work with is uint8.
# Matplotlib plotting can handle float32 and uint8, but image
# reading/writing for any format other than PNG is limited to uint8
# data. Why 8 bits? Most displays can only render 8 bits per channel
# worth of color gradation. Why can they only render 8 bits/channel?
# Because that's about all the human eye can see. More here (from a
# photography standpoint): `Luminous Landscape bit depth tutorial
# `_.
#
# Each inner list represents a pixel. Here, with an RGB image, there
# are 3 values. Since it's a black and white image, R, G, and B are all
# similar. An RGBA (where A is alpha, or transparency), has 4 values
# per inner list, and a simple luminance image just has one value (and
# is thus only a 2-D array, not a 3-D array). For RGB and RGBA images,
# matplotlib supports float32 and uint8 data types. For grayscale,
# matplotlib supports only float32. If your array data does not meet
# one of these descriptions, you need to rescale it.
#
# .. _plotting_data:
#
# Plotting numpy arrays as images
# ===================================
#
# So, you have your data in a numpy array (either by importing it, or by
# generating it). Let's render it. In Matplotlib, this is performed
# using the :func:`~matplotlib.pyplot.imshow` function. Here we'll grab
# the plot object. This object gives you an easy way to manipulate the
# plot from the prompt.
imgplot = plt.imshow(img)
###############################################################################
# You can also plot any numpy array.
#
# .. _Pseudocolor:
#
# Applying pseudocolor schemes to image plots
# -------------------------------------------------
#
# Pseudocolor can be a useful tool for enhancing contrast and
# visualizing your data more easily. This is especially useful when
# making presentations of your data using projectors - their contrast is
# typically quite poor.
#
# Pseudocolor is only relevant to single-channel, grayscale, luminosity
# images. We currently have an RGB image. Since R, G, and B are all
# similar (see for yourself above or in your data), we can just pick one
# channel of our data:
lum_img = img[:, :, 0]
# This is array slicing. You can read more in the `Numpy tutorial
# `_.
plt.imshow(lum_img)
###############################################################################
# Now, with a luminosity (2D, no color) image, the default colormap (aka lookup table,
# LUT), is applied. The default is called viridis. There are plenty of
# others to choose from.
plt.imshow(lum_img, cmap="hot")
###############################################################################
# Note that you can also change colormaps on existing plot objects using the
# :meth:`~matplotlib.image.Image.set_cmap` method:
imgplot = plt.imshow(lum_img)
imgplot.set_cmap('nipy_spectral')
###############################################################################
#
# .. note::
#
# However, remember that in the IPython notebook with the inline backend,
# you can't make changes to plots that have already been rendered. If you
# create imgplot here in one cell, you cannot call set_cmap() on it in a later
# cell and expect the earlier plot to change. Make sure that you enter these
# commands together in one cell. plt commands will not change plots from earlier
# cells.
#
# There are many other colormap schemes available. See the `list and
# images of the colormaps
# <../colors/colormaps.html>`_.
#
# .. _`Color Bars`:
#
# Color scale reference
# ------------------------
#
# It's helpful to have an idea of what value a color represents. We can
# do that by adding color bars.
imgplot = plt.imshow(lum_img)
plt.colorbar()
###############################################################################
# This adds a colorbar to your existing figure. This won't
# automatically change if you change you switch to a different
# colormap - you have to re-create your plot, and add in the colorbar
# again.
#
# .. _`Data ranges`:
#
# Examining a specific data range
# ---------------------------------
#
# Sometimes you want to enhance the contrast in your image, or expand
# the contrast in a particular region while sacrificing the detail in
# colors that don't vary much, or don't matter. A good tool to find
# interesting regions is the histogram. To create a histogram of our
# image data, we use the :func:`~matplotlib.pyplot.hist` function.
plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')
###############################################################################
# Most often, the "interesting" part of the image is around the peak,
# and you can get extra contrast by clipping the regions above and/or
# below the peak. In our histogram, it looks like there's not much
# useful information in the high end (not many white things in the
# image). Let's adjust the upper limit, so that we effectively "zoom in
# on" part of the histogram. We do this by passing the clim argument to
# imshow. You could also do this by calling the
# :meth:`~matplotlib.image.Image.set_clim` method of the image plot
# object, but make sure that you do so in the same cell as your plot
# command when working with the IPython Notebook - it will not change
# plots from earlier cells.
#
# You can specify the clim in the call to ``plot``.
imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))
###############################################################################
# You can also specify the clim using the returned object
fig = plt.figure()
a = fig.add_subplot(1, 2, 1)
imgplot = plt.imshow(lum_img)
a.set_title('Before')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
a = fig.add_subplot(1, 2, 2)
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0.0, 0.7)
a.set_title('After')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
###############################################################################
# .. _Interpolation:
#
# Array Interpolation schemes
# ---------------------------
#
# Interpolation calculates what the color or value of a pixel "should"
# be, according to different mathematical schemes. One common place
# that this happens is when you resize an image. The number of pixels
# change, but you want the same information. Since pixels are discrete,
# there's missing space. Interpolation is how you fill that space.
# This is why your images sometimes come out looking pixelated when you
# blow them up. The effect is more pronounced when the difference
# between the original image and the expanded image is greater. Let's
# take our image and shrink it. We're effectively discarding pixels,
# only keeping a select few. Now when we plot it, that data gets blown
# up to the size on your screen. The old pixels aren't there anymore,
# and the computer has to draw in pixels to fill that space.
#
# We'll use the Pillow library that we used to load the image also to resize
# the image.
from PIL import Image
img = Image.open('../../doc/_static/stinkbug.png')
img.thumbnail((64, 64), Image.ANTIALIAS) # resizes image in-place
imgplot = plt.imshow(img)
###############################################################################
# Here we have the default interpolation, bilinear, since we did not
# give :func:`~matplotlib.pyplot.imshow` any interpolation argument.
#
# Let's try some others. Here's "nearest", which does no interpolation.
imgplot = plt.imshow(img, interpolation="nearest")
###############################################################################
# and bucibic:
imgplot = plt.imshow(img, interpolation="bicubic")
###############################################################################
# Bicubic interpolation is often used when blowing up photos - people
# tend to prefer blurry over pixelated.
PK#JQ=FF01_introductory/pyplot.py"""
===============
Pyplot tutorial
===============
An introduction to the pyplot interface.
"""
###############################################################################
# Intro to pyplot
# ===============
#
# :mod:`matplotlib.pyplot` is a collection of command style functions
# that make matplotlib work like MATLAB.
# Each ``pyplot`` function makes
# some change to a figure: e.g., creates a figure, creates a plotting area
# in a figure, plots some lines in a plotting area, decorates the plot
# with labels, etc.
#
# In :mod:`matplotlib.pyplot` various states are preserved
# across function calls, so that it keeps track of things like
# the current figure and plotting area, and the plotting
# functions are directed to the current axes (please note that "axes" here
# and in most places in the documentation refers to the *axes*
# `part of a figure `__
# and not the strict mathematical term for more than one axis).
#
# .. note::
#
# the pyplot API is generally less-flexible than the object-oriented API.
# Most of the function calls you see here can also be called as methods
# from an ``Axes`` object. We recommend browsing the tutorials and
# examples to see how this works.
#
# Generating visualizations with pyplot is very quick:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
###############################################################################
# You may be wondering why the x-axis ranges from 0-3 and the y-axis
# from 1-4. If you provide a single list or array to the
# :func:`~matplotlib.pyplot.plot` command, matplotlib assumes it is a
# sequence of y values, and automatically generates the x values for
# you. Since python ranges start with 0, the default x vector has the
# same length as y but starts with 0. Hence the x data are
# ``[0,1,2,3]``.
#
# :func:`~matplotlib.pyplot.plot` is a versatile command, and will take
# an arbitrary number of arguments. For example, to plot x versus y,
# you can issue the command::
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
###############################################################################
# Formatting the style of your plot
# ---------------------------------
#
# For every x, y pair of arguments, there is an optional third argument
# which is the format string that indicates the color and line type of
# the plot. The letters and symbols of the format string are from
# MATLAB, and you concatenate a color string with a line style string.
# The default format string is 'b-', which is a solid blue line. For
# example, to plot the above with red circles, you would issue
plt.plot([1, 2, 3, 4], [1, 4, 9, 16], 'ro')
plt.axis([0, 6, 0, 20])
plt.show()
###############################################################################
# See the :func:`~matplotlib.pyplot.plot` documentation for a complete
# list of line styles and format strings. The
# :func:`~matplotlib.pyplot.axis` command in the example above takes a
# list of ``[xmin, xmax, ymin, ymax]`` and specifies the viewport of the
# axes.
#
# If matplotlib were limited to working with lists, it would be fairly
# useless for numeric processing. Generally, you will use `numpy
# `_ arrays. In fact, all sequences are
# converted to numpy arrays internally. The example below illustrates a
# plotting several lines with different format styles in one command
# using arrays.
import numpy as np
# evenly sampled time at 200ms intervals
t = np.arange(0., 5., 0.2)
# red dashes, blue squares and green triangles
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.show()
###############################################################################
# .. _plotting-with-keywords:
#
# Plotting with keyword strings
# =============================
#
# There are some instances where you have data in a format that lets you
# access particular variables with strings. For example, with
# :class:`numpy.recarray` or :class:`pandas.DataFrame`.
#
# Matplotlib allows you provide such an object with
# the ``data`` keyword argument. If provided, then you may generate plots with
# the strings corresponding to these variables.
data = {'a': np.arange(50),
'c': np.random.randint(0, 50, 50),
'd': np.random.randn(50)}
data['b'] = data['a'] + 10 * np.random.randn(50)
data['d'] = np.abs(data['d']) * 100
plt.scatter('a', 'b', c='c', s='d', data=data)
plt.xlabel('entry a')
plt.ylabel('entry b')
plt.show()
###############################################################################
# .. _plotting-with-categorical-vars:
#
# Plotting with categorical variables
# ===================================
#
# It is also possible to create a plot using categorical variables.
# Matplotlib allows you to pass categorical variables directly to
# many plotting functions. For example:
names = ['group_a', 'group_b', 'group_c']
values = [1, 10, 100]
plt.figure(1, figsize=(9, 3))
plt.subplot(131)
plt.bar(names, values)
plt.subplot(132)
plt.scatter(names, values)
plt.subplot(133)
plt.plot(names, values)
plt.suptitle('Categorical Plotting')
plt.show()
###############################################################################
# .. _controlling-line-properties:
#
# Controlling line properties
# ===========================
#
# Lines have many attributes that you can set: linewidth, dash style,
# antialiased, etc; see :class:`matplotlib.lines.Line2D`. There are
# several ways to set line properties
#
# * Use keyword args::
#
# plt.plot(x, y, linewidth=2.0)
#
#
# * Use the setter methods of a ``Line2D`` instance. ``plot`` returns a list
# of ``Line2D`` objects; e.g., ``line1, line2 = plot(x1, y1, x2, y2)``. In the code
# below we will suppose that we have only
# one line so that the list returned is of length 1. We use tuple unpacking with
# ``line,`` to get the first element of that list::
#
# line, = plt.plot(x, y, '-')
# line.set_antialiased(False) # turn off antialising
#
# * Use the :func:`~matplotlib.pyplot.setp` command. The example below
# uses a MATLAB-style command to set multiple properties
# on a list of lines. ``setp`` works transparently with a list of objects
# or a single object. You can either use python keyword arguments or
# MATLAB-style string/value pairs::
#
# lines = plt.plot(x1, y1, x2, y2)
# # use keyword args
# plt.setp(lines, color='r', linewidth=2.0)
# # or MATLAB style string value pairs
# plt.setp(lines, 'color', 'r', 'linewidth', 2.0)
#
#
# Here are the available :class:`~matplotlib.lines.Line2D` properties.
#
# ====================== ==================================================
# Property Value Type
# ====================== ==================================================
# alpha float
# animated [True | False]
# antialiased or aa [True | False]
# clip_box a matplotlib.transform.Bbox instance
# clip_on [True | False]
# clip_path a Path instance and a Transform instance, a Patch
# color or c any matplotlib color
# contains the hit testing function
# dash_capstyle [``'butt'`` | ``'round'`` | ``'projecting'``]
# dash_joinstyle [``'miter'`` | ``'round'`` | ``'bevel'``]
# dashes sequence of on/off ink in points
# data (np.array xdata, np.array ydata)
# figure a matplotlib.figure.Figure instance
# label any string
# linestyle or ls [ ``'-'`` | ``'--'`` | ``'-.'`` | ``':'`` | ``'steps'`` | ...]
# linewidth or lw float value in points
# lod [True | False]
# marker [ ``'+'`` | ``','`` | ``'.'`` | ``'1'`` | ``'2'`` | ``'3'`` | ``'4'`` ]
# markeredgecolor or mec any matplotlib color
# markeredgewidth or mew float value in points
# markerfacecolor or mfc any matplotlib color
# markersize or ms float
# markevery [ None | integer | (startind, stride) ]
# picker used in interactive line selection
# pickradius the line pick selection radius
# solid_capstyle [``'butt'`` | ``'round'`` | ``'projecting'``]
# solid_joinstyle [``'miter'`` | ``'round'`` | ``'bevel'``]
# transform a matplotlib.transforms.Transform instance
# visible [True | False]
# xdata np.array
# ydata np.array
# zorder any number
# ====================== ==================================================
#
# To get a list of settable line properties, call the
# :func:`~matplotlib.pyplot.setp` function with a line or lines
# as argument
#
# .. sourcecode:: ipython
#
# In [69]: lines = plt.plot([1, 2, 3])
#
# In [70]: plt.setp(lines)
# alpha: float
# animated: [True | False]
# antialiased or aa: [True | False]
# ...snip
#
# .. _multiple-figs-axes:
#
#
# Working with multiple figures and axes
# ======================================
#
# MATLAB, and :mod:`~matplotlib.pyplot`, have the concept of the current
# figure and the current axes. All plotting commands apply to the
# current axes. The function :func:`~matplotlib.pyplot.gca` returns the
# current axes (a :class:`matplotlib.axes.Axes` instance), and
# :func:`~matplotlib.pyplot.gcf` returns the current figure
# (:class:`matplotlib.figure.Figure` instance). Normally, you don't have
# to worry about this, because it is all taken care of behind the
# scenes. Below is a script to create two subplots.
def f(t):
return np.exp(-t) * np.cos(2*np.pi*t)
t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)
plt.figure(1)
plt.subplot(211)
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
plt.subplot(212)
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.show()
###############################################################################
# The :func:`~matplotlib.pyplot.figure` command here is optional because
# ``figure(1)`` will be created by default, just as a ``subplot(111)``
# will be created by default if you don't manually specify any axes. The
# :func:`~matplotlib.pyplot.subplot` command specifies ``numrows,
# numcols, fignum`` where ``fignum`` ranges from 1 to
# ``numrows*numcols``. The commas in the ``subplot`` command are
# optional if ``numrows*numcols<10``. So ``subplot(211)`` is identical
# to ``subplot(2, 1, 1)``.
#
# You can create an arbitrary number of subplots
# and axes. If you want to place an axes manually, i.e., not on a
# rectangular grid, use the :func:`~matplotlib.pyplot.axes` command,
# which allows you to specify the location as ``axes([left, bottom,
# width, height])`` where all values are in fractional (0 to 1)
# coordinates. See :ref:`sphx_glr_gallery_pylab_examples_axes_demo.py` for an example of
# placing axes manually and :ref:`sphx_glr_gallery_subplots_axes_and_figures_subplot_demo.py` for an
# example with lots of subplots.
#
#
# You can create multiple figures by using multiple
# :func:`~matplotlib.pyplot.figure` calls with an increasing figure
# number. Of course, each figure can contain as many axes and subplots
# as your heart desires::
#
# import matplotlib.pyplot as plt
# plt.figure(1) # the first figure
# plt.subplot(211) # the first subplot in the first figure
# plt.plot([1, 2, 3])
# plt.subplot(212) # the second subplot in the first figure
# plt.plot([4, 5, 6])
#
#
# plt.figure(2) # a second figure
# plt.plot([4, 5, 6]) # creates a subplot(111) by default
#
# plt.figure(1) # figure 1 current; subplot(212) still current
# plt.subplot(211) # make subplot(211) in figure1 current
# plt.title('Easy as 1, 2, 3') # subplot 211 title
#
# You can clear the current figure with :func:`~matplotlib.pyplot.clf`
# and the current axes with :func:`~matplotlib.pyplot.cla`. If you find
# it annoying that states (specifically the current image, figure and axes)
# are being maintained for you behind the scenes, don't despair: this is just a thin
# stateful wrapper around an object oriented API, which you can use
# instead (see :ref:`sphx_glr_tutorials_02_intermediate_artists.py`)
#
# If you are making lots of figures, you need to be aware of one
# more thing: the memory required for a figure is not completely
# released until the figure is explicitly closed with
# :func:`~matplotlib.pyplot.close`. Deleting all references to the
# figure, and/or using the window manager to kill the window in which
# the figure appears on the screen, is not enough, because pyplot
# maintains internal references until :func:`~matplotlib.pyplot.close`
# is called.
#
# .. _working-with-text:
#
# Working with text
# =================
#
# The :func:`~matplotlib.pyplot.text` command can be used to add text in
# an arbitrary location, and the :func:`~matplotlib.pyplot.xlabel`,
# :func:`~matplotlib.pyplot.ylabel` and :func:`~matplotlib.pyplot.title`
# are used to add text in the indicated locations (see :ref:`sphx_glr_tutorials_text_text_intro.py`
# for a more detailed example)
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='g', alpha=0.75)
plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()
###############################################################################
# All of the :func:`~matplotlib.pyplot.text` commands return an
# :class:`matplotlib.text.Text` instance. Just as with with lines
# above, you can customize the properties by passing keyword arguments
# into the text functions or using :func:`~matplotlib.pyplot.setp`::
#
# t = plt.xlabel('my data', fontsize=14, color='red')
#
# These properties are covered in more detail in :ref:`sphx_glr_tutorials_text_text_props.py`.
#
#
# Using mathematical expressions in text
# --------------------------------------
#
# matplotlib accepts TeX equation expressions in any text expression.
# For example to write the expression :math:`\sigma_i=15` in the title,
# you can write a TeX expression surrounded by dollar signs::
#
# plt.title(r'$\sigma_i=15$')
#
# The ``r`` preceding the title string is important -- it signifies
# that the string is a *raw* string and not to treat backslashes as
# python escapes. matplotlib has a built-in TeX expression parser and
# layout engine, and ships its own math fonts -- for details see
# :ref:`sphx_glr_tutorials_text_mathtext.py`. Thus you can use mathematical text across platforms
# without requiring a TeX installation. For those who have LaTeX and
# dvipng installed, you can also use LaTeX to format your text and
# incorporate the output directly into your display figures or saved
# postscript -- see :ref:`sphx_glr_tutorials_text_usetex.py`.
#
#
# Annotating text
# ---------------
#
# The uses of the basic :func:`~matplotlib.pyplot.text` command above
# place text at an arbitrary position on the Axes. A common use for
# text is to annotate some feature of the plot, and the
# :func:`~matplotlib.pyplot.annotate` method provides helper
# functionality to make annotations easy. In an annotation, there are
# two points to consider: the location being annotated represented by
# the argument ``xy`` and the location of the text ``xytext``. Both of
# these arguments are ``(x,y)`` tuples.
ax = plt.subplot(111)
t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = plt.plot(t, s, lw=2)
plt.annotate('local max', xy=(2, 1), xytext=(3, 1.5),
arrowprops=dict(facecolor='black', shrink=0.05),
)
plt.ylim(-2, 2)
plt.show()
###############################################################################
# In this basic example, both the ``xy`` (arrow tip) and ``xytext``
# locations (text location) are in data coordinates. There are a
# variety of other coordinate systems one can choose -- see
# :ref:`annotations-tutorial` and :ref:`plotting-guide-annotation` for
# details. More examples can be found in
# :ref:`sphx_glr_gallery_text_labels_and_annotations_annotation_demo.py`.
#
#
# Logarithmic and other nonlinear axes
# ====================================
#
# :mod:`matplotlib.pyplot` supports not only linear axis scales, but also
# logarithmic and logit scales. This is commonly used if data spans many orders
# of magnitude. Changing the scale of an axis is easy:
#
# plt.xscale('log')
#
# An example of four plots with the same data and different scales for the y axis
# is shown below.
from matplotlib.ticker import NullFormatter # useful for `logit` scale
# Fixing random state for reproducibility
np.random.seed(19680801)
# make up some data in the interval ]0, 1[
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(len(y))
# plot with various axes scales
plt.figure(1)
# linear
plt.subplot(221)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)
# log
plt.subplot(222)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)
# symmetric log
plt.subplot(223)
plt.plot(x, y - y.mean())
plt.yscale('symlog', linthreshy=0.01)
plt.title('symlog')
plt.grid(True)
# logit
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
plt.title('logit')
plt.grid(True)
# Format the minor tick labels of the y-axis into empty strings with
# `NullFormatter`, to avoid cumbering the axis with too many labels.
plt.gca().yaxis.set_minor_formatter(NullFormatter())
# Adjust the subplot layout, because the logit one may take more space
# than usual, due to y-tick labels like "1 - 10^{-3}"
plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
wspace=0.35)
plt.show()
###############################################################################
# It is also possible to add your own scale, see :ref:`adding-new-scales` for
# details.
PK#J48)8)01_introductory/sample_plots.py"""
==========================
Sample plots in Matplotlib
==========================
Here you'll find a host of example plots with the code that
generated them.
.. _matplotlibscreenshots:
Line Plot
=========
Here's how to create a line plot with text labels using
:func:`~matplotlib.pyplot.plot`.
.. figure:: ../../gallery/pylab_examples/images/sphx_glr_simple_plot_001.png
:target: ../../gallery/pylab_examples/simple_plot.html
:align: center
:scale: 50
Simple Plot
.. _screenshots_subplot_demo:
Subplot demo
============
Multiple axes (i.e. subplots) are created with the
:func:`~matplotlib.pyplot.subplot` command:
.. figure:: ../../gallery/subplots_axes_and_figures/images/sphx_glr_subplot_001.png
:target: ../../gallery/subplots_axes_and_figures/subplot.html
:align: center
:scale: 50
Subplot
.. _screenshots_histogram_demo:
Histograms
==========
The :func:`~matplotlib.pyplot.hist` command automatically generates
histograms and returns the bin counts or probabilities:
.. figure:: ../../gallery/statistics/images/sphx_glr_histogram_features_001.png
:target: ../../gallery/statistics/histogram_features.html
:align: center
:scale: 50
Histogram Features
.. _screenshots_path_demo:
Path demo
=========
You can add arbitrary paths in Matplotlib using the
:mod:`matplotlib.path` module:
.. figure:: ../../gallery/shapes_and_collections/images/sphx_glr_path_patch_001.png
:target: ../../gallery/shapes_and_collections/path_patch.html
:align: center
:scale: 50
Path Patch
.. _screenshots_mplot3d_surface:
mplot3d
=========
The mplot3d toolkit (see :ref:`toolkit_mplot3d-tutorial` and
:ref:`mplot3d-examples-index`) has support for simple 3d graphs
including surface, wireframe, scatter, and bar charts.
.. figure:: ../../gallery/mplot3d/images/sphx_glr_surface3d_001.png
:target: ../../gallery/mplot3d/surface3d.html
:align: center
:scale: 50
Surface3d
Thanks to John Porter, Jonathon Taylor, Reinier Heeres, and Ben Root for
the `mplot3d` toolkit. This toolkit is included with all standard Matplotlib
installs.
.. _screenshots_ellipse_demo:
Streamplot
==========
The :meth:`~matplotlib.pyplot.streamplot` function plots the streamlines of
a vector field. In addition to simply plotting the streamlines, it allows you
to map the colors and/or line widths of streamlines to a separate parameter,
such as the speed or local intensity of the vector field.
.. figure:: ../../gallery/images_contours_and_fields/images/sphx_glr_plot_streamplot_001.png
:target: ../../gallery/images_contours_and_fields/plot_streamplot.html
:align: center
:scale: 50
Plot Streamplot
This feature complements the :meth:`~matplotlib.pyplot.quiver` function for
plotting vector fields. Thanks to Tom Flannaghan and Tony Yu for adding the
streamplot function.
Ellipses
========
In support of the
`Phoenix `_ mission to
Mars (which used Matplotlib to display ground tracking of spacecraft),
Michael Droettboom built on work by Charlie Moad to provide an extremely
accurate 8-spline approximation to elliptical arcs (see
:class:`~matplotlib.patches.Arc`), which are insensitive to zoom level.
.. figure:: ../../gallery/pylab_examples/images/sphx_glr_ellipse_demo_001.png
:target: ../../gallery/pylab_examples/ellipse_demo.html
:align: center
:scale: 50
Ellipse Demo
.. _screenshots_barchart_demo:
Bar charts
==========
Use the :func:`~matplotlib.pyplot.bar` command to make bar charts, which
includes customizations such as error bars:
.. figure:: ../../gallery/statistics/images/sphx_glr_barchart_demo_001.png
:target: ../../gallery/statistics/barchart_demo.html
:align: center
:scale: 50
Barchart Demo
You can also create stacked bars
(`bar_stacked.py <../../gallery/pylab_examples/bar_stacked.html>`_),
or horizontal bar charts
(`barh.py <../../gallery/lines_bars_and_markers/barh.html>`_).
.. _screenshots_pie_demo:
Pie charts
==========
The :func:`~matplotlib.pyplot.pie` command allows you to create pie
charts. Optional features include auto-labeling the percentage of area,
exploding one or more wedges from the center of the pie, and a shadow effect.
Take a close look at the attached code, which generates this figure in just
a few lines of code.
.. figure:: ../../gallery/pie_and_polar_charts/images/sphx_glr_pie_features_001.png
:target: ../../gallery/pie_and_polar_charts/pie_features.html
:align: center
:scale: 50
Pie Features
.. _screenshots_table_demo:
Table demo
==========
The :func:`~matplotlib.pyplot.table` command adds a text table
to an axes.
.. figure:: ../../gallery/pylab_examples/images/sphx_glr_table_demo_001.png
:target: ../../gallery/pylab_examples/table_demo.html
:align: center
:scale: 50
Table Demo
.. _screenshots_scatter_demo:
Scatter demo
============
The :func:`~matplotlib.pyplot.scatter` command makes a scatter plot
with (optional) size and color arguments. This example plots changes
in Google's stock price, with marker sizes reflecting the
trading volume and colors varying with time. Here, the
alpha attribute is used to make semitransparent circle markers.
.. figure:: ../../gallery/lines_bars_and_markers/images/sphx_glr_scatter_demo2_001.png
:target: ../../gallery/lines_bars_and_markers/scatter_demo2.html
:align: center
:scale: 50
Scatter Demo2
.. _screenshots_slider_demo:
Slider demo
===========
Matplotlib has basic GUI widgets that are independent of the graphical
user interface you are using, allowing you to write cross GUI figures
and widgets. See :mod:`matplotlib.widgets` and the
`widget examples <../../gallery/index.html>`_.
.. figure:: ../../gallery/widgets/images/sphx_glr_slider_demo_001.png
:target: ../../gallery/widgets/slider_demo.html
:align: center
:scale: 50
Slider Demo
.. _screenshots_fill_demo:
Fill demo
=========
The :func:`~matplotlib.pyplot.fill` command lets you
plot filled curves and polygons:
.. figure:: ../../gallery/lines_bars_and_markers/images/sphx_glr_fill_001.png
:target: ../../gallery/lines_bars_and_markers/fill.html
:align: center
:scale: 50
Fill
Thanks to Andrew Straw for adding this function.
.. _screenshots_date_demo:
Date demo
=========
You can plot timeseries data with major and minor ticks and custom
tick formatters for both.
.. figure:: ../../gallery/api/images/sphx_glr_date_001.png
:target: ../../gallery/api/date.html
:align: center
:scale: 50
Date
See :mod:`matplotlib.ticker` and :mod:`matplotlib.dates` for details and usage.
.. _screenshots_log_demo:
Log plots
=========
The :func:`~matplotlib.pyplot.semilogx`,
:func:`~matplotlib.pyplot.semilogy` and
:func:`~matplotlib.pyplot.loglog` functions simplify the creation of
logarithmic plots.
.. figure:: ../../gallery/pylab_examples/images/sphx_glr_log_demo_001.png
:target: ../../gallery/pylab_examples/log_demo.html
:align: center
:scale: 50
Log Demo
Thanks to Andrew Straw, Darren Dale and Gregory Lielens for contributions
log-scaling infrastructure.
.. _screenshots_polar_demo:
Polar plots
===========
The :func:`~matplotlib.pyplot.polar` command generates polar plots.
.. figure:: ../../gallery/pylab_examples/images/sphx_glr_polar_demo_001.png
:target: ../../gallery/pylab_examples/polar_demo.html
:align: center
:scale: 50
Polar Demo
.. _screenshots_legend_demo:
Legends
=======
The :func:`~matplotlib.pyplot.legend` command automatically
generates figure legends, with MATLAB-compatible legend placement
commands.
.. figure:: ../../gallery/api/images/sphx_glr_legend_001.png
:target: ../../gallery/api/legend.html
:align: center
:scale: 50
Legend
Thanks to Charles Twardy for input on the legend command.
.. _screenshots_mathtext_examples_demo:
Mathtext_examples
=================
Below is a sampling of the many TeX expressions now supported by Matplotlib's
internal mathtext engine. The mathtext module provides TeX style mathematical
expressions using `FreeType `_
and the DejaVu, BaKoMa computer modern, or `STIX `_
fonts. See the :mod:`matplotlib.mathtext` module for additional details.
.. figure:: ../../gallery/text_labels_and_annotations/images/sphx_glr_mathtext_examples_001.png
:target: ../../gallery/text_labels_and_annotations/mathtext_examples.html
:align: center
:scale: 50
Mathtext Examples
Matplotlib's mathtext infrastructure is an independent implementation and
does not require TeX or any external packages installed on your computer. See
the tutorial at :ref:`sphx_glr_tutorials_text_mathtext.py`.
.. _screenshots_tex_demo:
Native TeX rendering
====================
Although Matplotlib's internal math rendering engine is quite
powerful, sometimes you need TeX. Matplotlib supports external TeX
rendering of strings with the *usetex* option.
.. figure:: ../../gallery/text_labels_and_annotations/images/sphx_glr_tex_demo_001.png
:target: ../../gallery/text_labels_and_annotations/tex_demo.html
:align: center
:scale: 50
Tex Demo
.. _screenshots_eeg_demo:
EEG demo
=========
You can embed Matplotlib into pygtk, wx, Tk, or Qt applications.
Here is a screenshot of an EEG viewer called `pbrain
`__.
.. image:: ../../_static/eeg_small.png
The lower axes uses :func:`~matplotlib.pyplot.specgram`
to plot the spectrogram of one of the EEG channels.
For examples of how to embed Matplotlib in different toolkits, see:
* :ref:`sphx_glr_gallery_user_interfaces_embedding_in_gtk2_sgskip.py`
* :ref:`sphx_glr_gallery_user_interfaces_embedding_in_wx2_sgskip.py`
* :ref:`sphx_glr_gallery_user_interfaces_mpl_with_glade_sgskip.py`
* :ref:`sphx_glr_gallery_user_interfaces_embedding_in_qt4_sgskip.py`
* :ref:`sphx_glr_gallery_user_interfaces_embedding_in_tk_sgskip.py`
XKCD-style sketch plots
=======================
Matplotlib supports plotting in the style of `xkcd
`.
.. figure:: ../../gallery/showcase/images/sphx_glr_xkcd_001.png
:target: ../../gallery/showcase/xkcd.html
:align: center
:scale: 50
Xkcd
"""
# An extra set of sample plots for the thumbnail image.
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(19680801)
data = np.random.randn(2, 100)
fig, axs = plt.subplots(2, 2, figsize=(5, 5))
axs[0, 0].hist(data[0])
axs[1, 0].scatter(data[0], data[1])
axs[0, 1].plot(data[0], data[1])
axs[1, 1].hist2d(data[0], data[1])
plt.show()
PK#J2ǑF''01_introductory/lifecycle.py"""
=======================
The Lifecycle of a Plot
=======================
This tutorial aims to show the beginning, middle, and end of a single
visualization using Matplotlib. We'll begin with some raw data and
end by saving a figure of a customized visualization. Along the way we'll try
to highlight some neat features and best-practices using Matplotlib.
.. currentmodule:: matplotlib
.. note::
This tutorial is based off of
`this excellent blog post `_
by Chris Moffitt. It was transformed into this tutorial by Chris Holdgraf.
A note on the Object-Oriented API vs Pyplot
===========================================
Matplotlib has two interfaces. The first is an object-oriented (OO)
interface. In this case, we utilize an instance of :class:`axes.Axes`
in order to render visualizations on an instance of :class:`figure.Figure`.
The second is based on MATLAB and uses
a state-based interface. This is encapsulated in the :mod:`pyplot`
module. See the :ref:`pyplot tutorials
`
for a more in-depth look at the pyplot interface.
Most of the terms are straightforward but the main thing to remember
is that:
* The Figure is the final image that may contain 1 or more Axes.
* The Axes represent an individual plot (don't confuse this with the word
"axis", which refers to the x/y axis of a plot).
We call methods that do the plotting directly from the Axes, which gives
us much more flexibility and power in customizing our plot. See the
:ref:`object-oriented examples ` for many examples of how
this approach is used.
.. note::
In general, try to use the object-oriented interface over the pyplot
interface.
Our data
========
We'll use the data from the post from which this tutorial was derived.
It contains sales information for a number of companies.
"""
# sphinx_gallery_thumbnail_number = 10
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
data = {'Barton LLC': 109438.50,
'Frami, Hills and Schmidt': 103569.59,
'Fritsch, Russel and Anderson': 112214.71,
'Jerde-Hilpert': 112591.43,
'Keeling LLC': 100934.30,
'Koepp Ltd': 103660.54,
'Kulas Inc': 137351.96,
'Trantow-Barrows': 123381.38,
'White-Trantow': 135841.99,
'Will LLC': 104437.60}
group_data = list(data.values())
group_names = list(data.keys())
group_mean = np.mean(group_data)
###############################################################################
# Getting started
# ===============
#
# This data is naturally visualized as a barplot, with one bar per
# group. To do this with the object-oriented approach, we'll first generate
# an instance of :class:`figure.Figure` and
# :class:`axes.Axes`. The Figure is like a canvas, and the Axes
# is a part of that canvas on which we will make a particular visualization.
#
# .. note::
#
# Figures can have multiple axes on them. For information on how to do this,
# see the :ref:`Tight Layout tutorial
# `.
fig, ax = plt.subplots()
###############################################################################
# Now that we have an Axes instance, we can plot on top of it.
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
###############################################################################
# Controlling the style
# =====================
#
# There are many styles available in Matplotlib in order to let you tailor
# your visualization to your needs. To see a list of styles, we can use
# :mod:`pyplot.style`.
print(plt.style.available)
###############################################################################
# You can activate a style with the following:
plt.style.use('fivethirtyeight')
###############################################################################
# Now let's remake the above plot to see how it looks:
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
###############################################################################
# The style controls many things, such as color, linewidths, backgrounds,
# etc.
#
# Customizing the plot
# ====================
#
# Now we've got a plot with the general look that we want, so let's fine-tune
# it so that it's ready for print. First let's rotate the labels on the x-axis
# so that they show up more clearly. We can gain access to these labels
# with the :meth:`axes.Axes.get_xticklabels` method:
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
###############################################################################
# If we'd like to set the property of many items at once, it's useful to use
# the :func:`pyplot.setp` function. This will take a list (or many lists) of
# Matplotlib objects, and attempt to set some style element of each one.
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
###############################################################################
# It looks like this cut off some of the labels on the bottom. We can
# tell Matplotlib to automatically make room for elements in the figures
# that we create. To do this we'll set the ``autolayout`` value of our
# rcParams. For more information on controlling the style, layout, and
# other features of plots with rcParams, see
# :ref:`sphx_glr_tutorials_01_introductory_customizing.py`.
plt.rcParams.update({'figure.autolayout': True})
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
###############################################################################
# Next, we'll add labels to the plot. To do this with the OO interface,
# we can use the :meth:`axes.Axes.set` method to set properties of this
# Axes object.
fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
###############################################################################
# We can also adjust the size of this plot using the :func:`pyplot.subplots`
# function. We can do this with the ``figsize`` kwarg.
#
# .. note::
#
# While indexing in NumPy follows the form (row, column), the figsize
# kwarg follows the form (width, height). This follows conventions in
# visualization, which unfortunately are different from those of linear
# algebra.
fig, ax = plt.subplots(figsize=(8, 4))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
###############################################################################
# For labels, we can specify custom formatting guidelines in the form of
# functions by using the :class:`ticker.FuncFormatter` class. Below we'll
# define a function that takes an integer as input, and returns a string
# as an output.
def currency(x, pos):
"""The two args are the value and tick position"""
if x >= 1e6:
s = '${:1.1f}M'.format(x*1e-6)
else:
s = '${:1.0f}K'.format(x*1e-3)
return s
formatter = FuncFormatter(currency)
###############################################################################
# We can then apply this formatter to the labels on our plot. To do this,
# we'll use the ``xaxis`` attribute of our axis. This lets you perform
# actions on a specific axis on our plot.
fig, ax = plt.subplots(figsize=(6, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
ax.xaxis.set_major_formatter(formatter)
###############################################################################
# Combining multiple visualizations
# =================================
#
# It is possible to draw multiple plot elements on the same instance of
# :class:`axes.Axes`. To do this we simply need to call another one of
# the plot methods on that axes object.
fig, ax = plt.subplots(figsize=(8, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
# Add a vertical line, here we set the style in the function call
ax.axvline(group_mean, ls='--', color='r')
# Annotate new companies
for group in [3, 5, 8]:
ax.text(145000, group, "New Company", fontsize=10,
verticalalignment="center")
# Now we'll move our title up since it's getting a little cramped
ax.title.set(y=1.05)
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
title='Company Revenue')
ax.xaxis.set_major_formatter(formatter)
ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
fig.subplots_adjust(right=.1)
plt.show()
###############################################################################
# Saving our plot
# ===============
#
# Now that we're happy with the outcome of our plot, we want to save it to
# disk. There are many file formats we can save to in Matplotlib. To see
# a list of available options, use:
print(fig.canvas.get_supported_filetypes())
###############################################################################
# We can then use the :meth:`figure.Figure.savefig` in order to save the figure
# to disk. Note that there are several useful flags we'll show below:
#
# * ``transparent=True`` makes the background of the saved figure transparent
# if the format supports it.
# * ``dpi=80`` controls the resolution (dots per square inch) of the output.
# * ``bbox_inches="tight"`` fits the bounds of the figure to our plot.
# Uncomment this line to save the figure.
# fig.savefig('sales.png', transparent=False, dpi=80, bbox_inches="tight")
PK#J#++02_intermediate/legend_guide.py"""
============
Legend guide
============
Generating legends flexibly in Matplotlib.
.. currentmodule:: matplotlib.pyplot
This legend guide is an extension of the documentation available at
:func:`~matplotlib.pyplot.legend` - please ensure you are familiar with
contents of that documentation before proceeding with this guide.
This guide makes use of some common terms, which are documented here for clarity:
.. glossary::
legend entry
A legend is made up of one or more legend entries. An entry is made up of
exactly one key and one label.
legend key
The colored/patterned marker to the left of each legend label.
legend label
The text which describes the handle represented by the key.
legend handle
The original object which is used to generate an appropriate entry in
the legend.
Controlling the legend entries
==============================
Calling :func:`legend` with no arguments automatically fetches the legend
handles and their associated labels. This functionality is equivalent to::
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)
The :meth:`~matplotlib.axes.Axes.get_legend_handles_labels` function returns
a list of handles/artists which exist on the Axes which can be used to
generate entries for the resulting legend - it is worth noting however that
not all artists can be added to a legend, at which point a "proxy" will have
to be created (see :ref:`proxy_legend_handles` for further details).
# For full control of what is being added to the legend, it is common to pass
# the appropriate handles directly to :func:`legend`
line_up, = plt.plot([1,2,3], label='Line 2')
line_down, = plt.plot([3,2,1], label='Line 1')
plt.legend(handles=[line_up, line_down])
In some cases, it is not possible to set the label of the handle, so it is
possible to pass through the list of labels to :func:`legend`::
line_up, = plt.plot([1,2,3], label='Line 2')
line_down, = plt.plot([3,2,1], label='Line 1')
plt.legend([line_up, line_down], ['Line Up', 'Line Down'])
.. _proxy_legend_handles:
Creating artists specifically for adding to the legend (aka. Proxy artists)
===========================================================================
Not all handles can be turned into legend entries automatically,
so it is often necessary to create an artist which *can*. Legend handles
don't have to exists on the Figure or Axes in order to be used.
Suppose we wanted to create a legend which has an entry for some data which
is represented by a red color:
"""
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
red_patch = mpatches.Patch(color='red', label='The red data')
plt.legend(handles=[red_patch])
plt.show()
###############################################################################
# There are many supported legend handles, instead of creating a patch of color
# we could have created a line with a marker:
import matplotlib.lines as mlines
blue_line = mlines.Line2D([], [], color='blue', marker='*',
markersize=15, label='Blue stars')
plt.legend(handles=[blue_line])
plt.show()
###############################################################################
# Legend location
# ===============
#
# The location of the legend can be specified by the keyword argument
# *loc*. Please see the documentation at :func:`legend` for more details.
#
# The ``bbox_to_anchor`` keyword gives a great degree of control for manual
# legend placement. For example, if you want your axes legend located at the
# figure's top right-hand corner instead of the axes' corner, simply specify
# the corner's location, and the coordinate system of that location::
#
# plt.legend(bbox_to_anchor=(1, 1),
# bbox_transform=plt.gcf().transFigure)
#
# More examples of custom legend placement:
plt.subplot(211)
plt.plot([1, 2, 3], label="test1")
plt.plot([3, 2, 1], label="test2")
# Place a legend above this subplot, expanding itself to
# fully use the given bounding box.
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
ncol=2, mode="expand", borderaxespad=0.)
plt.subplot(223)
plt.plot([1, 2, 3], label="test1")
plt.plot([3, 2, 1], label="test2")
# Place a legend to the right of this smaller subplot.
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
###############################################################################
# Multiple legends on the same Axes
# =================================
#
# Sometimes it is more clear to split legend entries across multiple
# legends. Whilst the instinctive approach to doing this might be to call
# the :func:`legend` function multiple times, you will find that only one
# legend ever exists on the Axes. This has been done so that it is possible
# to call :func:`legend` repeatedly to update the legend to the latest
# handles on the Axes, so to persist old legend instances, we must add them
# manually to the Axes:
line1, = plt.plot([1, 2, 3], label="Line 1", linestyle='--')
line2, = plt.plot([3, 2, 1], label="Line 2", linewidth=4)
# Create a legend for the first line.
first_legend = plt.legend(handles=[line1], loc=1)
# Add the legend manually to the current Axes.
ax = plt.gca().add_artist(first_legend)
# Create another legend for the second line.
plt.legend(handles=[line2], loc=4)
plt.show()
###############################################################################
# Legend Handlers
# ===============
#
# In order to create legend entries, handles are given as an argument to an
# appropriate :class:`~matplotlib.legend_handler.HandlerBase` subclass.
# The choice of handler subclass is determined by the following rules:
#
# 1. Update :func:`~matplotlib.legend.Legend.get_legend_handler_map`
# with the value in the ``handler_map`` keyword.
# 2. Check if the ``handle`` is in the newly created ``handler_map``.
# 3. Check if the type of ``handle`` is in the newly created
# ``handler_map``.
# 4. Check if any of the types in the ``handle``'s mro is in the newly
# created ``handler_map``.
#
# For completeness, this logic is mostly implemented in
# :func:`~matplotlib.legend.Legend.get_legend_handler`.
#
# All of this flexibility means that we have the necessary hooks to implement
# custom handlers for our own type of legend key.
#
# The simplest example of using custom handlers is to instantiate one of the
# existing :class:`~matplotlib.legend_handler.HandlerBase` subclasses. For the
# sake of simplicity, let's choose :class:`matplotlib.legend_handler.HandlerLine2D`
# which accepts a ``numpoints`` argument (note numpoints is a keyword
# on the :func:`legend` function for convenience). We can then pass the mapping
# of instance to Handler as a keyword to legend.
from matplotlib.legend_handler import HandlerLine2D
line1, = plt.plot([3, 2, 1], marker='o', label='Line 1')
line2, = plt.plot([1, 2, 3], marker='o', label='Line 2')
plt.legend(handler_map={line1: HandlerLine2D(numpoints=4)})
###############################################################################
# As you can see, "Line 1" now has 4 marker points, where "Line 2" has 2 (the
# default). Try the above code, only change the map's key from ``line1`` to
# ``type(line1)``. Notice how now both :class:`~matplotlib.lines.Line2D` instances
# get 4 markers.
#
# Along with handlers for complex plot types such as errorbars, stem plots
# and histograms, the default ``handler_map`` has a special ``tuple`` handler
# (:class:`~matplotlib.legend_handler.HandlerTuple`) which simply plots
# the handles on top of one another for each item in the given tuple. The
# following example demonstrates combining two legend keys on top of one another:
from numpy.random import randn
z = randn(10)
red_dot, = plt.plot(z, "ro", markersize=15)
# Put a white cross over some of the data.
white_cross, = plt.plot(z[:5], "w+", markeredgewidth=3, markersize=15)
plt.legend([red_dot, (red_dot, white_cross)], ["Attr A", "Attr A+B"])
###############################################################################
# The :class:`~matplotlib.legend_handler.HandlerTuple` class can also be used to
# assign several legend keys to the same entry:
from matplotlib.legend_handler import HandlerLine2D, HandlerTuple
p1, = plt.plot([1, 2.5, 3], 'r-d')
p2, = plt.plot([3, 2, 1], 'k-o')
l = plt.legend([(p1, p2)], ['Two keys'], numpoints=1,
handler_map={tuple: HandlerTuple(ndivide=None)})
###############################################################################
# Implementing a custom legend handler
# ------------------------------------
#
# A custom handler can be implemented to turn any handle into a legend key (handles
# don't necessarily need to be matplotlib artists).
# The handler must implement a "legend_artist" method which returns a
# single artist for the legend to use. Signature details about the "legend_artist"
# are documented at :meth:`~matplotlib.legend_handler.HandlerBase.legend_artist`.
import matplotlib.patches as mpatches
class AnyObject(object):
pass
class AnyObjectHandler(object):
def legend_artist(self, legend, orig_handle, fontsize, handlebox):
x0, y0 = handlebox.xdescent, handlebox.ydescent
width, height = handlebox.width, handlebox.height
patch = mpatches.Rectangle([x0, y0], width, height, facecolor='red',
edgecolor='black', hatch='xx', lw=3,
transform=handlebox.get_transform())
handlebox.add_artist(patch)
return patch
plt.legend([AnyObject()], ['My first handler'],
handler_map={AnyObject: AnyObjectHandler()})
###############################################################################
# Alternatively, had we wanted to globally accept ``AnyObject`` instances without
# needing to manually set the ``handler_map`` keyword all the time, we could have
# registered the new handler with::
#
# from matplotlib.legend import Legend
# Legend.update_default_handler_map({AnyObject: AnyObjectHandler()})
#
# Whilst the power here is clear, remember that there are already many handlers
# implemented and what you want to achieve may already be easily possible with
# existing classes. For example, to produce elliptical legend keys, rather than
# rectangular ones:
from matplotlib.legend_handler import HandlerPatch
class HandlerEllipse(HandlerPatch):
def create_artists(self, legend, orig_handle,
xdescent, ydescent, width, height, fontsize, trans):
center = 0.5 * width - 0.5 * xdescent, 0.5 * height - 0.5 * ydescent
p = mpatches.Ellipse(xy=center, width=width + xdescent,
height=height + ydescent)
self.update_prop(p, orig_handle, legend)
p.set_transform(trans)
return [p]
c = mpatches.Circle((0.5, 0.5), 0.25, facecolor="green",
edgecolor="red", linewidth=3)
plt.gca().add_patch(c)
plt.legend([c], ["An ellipse, not a rectangle"],
handler_map={mpatches.Circle: HandlerEllipse()})
PK#J`4rr02_intermediate/artists.py"""
===============
Artist tutorial
===============
Using Artist objects to render on the canvas.
There are three layers to the matplotlib API.
* the :class:`matplotlib.backend_bases.FigureCanvas` is the area onto which
the figure is drawn
* the :class:`matplotlib.backend_bases.Renderer` is
the object which knows how to draw on the
:class:`~matplotlib.backend_bases.FigureCanvas`
* and the :class:`matplotlib.artist.Artist` is the object that knows how to use
a renderer to paint onto the canvas.
The :class:`~matplotlib.backend_bases.FigureCanvas` and
:class:`~matplotlib.backend_bases.Renderer` handle all the details of
talking to user interface toolkits like `wxPython
`_ or drawing languages like PostScript®, and
the ``Artist`` handles all the high level constructs like representing
and laying out the figure, text, and lines. The typical user will
spend 95% of their time working with the ``Artists``.
There are two types of ``Artists``: primitives and containers. The primitives
represent the standard graphical objects we want to paint onto our canvas:
:class:`~matplotlib.lines.Line2D`, :class:`~matplotlib.patches.Rectangle`,
:class:`~matplotlib.text.Text`, :class:`~matplotlib.image.AxesImage`, etc., and
the containers are places to put them (:class:`~matplotlib.axis.Axis`,
:class:`~matplotlib.axes.Axes` and :class:`~matplotlib.figure.Figure`). The
standard use is to create a :class:`~matplotlib.figure.Figure` instance, use
the ``Figure`` to create one or more :class:`~matplotlib.axes.Axes` or
:class:`~matplotlib.axes.Subplot` instances, and use the ``Axes`` instance
helper methods to create the primitives. In the example below, we create a
``Figure`` instance using :func:`matplotlib.pyplot.figure`, which is a
convenience method for instantiating ``Figure`` instances and connecting them
with your user interface or drawing toolkit ``FigureCanvas``. As we will
discuss below, this is not necessary -- you can work directly with PostScript,
PDF Gtk+, or wxPython ``FigureCanvas`` instances, instantiate your ``Figures``
directly and connect them yourselves -- but since we are focusing here on the
``Artist`` API we'll let :mod:`~matplotlib.pyplot` handle some of those details
for us::
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(2,1,1) # two rows, one column, first plot
The :class:`~matplotlib.axes.Axes` is probably the most important
class in the matplotlib API, and the one you will be working with most
of the time. This is because the ``Axes`` is the plotting area into
which most of the objects go, and the ``Axes`` has many special helper
methods (:meth:`~matplotlib.axes.Axes.plot`,
:meth:`~matplotlib.axes.Axes.text`,
:meth:`~matplotlib.axes.Axes.hist`,
:meth:`~matplotlib.axes.Axes.imshow`) to create the most common
graphics primitives (:class:`~matplotlib.lines.Line2D`,
:class:`~matplotlib.text.Text`,
:class:`~matplotlib.patches.Rectangle`,
:class:`~matplotlib.image.Image`, respectively). These helper methods
will take your data (e.g., ``numpy`` arrays and strings) and create
primitive ``Artist`` instances as needed (e.g., ``Line2D``), add them to
the relevant containers, and draw them when requested. Most of you
are probably familiar with the :class:`~matplotlib.axes.Subplot`,
which is just a special case of an ``Axes`` that lives on a regular
rows by columns grid of ``Subplot`` instances. If you want to create
an ``Axes`` at an arbitrary location, simply use the
:meth:`~matplotlib.figure.Figure.add_axes` method which takes a list
of ``[left, bottom, width, height]`` values in 0-1 relative figure
coordinates::
fig2 = plt.figure()
ax2 = fig2.add_axes([0.15, 0.1, 0.7, 0.3])
Continuing with our example::
import numpy as np
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax.plot(t, s, color='blue', lw=2)
In this example, ``ax`` is the ``Axes`` instance created by the
``fig.add_subplot`` call above (remember ``Subplot`` is just a
subclass of ``Axes``) and when you call ``ax.plot``, it creates a
``Line2D`` instance and adds it to the :attr:`Axes.lines
` list. In the interactive `ipython
`_ session below, you can see that the
``Axes.lines`` list is length one and contains the same line that was
returned by the ``line, = ax.plot...`` call:
.. sourcecode:: ipython
In [101]: ax.lines[0]
Out[101]:
In [102]: line
Out[102]:
If you make subsequent calls to ``ax.plot`` (and the hold state is "on"
which is the default) then additional lines will be added to the list.
You can remove lines later simply by calling the list methods; either
of these will work::
del ax.lines[0]
ax.lines.remove(line) # one or the other, not both!
The Axes also has helper methods to configure and decorate the x-axis
and y-axis tick, tick labels and axis labels::
xtext = ax.set_xlabel('my xdata') # returns a Text instance
ytext = ax.set_ylabel('my ydata')
When you call :meth:`ax.set_xlabel `,
it passes the information on the :class:`~matplotlib.text.Text`
instance of the :class:`~matplotlib.axis.XAxis`. Each ``Axes``
instance contains an :class:`~matplotlib.axis.XAxis` and a
:class:`~matplotlib.axis.YAxis` instance, which handle the layout and
drawing of the ticks, tick labels and axis labels.
.. I'm commenting this out, since the new Sphinx cross-references
.. sort of take care of this above - MGD
.. Here are the most important matplotlib modules that contain the
.. classes referenced above
.. =============== ==================
.. Artist Module
.. =============== ==================
.. Artist matplotlib.artist
.. Rectangle matplotlib.patches
.. Line2D matplotlib.lines
.. Axes matplotlib.axes
.. XAxis and YAxis matplotlib.axis
.. Figure matplotlib.figure
.. Text matplotlib.text
.. =============== ==================
Try creating the figure below.
"""
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
fig.subplots_adjust(top=0.8)
ax1 = fig.add_subplot(211)
ax1.set_ylabel('volts')
ax1.set_title('a sine wave')
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax1.plot(t, s, color='blue', lw=2)
# Fixing random state for reproducibility
np.random.seed(19680801)
ax2 = fig.add_axes([0.15, 0.1, 0.7, 0.3])
n, bins, patches = ax2.hist(np.random.randn(1000), 50,
facecolor='yellow', edgecolor='yellow')
ax2.set_xlabel('time (s)')
plt.show()
###############################################################################
# .. _customizing-artists:
#
# Customizing your objects
# ========================
#
# Every element in the figure is represented by a matplotlib
# :class:`~matplotlib.artist.Artist`, and each has an extensive list of
# properties to configure its appearance. The figure itself contains a
# :class:`~matplotlib.patches.Rectangle` exactly the size of the figure,
# which you can use to set the background color and transparency of the
# figures. Likewise, each :class:`~matplotlib.axes.Axes` bounding box
# (the standard white box with black edges in the typical matplotlib
# plot, has a ``Rectangle`` instance that determines the color,
# transparency, and other properties of the Axes. These instances are
# stored as member variables :attr:`Figure.patch
# ` and :attr:`Axes.patch
# ` ("Patch" is a name inherited from
# MATLAB, and is a 2D "patch" of color on the figure, e.g., rectangles,
# circles and polygons). Every matplotlib ``Artist`` has the following
# properties
#
# ========== ================================================================================
# Property Description
# ========== ================================================================================
# alpha The transparency - a scalar from 0-1
# animated A boolean that is used to facilitate animated drawing
# axes The axes that the Artist lives in, possibly None
# clip_box The bounding box that clips the Artist
# clip_on Whether clipping is enabled
# clip_path The path the artist is clipped to
# contains A picking function to test whether the artist contains the pick point
# figure The figure instance the artist lives in, possibly None
# label A text label (e.g., for auto-labeling)
# picker A python object that controls object picking
# transform The transformation
# visible A boolean whether the artist should be drawn
# zorder A number which determines the drawing order
# rasterized Boolean; Turns vectors into rastergraphics: (for compression & eps transparency)
# ========== ================================================================================
#
# Each of the properties is accessed with an old-fashioned setter or
# getter (yes we know this irritates Pythonistas and we plan to support
# direct access via properties or traits but it hasn't been done yet).
# For example, to multiply the current alpha by a half::
#
# a = o.get_alpha()
# o.set_alpha(0.5*a)
#
# If you want to set a number of properties at once, you can also use
# the ``set`` method with keyword arguments. For example::
#
# o.set(alpha=0.5, zorder=2)
#
# If you are working interactively at the python shell, a handy way to
# inspect the ``Artist`` properties is to use the
# :func:`matplotlib.artist.getp` function (simply
# :func:`~matplotlib.pylab.getp` in pylab), which lists the properties
# and their values. This works for classes derived from ``Artist`` as
# well, e.g., ``Figure`` and ``Rectangle``. Here are the ``Figure`` rectangle
# properties mentioned above:
#
# .. sourcecode:: ipython
#
# In [149]: matplotlib.artist.getp(fig.patch)
# alpha = 1.0
# animated = False
# antialiased or aa = True
# axes = None
# clip_box = None
# clip_on = False
# clip_path = None
# contains = None
# edgecolor or ec = w
# facecolor or fc = 0.75
# figure = Figure(8.125x6.125)
# fill = 1
# hatch = None
# height = 1
# label =
# linewidth or lw = 1.0
# picker = None
# transform =
# verts = ((0, 0), (0, 1), (1, 1), (1, 0))
# visible = True
# width = 1
# window_extent =
# x = 0
# y = 0
# zorder = 1
#
# .. TODO: Update these URLs
#
# The docstrings for all of the classes also contain the ``Artist``
# properties, so you can consult the interactive "help" or the
# :ref:`artist-api` for a listing of properties for a given object.
#
# .. _object-containers:
#
# Object containers
# =================
#
#
# Now that we know how to inspect and set the properties of a given
# object we want to configure, we need to know how to get at that object.
# As mentioned in the introduction, there are two kinds of objects:
# primitives and containers. The primitives are usually the things you
# want to configure (the font of a :class:`~matplotlib.text.Text`
# instance, the width of a :class:`~matplotlib.lines.Line2D`) although
# the containers also have some properties as well -- for example the
# :class:`~matplotlib.axes.Axes` :class:`~matplotlib.artist.Artist` is a
# container that contains many of the primitives in your plot, but it
# also has properties like the ``xscale`` to control whether the xaxis
# is 'linear' or 'log'. In this section we'll review where the various
# container objects store the ``Artists`` that you want to get at.
#
# .. _figure-container:
#
# Figure container
# ================
#
# The top level container ``Artist`` is the
# :class:`matplotlib.figure.Figure`, and it contains everything in the
# figure. The background of the figure is a
# :class:`~matplotlib.patches.Rectangle` which is stored in
# :attr:`Figure.patch `. As
# you add subplots (:meth:`~matplotlib.figure.Figure.add_subplot`) and
# axes (:meth:`~matplotlib.figure.Figure.add_axes`) to the figure
# these will be appended to the :attr:`Figure.axes
# `. These are also returned by the
# methods that create them:
#
# .. sourcecode:: ipython
#
# In [156]: fig = plt.figure()
#
# In [157]: ax1 = fig.add_subplot(211)
#
# In [158]: ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3])
#
# In [159]: ax1
# Out[159]:
#
# In [160]: print fig.axes
# [, ]
#
# Because the figure maintains the concept of the "current axes" (see
# :meth:`Figure.gca ` and
# :meth:`Figure.sca `) to support the
# pylab/pyplot state machine, you should not insert or remove axes
# directly from the axes list, but rather use the
# :meth:`~matplotlib.figure.Figure.add_subplot` and
# :meth:`~matplotlib.figure.Figure.add_axes` methods to insert, and the
# :meth:`~matplotlib.figure.Figure.delaxes` method to delete. You are
# free however, to iterate over the list of axes or index into it to get
# access to ``Axes`` instances you want to customize. Here is an
# example which turns all the axes grids on::
#
# for ax in fig.axes:
# ax.grid(True)
#
#
# The figure also has its own text, lines, patches and images, which you
# can use to add primitives directly. The default coordinate system for
# the ``Figure`` will simply be in pixels (which is not usually what you
# want) but you can control this by setting the transform property of
# the ``Artist`` you are adding to the figure.
#
# .. TODO: Is that still true?
#
# More useful is "figure coordinates" where (0, 0) is the bottom-left of
# the figure and (1, 1) is the top-right of the figure which you can
# obtain by setting the ``Artist`` transform to :attr:`fig.transFigure
# `:
import matplotlib.lines as lines
fig = plt.figure()
l1 = lines.Line2D([0, 1], [0, 1], transform=fig.transFigure, figure=fig)
l2 = lines.Line2D([0, 1], [1, 0], transform=fig.transFigure, figure=fig)
fig.lines.extend([l1, l2])
plt.show()
###############################################################################
# Here is a summary of the Artists the figure contains
#
# .. TODO: Add xrefs to this table
#
# ================ ===============================================================
# Figure attribute Description
# ================ ===============================================================
# axes A list of Axes instances (includes Subplot)
# patch The Rectangle background
# images A list of FigureImages patches - useful for raw pixel display
# legends A list of Figure Legend instances (different from Axes.legends)
# lines A list of Figure Line2D instances (rarely used, see Axes.lines)
# patches A list of Figure patches (rarely used, see Axes.patches)
# texts A list Figure Text instances
# ================ ===============================================================
#
# .. _axes-container:
#
# Axes container
# ==============
#
# The :class:`matplotlib.axes.Axes` is the center of the matplotlib
# universe -- it contains the vast majority of all the ``Artists`` used
# in a figure with many helper methods to create and add these
# ``Artists`` to itself, as well as helper methods to access and
# customize the ``Artists`` it contains. Like the
# :class:`~matplotlib.figure.Figure`, it contains a
# :class:`~matplotlib.patches.Patch`
# :attr:`~matplotlib.axes.Axes.patch` which is a
# :class:`~matplotlib.patches.Rectangle` for Cartesian coordinates and a
# :class:`~matplotlib.patches.Circle` for polar coordinates; this patch
# determines the shape, background and border of the plotting region::
#
# ax = fig.add_subplot(111)
# rect = ax.patch # a Rectangle instance
# rect.set_facecolor('green')
#
# When you call a plotting method, e.g., the canonical
# :meth:`~matplotlib.axes.Axes.plot` and pass in arrays or lists of
# values, the method will create a :meth:`matplotlib.lines.Line2D`
# instance, update the line with all the ``Line2D`` properties passed as
# keyword arguments, add the line to the :attr:`Axes.lines
# ` container, and returns it to you:
#
# .. sourcecode:: ipython
#
# In [213]: x, y = np.random.rand(2, 100)
#
# In [214]: line, = ax.plot(x, y, '-', color='blue', linewidth=2)
#
# ``plot`` returns a list of lines because you can pass in multiple x, y
# pairs to plot, and we are unpacking the first element of the length
# one list into the line variable. The line has been added to the
# ``Axes.lines`` list:
#
# .. sourcecode:: ipython
#
# In [229]: print ax.lines
# []
#
# Similarly, methods that create patches, like
# :meth:`~matplotlib.axes.Axes.bar` creates a list of rectangles, will
# add the patches to the :attr:`Axes.patches
# ` list:
#
# .. sourcecode:: ipython
#
# In [233]: n, bins, rectangles = ax.hist(np.random.randn(1000), 50, facecolor='yellow')
#
# In [234]: rectangles
# Out[234]:
#
# In [235]: print len(ax.patches)
#
# You should not add objects directly to the ``Axes.lines`` or
# ``Axes.patches`` lists unless you know exactly what you are doing,
# because the ``Axes`` needs to do a few things when it creates and adds
# an object. It sets the figure and axes property of the ``Artist``, as
# well as the default ``Axes`` transformation (unless a transformation
# is set). It also inspects the data contained in the ``Artist`` to
# update the data structures controlling auto-scaling, so that the view
# limits can be adjusted to contain the plotted data. You can,
# nonetheless, create objects yourself and add them directly to the
# ``Axes`` using helper methods like
# :meth:`~matplotlib.axes.Axes.add_line` and
# :meth:`~matplotlib.axes.Axes.add_patch`. Here is an annotated
# interactive session illustrating what is going on:
#
# .. sourcecode:: ipython
#
# In [261]: fig = plt.figure()
#
# In [262]: ax = fig.add_subplot(111)
#
# # create a rectangle instance
# In [263]: rect = matplotlib.patches.Rectangle( (1,1), width=5, height=12)
#
# # by default the axes instance is None
# In [264]: print rect.get_axes()
# None
#
# # and the transformation instance is set to the "identity transform"
# In [265]: print rect.get_transform()
#
#
# # now we add the Rectangle to the Axes
# In [266]: ax.add_patch(rect)
#
# # and notice that the ax.add_patch method has set the axes
# # instance
# In [267]: print rect.get_axes()
# Axes(0.125,0.1;0.775x0.8)
#
# # and the transformation has been set too
# In [268]: print rect.get_transform()
#
#
# # the default axes transformation is ax.transData
# In [269]: print ax.transData
#
#
# # notice that the xlimits of the Axes have not been changed
# In [270]: print ax.get_xlim()
# (0.0, 1.0)
#
# # but the data limits have been updated to encompass the rectangle
# In [271]: print ax.dataLim.bounds
# (1.0, 1.0, 5.0, 12.0)
#
# # we can manually invoke the auto-scaling machinery
# In [272]: ax.autoscale_view()
#
# # and now the xlim are updated to encompass the rectangle
# In [273]: print ax.get_xlim()
# (1.0, 6.0)
#
# # we have to manually force a figure draw
# In [274]: ax.figure.canvas.draw()
#
#
# There are many, many ``Axes`` helper methods for creating primitive
# ``Artists`` and adding them to their respective containers. The table
# below summarizes a small sampling of them, the kinds of ``Artist`` they
# create, and where they store them
#
# ============================== ==================== =======================
# Helper method Artist Container
# ============================== ==================== =======================
# ax.annotate - text annotations Annotate ax.texts
# ax.bar - bar charts Rectangle ax.patches
# ax.errorbar - error bar plots Line2D and Rectangle ax.lines and ax.patches
# ax.fill - shared area Polygon ax.patches
# ax.hist - histograms Rectangle ax.patches
# ax.imshow - image data AxesImage ax.images
# ax.legend - axes legends Legend ax.legends
# ax.plot - xy plots Line2D ax.lines
# ax.scatter - scatter charts PolygonCollection ax.collections
# ax.text - text Text ax.texts
# ============================== ==================== =======================
#
#
# In addition to all of these ``Artists``, the ``Axes`` contains two
# important ``Artist`` containers: the :class:`~matplotlib.axis.XAxis`
# and :class:`~matplotlib.axis.YAxis`, which handle the drawing of the
# ticks and labels. These are stored as instance variables
# :attr:`~matplotlib.axes.Axes.xaxis` and
# :attr:`~matplotlib.axes.Axes.yaxis`. The ``XAxis`` and ``YAxis``
# containers will be detailed below, but note that the ``Axes`` contains
# many helper methods which forward calls on to the
# :class:`~matplotlib.axis.Axis` instances so you often do not need to
# work with them directly unless you want to. For example, you can set
# the font color of the ``XAxis`` ticklabels using the ``Axes`` helper
# method::
#
# for label in ax.get_xticklabels():
# label.set_color('orange')
#
# Below is a summary of the Artists that the Axes contains
#
# ============== ======================================
# Axes attribute Description
# ============== ======================================
# artists A list of Artist instances
# patch Rectangle instance for Axes background
# collections A list of Collection instances
# images A list of AxesImage
# legends A list of Legend instances
# lines A list of Line2D instances
# patches A list of Patch instances
# texts A list of Text instances
# xaxis matplotlib.axis.XAxis instance
# yaxis matplotlib.axis.YAxis instance
# ============== ======================================
#
# .. _axis-container:
#
# Axis containers
# ===============
#
# The :class:`matplotlib.axis.Axis` instances handle the drawing of the
# tick lines, the grid lines, the tick labels and the axis label. You
# can configure the left and right ticks separately for the y-axis, and
# the upper and lower ticks separately for the x-axis. The ``Axis``
# also stores the data and view intervals used in auto-scaling, panning
# and zooming, as well as the :class:`~matplotlib.ticker.Locator` and
# :class:`~matplotlib.ticker.Formatter` instances which control where
# the ticks are placed and how they are represented as strings.
#
# Each ``Axis`` object contains a :attr:`~matplotlib.axis.Axis.label` attribute
# (this is what :mod:`~matplotlib.pylab` modifies in calls to
# :func:`~matplotlib.pylab.xlabel` and :func:`~matplotlib.pylab.ylabel`) as well
# as a list of major and minor ticks. The ticks are
# :class:`~matplotlib.axis.XTick` and :class:`~matplotlib.axis.YTick` instances,
# which contain the actual line and text primitives that render the ticks and
# ticklabels. Because the ticks are dynamically created as needed (e.g., when
# panning and zooming), you should access the lists of major and minor ticks
# through their accessor methods :meth:`~matplotlib.axis.Axis.get_major_ticks`
# and :meth:`~matplotlib.axis.Axis.get_minor_ticks`. Although the ticks contain
# all the primitives and will be covered below, ``Axis`` instances have accessor
# methods that return the tick lines, tick labels, tick locations etc.:
fig, ax = plt.subplots()
axis = ax.xaxis
axis.get_ticklocs()
###############################################################################
axis.get_ticklabels()
###############################################################################
# note there are twice as many ticklines as labels because by
# default there are tick lines at the top and bottom but only tick
# labels below the xaxis; this can be customized
axis.get_ticklines()
###############################################################################
# by default you get the major ticks back
axis.get_ticklines()
###############################################################################
# but you can also ask for the minor ticks
axis.get_ticklines(minor=True)
# Here is a summary of some of the useful accessor methods of the ``Axis``
# (these have corresponding setters where useful, such as
# set_major_formatter)
#
# ====================== =========================================================
# Accessor method Description
# ====================== =========================================================
# get_scale The scale of the axis, e.g., 'log' or 'linear'
# get_view_interval The interval instance of the axis view limits
# get_data_interval The interval instance of the axis data limits
# get_gridlines A list of grid lines for the Axis
# get_label The axis label - a Text instance
# get_ticklabels A list of Text instances - keyword minor=True|False
# get_ticklines A list of Line2D instances - keyword minor=True|False
# get_ticklocs A list of Tick locations - keyword minor=True|False
# get_major_locator The matplotlib.ticker.Locator instance for major ticks
# get_major_formatter The matplotlib.ticker.Formatter instance for major ticks
# get_minor_locator The matplotlib.ticker.Locator instance for minor ticks
# get_minor_formatter The matplotlib.ticker.Formatter instance for minor ticks
# get_major_ticks A list of Tick instances for major ticks
# get_minor_ticks A list of Tick instances for minor ticks
# grid Turn the grid on or off for the major or minor ticks
# ====================== =========================================================
#
# Here is an example, not recommended for its beauty, which customizes
# the axes and tick properties
# plt.figure creates a matplotlib.figure.Figure instance
fig = plt.figure()
rect = fig.patch # a rectangle instance
rect.set_facecolor('lightgoldenrodyellow')
ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4])
rect = ax1.patch
rect.set_facecolor('lightslategray')
for label in ax1.xaxis.get_ticklabels():
# label is a Text instance
label.set_color('red')
label.set_rotation(45)
label.set_fontsize(16)
for line in ax1.yaxis.get_ticklines():
# line is a Line2D instance
line.set_color('green')
line.set_markersize(25)
line.set_markeredgewidth(3)
plt.show()
###############################################################################
# .. _tick-container:
#
# Tick containers
# ===============
#
# The :class:`matplotlib.axis.Tick` is the final container object in our
# descent from the :class:`~matplotlib.figure.Figure` to the
# :class:`~matplotlib.axes.Axes` to the :class:`~matplotlib.axis.Axis`
# to the :class:`~matplotlib.axis.Tick`. The ``Tick`` contains the tick
# and grid line instances, as well as the label instances for the upper
# and lower ticks. Each of these is accessible directly as an attribute
# of the ``Tick``. In addition, there are boolean variables that determine
# whether the upper labels and ticks are on for the x-axis and whether
# the right labels and ticks are on for the y-axis.
#
# ============== ==========================================================
# Tick attribute Description
# ============== ==========================================================
# tick1line Line2D instance
# tick2line Line2D instance
# gridline Line2D instance
# label1 Text instance
# label2 Text instance
# gridOn boolean which determines whether to draw the gridline
# tick1On boolean which determines whether to draw the 1st tickline
# tick2On boolean which determines whether to draw the 2nd tickline
# label1On boolean which determines whether to draw the 1st tick label
# label2On boolean which determines whether to draw the 2nd tick label
# ============== ==========================================================
#
# Here is an example which sets the formatter for the right side ticks with
# dollar signs and colors them green on the right side of the yaxis
import matplotlib.ticker as ticker
# Fixing random state for reproducibility
np.random.seed(19680801)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(100*np.random.rand(20))
formatter = ticker.FormatStrFormatter('$%1.2f')
ax.yaxis.set_major_formatter(formatter)
for tick in ax.yaxis.get_major_ticks():
tick.label1On = False
tick.label2On = True
tick.label2.set_color('green')
plt.show()
PK#JX`%%%02_intermediate/tight_layout_guide.py"""
==================
Tight Layout guide
==================
How to use tight-layout to fit plots within your figure cleanly.
*tight_layout* automatically adjusts subplot params so that the
subplot(s) fits in to the figure area. This is an experimental
feature and may not work for some cases. It only checks the extents
of ticklabels, axis labels, and titles.
Simple Example
==============
In matplotlib, the location of axes (including subplots) are specified in
normalized figure coordinates. It can happen that your axis labels or
titles (or sometimes even ticklabels) go outside the figure area, and are thus
clipped.
"""
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['savefig.facecolor'] = "0.8"
def example_plot(ax, fontsize=12):
ax.plot([1, 2])
ax.locator_params(nbins=3)
ax.set_xlabel('x-label', fontsize=fontsize)
ax.set_ylabel('y-label', fontsize=fontsize)
ax.set_title('Title', fontsize=fontsize)
plt.close('all')
fig, ax = plt.subplots()
example_plot(ax, fontsize=24)
###############################################################################
# To prevent this, the location of axes needs to be adjusted. For
# subplots, this can be done by adjusting the subplot params
# (:ref:`howto-subplots-adjust`). Matplotlib v1.1 introduces a new
# command :func:`~matplotlib.pyplot.tight_layout` that does this
# automatically for you.
fig, ax = plt.subplots()
example_plot(ax, fontsize=24)
plt.tight_layout()
###############################################################################
# When you have multiple subplots, often you see labels of different
# axes overlapping each other.
plt.close('all')
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
###############################################################################
# :func:`~matplotlib.pyplot.tight_layout` will also adjust spacing between
# subplots to minimize the overlaps.
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
plt.tight_layout()
###############################################################################
# :func:`~matplotlib.pyplot.tight_layout` can take keyword arguments of
# *pad*, *w_pad* and *h_pad*. These control the extra padding around the
# figure border and between subplots. The pads are specified in fraction
# of fontsize.
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
###############################################################################
# :func:`~matplotlib.pyplot.tight_layout` will work even if the sizes of
# subplots are different as far as their grid specification is
# compatible. In the example below, *ax1* and *ax2* are subplots of a 2x2
# grid, while *ax3* is of a 1x2 grid.
plt.close('all')
fig = plt.figure()
ax1 = plt.subplot(221)
ax2 = plt.subplot(223)
ax3 = plt.subplot(122)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
plt.tight_layout()
###############################################################################
# It works with subplots created with
# :func:`~matplotlib.pyplot.subplot2grid`. In general, subplots created
# from the gridspec (:ref:`sphx_glr_tutorials_02_intermediate_gridspec.py`) will work.
plt.close('all')
fig = plt.figure()
ax1 = plt.subplot2grid((3, 3), (0, 0))
ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)
ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
plt.tight_layout()
###############################################################################
# Although not thoroughly tested, it seems to work for subplots with
# aspect != "auto" (e.g., axes with images).
arr = np.arange(100).reshape((10, 10))
plt.close('all')
fig = plt.figure(figsize=(5, 4))
ax = plt.subplot(111)
im = ax.imshow(arr, interpolation="none")
plt.tight_layout()
###############################################################################
# Caveats
# -------
#
# * :func:`~matplotlib.pyplot.tight_layout` only considers ticklabels, axis
# labels, and titles. Thus, other artists may be clipped and also may
# overlap.
#
# * It assumes that the extra space needed for ticklabels, axis labels,
# and titles is independent of original location of axes. This is
# often true, but there are rare cases where it is not.
#
# * pad=0 clips some of the texts by a few pixels. This may be a bug or
# a limitation of the current algorithm and it is not clear why it
# happens. Meanwhile, use of pad at least larger than 0.3 is
# recommended.
#
# Use with GridSpec
# -----------------
#
# GridSpec has its own :func:`~matplotlib.gridspec.GridSpec.tight_layout` method
# (the pyplot api :func:`~matplotlib.pyplot.tight_layout` also works).
import matplotlib.gridspec as gridspec
plt.close('all')
fig = plt.figure()
gs1 = gridspec.GridSpec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])
example_plot(ax1)
example_plot(ax2)
gs1.tight_layout(fig)
###############################################################################
# You may provide an optional *rect* parameter, which specifies the bounding box
# that the subplots will be fit inside. The coordinates must be in normalized
# figure coordinates and the default is (0, 0, 1, 1).
fig = plt.figure()
gs1 = gridspec.GridSpec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])
example_plot(ax1)
example_plot(ax2)
gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])
###############################################################################
# For example, this can be used for a figure with multiple gridspecs.
fig = plt.figure()
gs1 = gridspec.GridSpec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])
example_plot(ax1)
example_plot(ax2)
gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])
gs2 = gridspec.GridSpec(3, 1)
for ss in gs2:
ax = fig.add_subplot(ss)
example_plot(ax)
ax.set_title("")
ax.set_xlabel("")
ax.set_xlabel("x-label", fontsize=12)
gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)
# We may try to match the top and bottom of two grids ::
top = min(gs1.top, gs2.top)
bottom = max(gs1.bottom, gs2.bottom)
gs1.update(top=top, bottom=bottom)
gs2.update(top=top, bottom=bottom)
plt.show()
###############################################################################
# While this should be mostly good enough, adjusting top and bottom
# may require adjustment of hspace also. To update hspace & vspace, we
# call :func:`~matplotlib.gridspec.GridSpec.tight_layout` again with updated
# rect argument. Note that the rect argument specifies the area including the
# ticklabels, etc. Thus, we will increase the bottom (which is 0 for the normal
# case) by the difference between the *bottom* from above and the bottom of each
# gridspec. Same thing for the top.
fig = plt.gcf()
gs1 = gridspec.GridSpec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])
example_plot(ax1)
example_plot(ax2)
gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])
gs2 = gridspec.GridSpec(3, 1)
for ss in gs2:
ax = fig.add_subplot(ss)
example_plot(ax)
ax.set_title("")
ax.set_xlabel("")
ax.set_xlabel("x-label", fontsize=12)
gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)
top = min(gs1.top, gs2.top)
bottom = max(gs1.bottom, gs2.bottom)
gs1.update(top=top, bottom=bottom)
gs2.update(top=top, bottom=bottom)
top = min(gs1.top, gs2.top)
bottom = max(gs1.bottom, gs2.bottom)
gs1.tight_layout(fig, rect=[None, 0 + (bottom-gs1.bottom),
0.5, 1 - (gs1.top-top)])
gs2.tight_layout(fig, rect=[0.5, 0 + (bottom-gs2.bottom),
None, 1 - (gs2.top-top)],
h_pad=0.5)
###############################################################################
# Use with AxesGrid1
# ------------------
#
# While limited, the axes_grid1 toolkit is also supported.
from mpl_toolkits.axes_grid1 import Grid
plt.close('all')
fig = plt.figure()
grid = Grid(fig, rect=111, nrows_ncols=(2, 2),
axes_pad=0.25, label_mode='L',
)
for ax in grid:
example_plot(ax)
ax.title.set_visible(False)
plt.tight_layout()
###############################################################################
# Colorbar
# --------
#
# If you create a colorbar with the :func:`~matplotlib.pyplot.colorbar`
# command, the created colorbar is an instance of Axes, *not* Subplot, so
# tight_layout does not work. With Matplotlib v1.1, you may create a
# colorbar as a subplot using the gridspec.
plt.close('all')
arr = np.arange(100).reshape((10, 10))
fig = plt.figure(figsize=(4, 4))
im = plt.imshow(arr, interpolation="none")
plt.colorbar(im, use_gridspec=True)
plt.tight_layout()
###############################################################################
# Another option is to use AxesGrid1 toolkit to
# explicitly create an axes for colorbar.
from mpl_toolkits.axes_grid1 import make_axes_locatable
plt.close('all')
arr = np.arange(100).reshape((10, 10))
fig = plt.figure(figsize=(4, 4))
im = plt.imshow(arr, interpolation="none")
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", "5%", pad="3%")
plt.colorbar(im, cax=cax)
plt.tight_layout()
PK#JI bpp02_intermediate/gridspec.py"""
==============================================
Customizing Location of Subplot Using GridSpec
==============================================
How to create grid-shaped combinations of axes.
:class:`~matplotlib.gridspec.GridSpec`
specifies the geometry of the grid that a subplot will be
placed in. The number of rows and number of columns of the grid
need to be set. Optionally, the subplot layout parameters
(e.g., left, right, etc.) can be tuned.
:class:`~matplotlib.gridspec.SubplotSpec`
specifies the location of the subplot in the given *GridSpec*.
:func:`~matplotlib.pyplot.subplot2grid`
a helper function that is similar to :func:`~matplotlib.pyplot.subplot`
but uses 0-based indexing and let subplot to occupy multiple cells.
"""
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
###############################################################################
# Basic Example of using subplot2grid
# ===================================
# To use :func:`~matplotlib.pyplot.subplot2grid`, you provide geometry of
# the grid and the location of the subplot in the grid. For a simple
# single-cell subplot
fig = plt.figure()
ax = plt.subplot2grid((2, 2), (0, 0))
# is identical to
fig = plt.figure()
ax = plt.subplot(2, 2, 1)
###############################################################################
# Note that, unlike Matplotlib's subplot, the index starts from 0 in GridSpec.
#
# To create a subplot that spans multiple cells:
fig = plt.figure()
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
###############################################################################
# For example, see the output of the following commands:
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
ax4 = plt.subplot2grid((3, 3), (2, 0))
ax5 = plt.subplot2grid((3, 3), (2, 1))
###############################################################################
# GridSpec and SubplotSpec
# ========================
#
# You can create :class:`~matplotlib.gridspec.GridSpec` explicitly and use
# them to create a subplot.
#
# For example:
fig = plt.figure()
ax = plt.subplot2grid((2, 2), (0, 0))
# is equal to:
fig = plt.figure()
gs = gridspec.GridSpec(2, 2)
ax = plt.subplot(gs[0, 0])
# A GridSpec instance provides array-like (2d or 1d) indexing that
# returns the SubplotSpec instance. For a SubplotSpec that spans multiple
# cells, use slice. ::
ax2 = plt.subplot(gs[1, :-1])
ax3 = plt.subplot(gs[1:, -1])
###############################################################################
# The above example becomes ::
fig = plt.figure()
gs = gridspec.GridSpec(3, 3)
ax1 = plt.subplot(gs[0, :])
ax2 = plt.subplot(gs[1, :-1])
ax3 = plt.subplot(gs[1:, -1])
ax4 = plt.subplot(gs[-1, 0])
ax5 = plt.subplot(gs[-1, -2])
###############################################################################
# Adjust GridSpec layout
# ======================
#
# When a GridSpec is explicitly used, you can adjust the layout
# parameters of subplots that are created from the GridSpec. ::
fig = plt.figure()
gs1 = gridspec.GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
###############################################################################
# This is similar to :func:`~matplotlib.pyplot.subplots_adjust`, but it only
# affects the subplots that are created from the given GridSpec.
#
# For example, see this code and the resulting figure:
fig = plt.figure()
gs1 = gridspec.GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
ax1 = plt.subplot(gs1[:-1, :])
ax2 = plt.subplot(gs1[-1, :-1])
ax3 = plt.subplot(gs1[-1, -1])
fig = plt.figure()
gs2 = gridspec.GridSpec(3, 3)
gs2.update(left=0.55, right=0.98, hspace=0.05)
ax4 = plt.subplot(gs2[:, :-1])
ax5 = plt.subplot(gs2[:-1, -1])
ax6 = plt.subplot(gs2[-1, -1])
###############################################################################
# GridSpec using SubplotSpec
# ==========================
#
# You can create GridSpec from the :class:`~matplotlib.gridspec.SubplotSpec`,
# in which case its layout parameters are set to that of the location of
# the given SubplotSpec.
fig = plt.figure()
gs0 = gridspec.GridSpec(1, 2)
gs00 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[0])
gs01 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[1])
###############################################################################
# A Complex Nested GridSpec using SubplotSpec
# ===========================================
#
# Here's a more sophisticated example of nested GridSpec where we put
# a box around each cell of the outer 4x4 grid, by hiding appropriate
# spines in each of the inner 3x3 grids.
import numpy as np
from itertools import product
def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
return np.sin(i*a)*np.cos(i*b), np.sin(i*c)*np.cos(i*d)
fig = plt.figure(figsize=(8, 8))
# gridspec inside gridspec
outer_grid = gridspec.GridSpec(4, 4, wspace=0.0, hspace=0.0)
for i in range(16):
inner_grid = gridspec.GridSpecFromSubplotSpec(
3, 3, subplot_spec=outer_grid[i], wspace=0.0, hspace=0.0)
a, b = int(i/4)+1, i % 4+1
for j, (c, d) in enumerate(product(range(1, 4), repeat=2)):
ax = plt.Subplot(fig, inner_grid[j])
ax.plot(*squiggle_xy(a, b, c, d))
ax.set_xticks([])
ax.set_yticks([])
fig.add_subplot(ax)
all_axes = fig.get_axes()
# show only the outside spines
for ax in all_axes:
for sp in ax.spines.values():
sp.set_visible(False)
if ax.is_first_row():
ax.spines['top'].set_visible(True)
if ax.is_last_row():
ax.spines['bottom'].set_visible(True)
if ax.is_first_col():
ax.spines['left'].set_visible(True)
if ax.is_last_col():
ax.spines['right'].set_visible(True)
plt.show()
# GridSpec with Varying Cell Sizes
# ================================
#
# By default, GridSpec creates cells of equal sizes. You can adjust
# relative heights and widths of rows and columns. Note that absolute
# values are meaningless, only their relative ratios matter.
fig = plt.figure()
gs = gridspec.GridSpec(2, 2,
width_ratios=[1, 2],
height_ratios=[4, 1]
)
ax1 = plt.subplot(gs[0])
ax2 = plt.subplot(gs[1])
ax3 = plt.subplot(gs[2])
ax4 = plt.subplot(gs[3])
PK#J##03_advanced/path_tutorial.py"""
=============
Path Tutorial
=============
Defining paths in your Matplotlib visualization.
The object underlying all of the :mod:`matplotlib.patch` objects is
the :class:`~matplotlib.path.Path`, which supports the standard set of
moveto, lineto, curveto commands to draw simple and compound outlines
consisting of line segments and splines. The ``Path`` is instantiated
with a (N,2) array of (x,y) vertices, and a N-length array of path
codes. For example to draw the unit rectangle from (0,0) to (1,1), we
could use this code
"""
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
verts = [
(0., 0.), # left, bottom
(0., 1.), # left, top
(1., 1.), # right, top
(1., 0.), # right, bottom
(0., 0.), # ignored
]
codes = [
Path.MOVETO,
Path.LINETO,
Path.LINETO,
Path.LINETO,
Path.CLOSEPOLY,
]
path = Path(verts, codes)
fig = plt.figure()
ax = fig.add_subplot(111)
patch = patches.PathPatch(path, facecolor='orange', lw=2)
ax.add_patch(patch)
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
plt.show()
###############################################################################
# The following path codes are recognized
#
# ============== ================================= ====================================================================================================================
# Code Vertices Description
# ============== ================================= ====================================================================================================================
# ``STOP`` 1 (ignored) A marker for the end of the entire path (currently not required and ignored)
# ``MOVETO`` 1 Pick up the pen and move to the given vertex.
# ``LINETO`` 1 Draw a line from the current position to the given vertex.
# ``CURVE3`` 2 (1 control point, 1 endpoint) Draw a quadratic Bézier curve from the current position, with the given control point, to the given end point.
# ``CURVE4`` 3 (2 control points, 1 endpoint) Draw a cubic Bézier curve from the current position, with the given control points, to the given end point.
# ``CLOSEPOLY`` 1 (point itself is ignored) Draw a line segment to the start point of the current polyline.
# ============== ================================= ====================================================================================================================
#
#
# .. path-curves:
#
#
# Bézier example
# ==============
#
# Some of the path components require multiple vertices to specify them:
# for example CURVE 3 is a `bézier
# `_ curve with one
# control point and one end point, and CURVE4 has three vertices for the
# two control points and the end point. The example below shows a
# CURVE4 Bézier spline -- the bézier curve will be contained in the
# convex hull of the start point, the two control points, and the end
# point
verts = [
(0., 0.), # P0
(0.2, 1.), # P1
(1., 0.8), # P2
(0.8, 0.), # P3
]
codes = [
Path.MOVETO,
Path.CURVE4,
Path.CURVE4,
Path.CURVE4,
]
path = Path(verts, codes)
fig = plt.figure()
ax = fig.add_subplot(111)
patch = patches.PathPatch(path, facecolor='none', lw=2)
ax.add_patch(patch)
xs, ys = zip(*verts)
ax.plot(xs, ys, 'x--', lw=2, color='black', ms=10)
ax.text(-0.05, -0.05, 'P0')
ax.text(0.15, 1.05, 'P1')
ax.text(1.05, 0.85, 'P2')
ax.text(0.85, -0.05, 'P3')
ax.set_xlim(-0.1, 1.1)
ax.set_ylim(-0.1, 1.1)
plt.show()
###############################################################################
# .. compound_paths:
#
# Compound paths
# ==============
#
# All of the simple patch primitives in matplotlib, Rectangle, Circle,
# Polygon, etc, are implemented with simple path. Plotting functions
# like :meth:`~matplotlib.axes.Axes.hist` and
# :meth:`~matplotlib.axes.Axes.bar`, which create a number of
# primitives, e.g., a bunch of Rectangles, can usually be implemented more
# efficiently using a compound path. The reason ``bar`` creates a list
# of rectangles and not a compound path is largely historical: the
# :class:`~matplotlib.path.Path` code is comparatively new and ``bar``
# predates it. While we could change it now, it would break old code,
# so here we will cover how to create compound paths, replacing the
# functionality in bar, in case you need to do so in your own code for
# efficiency reasons, e.g., you are creating an animated bar plot.
#
# We will make the histogram chart by creating a series of rectangles
# for each histogram bar: the rectangle width is the bin width and the
# rectangle height is the number of datapoints in that bin. First we'll
# create some random normally distributed data and compute the
# histogram. Because numpy returns the bin edges and not centers, the
# length of ``bins`` is 1 greater than the length of ``n`` in the
# example below::
#
# # histogram our data with numpy
# data = np.random.randn(1000)
# n, bins = np.histogram(data, 100)
#
# We'll now extract the corners of the rectangles. Each of the
# ``left``, ``bottom``, etc, arrays below is ``len(n)``, where ``n`` is
# the array of counts for each histogram bar::
#
# # get the corners of the rectangles for the histogram
# left = np.array(bins[:-1])
# right = np.array(bins[1:])
# bottom = np.zeros(len(left))
# top = bottom + n
#
# Now we have to construct our compound path, which will consist of a
# series of ``MOVETO``, ``LINETO`` and ``CLOSEPOLY`` for each rectangle.
# For each rectangle, we need 5 vertices: 1 for the ``MOVETO``, 3 for
# the ``LINETO``, and 1 for the ``CLOSEPOLY``. As indicated in the
# table above, the vertex for the closepoly is ignored but we still need
# it to keep the codes aligned with the vertices::
#
# nverts = nrects*(1+3+1)
# verts = np.zeros((nverts, 2))
# codes = np.ones(nverts, int) * path.Path.LINETO
# codes[0::5] = path.Path.MOVETO
# codes[4::5] = path.Path.CLOSEPOLY
# verts[0::5,0] = left
# verts[0::5,1] = bottom
# verts[1::5,0] = left
# verts[1::5,1] = top
# verts[2::5,0] = right
# verts[2::5,1] = top
# verts[3::5,0] = right
# verts[3::5,1] = bottom
#
# All that remains is to create the path, attach it to a
# :class:`~matplotlib.patch.PathPatch`, and add it to our axes::
#
# barpath = path.Path(verts, codes)
# patch = patches.PathPatch(barpath, facecolor='green',
# edgecolor='yellow', alpha=0.5)
# ax.add_patch(patch)
import numpy as np
import matplotlib.patches as patches
import matplotlib.path as path
fig = plt.figure()
ax = fig.add_subplot(111)
# Fixing random state for reproducibility
np.random.seed(19680801)
# histogram our data with numpy
data = np.random.randn(1000)
n, bins = np.histogram(data, 100)
# get the corners of the rectangles for the histogram
left = np.array(bins[:-1])
right = np.array(bins[1:])
bottom = np.zeros(len(left))
top = bottom + n
nrects = len(left)
nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
codes = np.ones(nverts, int) * path.Path.LINETO
codes[0::5] = path.Path.MOVETO
codes[4::5] = path.Path.CLOSEPOLY
verts[0::5, 0] = left
verts[0::5, 1] = bottom
verts[1::5, 0] = left
verts[1::5, 1] = top
verts[2::5, 0] = right
verts[2::5, 1] = top
verts[3::5, 0] = right
verts[3::5, 1] = bottom
barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green',
edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)
ax.set_xlim(left[0], right[-1])
ax.set_ylim(bottom.min(), top.max())
plt.show()
PK#J/@K@K"03_advanced/transforms_tutorial.py"""
========================
Transformations Tutorial
========================
Transforming visuals in Matplotlib.
Like any graphics packages, matplotlib is built on top of a
transformation framework to easily move between coordinate systems,
the userland `data` coordinate system, the `axes` coordinate system,
the `figure` coordinate system, and the `display` coordinate system.
In 95% of your plotting, you won't need to think about this, as it
happens under the hood, but as you push the limits of custom figure
generation, it helps to have an understanding of these objects so you
can reuse the existing transformations matplotlib makes available to
you, or create your own (see :mod:`matplotlib.transforms`). The table
below summarizes the existing coordinate systems, the transformation
object you should use to work in that coordinate system, and the
description of that system. In the `Transformation Object` column,
``ax`` is a :class:`~matplotlib.axes.Axes` instance, and ``fig`` is a
:class:`~matplotlib.figure.Figure` instance.
========== ===================== ====================================================================================
Coordinate Transformation Object Description
========== ===================== ====================================================================================
`data` ``ax.transData`` The userland data coordinate system, controlled by the xlim and ylim
`axes` ``ax.transAxes`` The coordinate system of the :class:`~matplotlib.axes.Axes`; (0, 0) is
bottom left of the axes, and (1, 1) is top right of the axes.
`figure` ``fig.transFigure`` The coordinate system of the :class:`~matplotlib.figure.Figure`; (0, 0)
is bottom left of the figure, and (1, 1) is top right of the figure.
`display` `None` This is the pixel coordinate system of the display; (0, 0) is the bottom
left of the display, and (width, height) is the top right of the display in pixels.
Alternatively, the identity transform
(:class:`matplotlib.transforms.IdentityTransform()`) may be used instead of None.
========== ===================== ====================================================================================
All of the transformation objects in the table above take inputs in
their coordinate system, and transform the input to the `display`
coordinate system. That is why the `display` coordinate system has
`None` for the `Transformation Object` column -- it already is in
display coordinates. The transformations also know how to invert
themselves, to go from `display` back to the native coordinate system.
This is particularly useful when processing events from the user
interface, which typically occur in display space, and you want to
know where the mouse click or key-press occurred in your data
coordinate system.
.. _data-coords:
Data coordinates
================
Let's start with the most commonly used coordinate, the `data`
coordinate system. Whenever you add data to the axes, matplotlib
updates the datalimits, most commonly updated with the
:meth:`~matplotlib.axes.Axes.set_xlim` and
:meth:`~matplotlib.axes.Axes.set_ylim` methods. For example, in the
figure below, the data limits stretch from 0 to 10 on the x-axis, and
-1 to 1 on the y-axis.
"""
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 10, 0.005)
y = np.exp(-x/2.) * np.sin(2*np.pi*x)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)
plt.show()
###############################################################################
# You can use the ``ax.transData`` instance to transform from your
# `data` to your `display` coordinate system, either a single point or a
# sequence of points as shown below:
#
# .. sourcecode:: ipython
#
# In [14]: type(ax.transData)
# Out[14]:
#
# In [15]: ax.transData.transform((5, 0))
# Out[15]: array([ 335.175, 247. ])
#
# In [16]: ax.transData.transform([(5, 0), (1, 2)])
# Out[16]:
# array([[ 335.175, 247. ],
# [ 132.435, 642.2 ]])
#
# You can use the :meth:`~matplotlib.transforms.Transform.inverted`
# method to create a transform which will take you from display to data
# coordinates:
#
# .. sourcecode:: ipython
#
# In [41]: inv = ax.transData.inverted()
#
# In [42]: type(inv)
# Out[42]:
#
# In [43]: inv.transform((335.175, 247.))
# Out[43]: array([ 5., 0.])
#
# If your are typing along with this tutorial, the exact values of the
# display coordinates may differ if you have a different window size or
# dpi setting. Likewise, in the figure below, the display labeled
# points are probably not the same as in the ipython session because the
# documentation figure size defaults are different.
x = np.arange(0, 10, 0.005)
y = np.exp(-x/2.) * np.sin(2*np.pi*x)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)
xdata, ydata = 5, 0
xdisplay, ydisplay = ax.transData.transform_point((xdata, ydata))
bbox = dict(boxstyle="round", fc="0.8")
arrowprops = dict(
arrowstyle="->",
connectionstyle="angle,angleA=0,angleB=90,rad=10")
offset = 72
ax.annotate('data = (%.1f, %.1f)' % (xdata, ydata),
(xdata, ydata), xytext=(-2*offset, offset), textcoords='offset points',
bbox=bbox, arrowprops=arrowprops)
disp = ax.annotate('display = (%.1f, %.1f)' % (xdisplay, ydisplay),
(xdisplay, ydisplay), xytext=(0.5*offset, -offset),
xycoords='figure pixels',
textcoords='offset points',
bbox=bbox, arrowprops=arrowprops)
plt.show()
###############################################################################
# .. note::
#
# If you run the source code in the example above in a GUI backend,
# you may also find that the two arrows for the `data` and `display`
# annotations do not point to exactly the same point. This is because
# the display point was computed before the figure was displayed, and
# the GUI backend may slightly resize the figure when it is created.
# The effect is more pronounced if you resize the figure yourself.
# This is one good reason why you rarely want to work in display
# space, but you can connect to the ``'on_draw'``
# :class:`~matplotlib.backend_bases.Event` to update figure
# coordinates on figure draws; see :ref:`event-handling-tutorial`.
#
# When you change the x or y limits of your axes, the data limits are
# updated so the transformation yields a new display point. Note that
# when we just change the ylim, only the y-display coordinate is
# altered, and when we change the xlim too, both are altered. More on
# this later when we talk about the
# :class:`~matplotlib.transforms.Bbox`.
#
# .. sourcecode:: ipython
#
# In [54]: ax.transData.transform((5, 0))
# Out[54]: array([ 335.175, 247. ])
#
# In [55]: ax.set_ylim(-1, 2)
# Out[55]: (-1, 2)
#
# In [56]: ax.transData.transform((5, 0))
# Out[56]: array([ 335.175 , 181.13333333])
#
# In [57]: ax.set_xlim(10, 20)
# Out[57]: (10, 20)
#
# In [58]: ax.transData.transform((5, 0))
# Out[58]: array([-171.675 , 181.13333333])
#
#
# .. _axes-coords:
#
# Axes coordinates
# ================
#
# After the `data` coordinate system, `axes` is probably the second most
# useful coordinate system. Here the point (0, 0) is the bottom left of
# your axes or subplot, (0.5, 0.5) is the center, and (1.0, 1.0) is the
# top right. You can also refer to points outside the range, so (-0.1,
# 1.1) is to the left and above your axes. This coordinate system is
# extremely useful when placing text in your axes, because you often
# want a text bubble in a fixed, location, e.g., the upper left of the axes
# pane, and have that location remain fixed when you pan or zoom. Here
# is a simple example that creates four panels and labels them 'A', 'B',
# 'C', 'D' as you often see in journals.
fig = plt.figure()
for i, label in enumerate(('A', 'B', 'C', 'D')):
ax = fig.add_subplot(2, 2, i+1)
ax.text(0.05, 0.95, label, transform=ax.transAxes,
fontsize=16, fontweight='bold', va='top')
plt.show()
###############################################################################
# You can also make lines or patches in the axes coordinate system, but
# this is less useful in my experience than using ``ax.transAxes`` for
# placing text. Nonetheless, here is a silly example which plots some
# random dots in `data` space, and overlays a semi-transparent
# :class:`~matplotlib.patches.Circle` centered in the middle of the axes
# with a radius one quarter of the axes -- if your axes does not
# preserve aspect ratio (see :meth:`~matplotlib.axes.Axes.set_aspect`),
# this will look like an ellipse. Use the pan/zoom tool to move around,
# or manually change the data xlim and ylim, and you will see the data
# move, but the circle will remain fixed because it is not in `data`
# coordinates and will always remain at the center of the axes.
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.add_subplot(111)
x, y = 10*np.random.rand(2, 1000)
ax.plot(x, y, 'go') # plot some data in data coordinates
circ = patches.Circle((0.5, 0.5), 0.25, transform=ax.transAxes,
facecolor='yellow', alpha=0.5)
ax.add_patch(circ)
plt.show()
###############################################################################
# .. blended_transformations:
#
# Blended transformations
# =======================
#
# Drawing in `blended` coordinate spaces which mix `axes` with `data`
# coordinates is extremely useful, for example to create a horizontal
# span which highlights some region of the y-data but spans across the
# x-axis regardless of the data limits, pan or zoom level, etc. In fact
# these blended lines and spans are so useful, we have built in
# functions to make them easy to plot (see
# :meth:`~matplotlib.axes.Axes.axhline`,
# :meth:`~matplotlib.axes.Axes.axvline`,
# :meth:`~matplotlib.axes.Axes.axhspan`,
# :meth:`~matplotlib.axes.Axes.axvspan`) but for didactic purposes we
# will implement the horizontal span here using a blended
# transformation. This trick only works for separable transformations,
# like you see in normal Cartesian coordinate systems, but not on
# inseparable transformations like the
# :class:`~matplotlib.projections.polar.PolarAxes.PolarTransform`.
import matplotlib.transforms as transforms
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.random.randn(1000)
ax.hist(x, 30)
ax.set_title(r'$\sigma=1 \/ \dots \/ \sigma=2$', fontsize=16)
# the x coords of this transformation are data, and the
# y coord are axes
trans = transforms.blended_transform_factory(
ax.transData, ax.transAxes)
# highlight the 1..2 stddev region with a span.
# We want x to be in data coordinates and y to
# span from 0..1 in axes coords
rect = patches.Rectangle((1, 0), width=1, height=1,
transform=trans, color='yellow',
alpha=0.5)
ax.add_patch(rect)
plt.show()
###############################################################################
# .. note::
#
# The blended transformations where x is in data coords and y in axes
# coordinates is so useful that we have helper methods to return the
# versions mpl uses internally for drawing ticks, ticklabels, etc.
# The methods are :meth:`matplotlib.axes.Axes.get_xaxis_transform` and
# :meth:`matplotlib.axes.Axes.get_yaxis_transform`. So in the example
# above, the call to
# :meth:`~matplotlib.transforms.blended_transform_factory` can be
# replaced by ``get_xaxis_transform``::
#
# trans = ax.get_xaxis_transform()
#
# .. offset-transforms-shadow:
#
# Using offset transforms to create a shadow effect
# =================================================
#
# One use of transformations is to create a new transformation that is
# offset from another transformation, e.g., to place one object shifted a
# bit relative to another object. Typically you want the shift to be in
# some physical dimension, like points or inches rather than in data
# coordinates, so that the shift effect is constant at different zoom
# levels and dpi settings.
#
# One use for an offset is to create a shadow effect, where you draw one
# object identical to the first just to the right of it, and just below
# it, adjusting the zorder to make sure the shadow is drawn first and
# then the object it is shadowing above it. The transforms module has a
# helper transformation
# :class:`~matplotlib.transforms.ScaledTranslation`. It is
# instantiated with::
#
# trans = ScaledTranslation(xt, yt, scale_trans)
#
# where `xt` and `yt` are the translation offsets, and `scale_trans` is
# a transformation which scales `xt` and `yt` at transformation time
# before applying the offsets. A typical use case is to use the figure
# ``fig.dpi_scale_trans`` transformation for the `scale_trans` argument,
# to first scale `xt` and `yt` specified in points to `display` space
# before doing the final offset. The dpi and inches offset is a
# common-enough use case that we have a special helper function to
# create it in :func:`matplotlib.transforms.offset_copy`, which returns
# a new transform with an added offset. But in the example below, we'll
# create the offset transform ourselves. Note the use of the plus
# operator in::
#
# offset = transforms.ScaledTranslation(dx, dy,
# fig.dpi_scale_trans)
# shadow_transform = ax.transData + offset
#
# showing that can chain transformations using the addition operator.
# This code says: first apply the data transformation ``ax.transData``
# and then translate the data by `dx` and `dy` points. In typography,
# a`point `_ is
# 1/72 inches, and by specifying your offsets in points, your figure
# will look the same regardless of the dpi resolution it is saved in.
fig = plt.figure()
ax = fig.add_subplot(111)
# make a simple sine wave
x = np.arange(0., 2., 0.01)
y = np.sin(2*np.pi*x)
line, = ax.plot(x, y, lw=3, color='blue')
# shift the object over 2 points, and down 2 points
dx, dy = 2/72., -2/72.
offset = transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
shadow_transform = ax.transData + offset
# now plot the same data with our offset transform;
# use the zorder to make sure we are below the line
ax.plot(x, y, lw=3, color='gray',
transform=shadow_transform,
zorder=0.5*line.get_zorder())
ax.set_title('creating a shadow effect with an offset transform')
plt.show()
###############################################################################
# .. transformation-pipeline:
#
# The transformation pipeline
# ===========================
#
# The ``ax.transData`` transform we have been working with in this
# tutorial is a composite of three different transformations that
# comprise the transformation pipeline from `data` -> `display`
# coordinates. Michael Droettboom implemented the transformations
# framework, taking care to provide a clean API that segregated the
# nonlinear projections and scales that happen in polar and logarithmic
# plots, from the linear affine transformations that happen when you pan
# and zoom. There is an efficiency here, because you can pan and zoom
# in your axes which affects the affine transformation, but you may not
# need to compute the potentially expensive nonlinear scales or
# projections on simple navigation events. It is also possible to
# multiply affine transformation matrices together, and then apply them
# to coordinates in one step. This is not true of all possible
# transformations.
#
#
# Here is how the ``ax.transData`` instance is defined in the basic
# separable axis :class:`~matplotlib.axes.Axes` class::
#
# self.transData = self.transScale + (self.transLimits + self.transAxes)
#
# We've been introduced to the ``transAxes`` instance above in
# :ref:`axes-coords`, which maps the (0, 0), (1, 1) corners of the
# axes or subplot bounding box to `display` space, so let's look at
# these other two pieces.
#
# ``self.transLimits`` is the transformation that takes you from
# ``data`` to ``axes`` coordinates; i.e., it maps your view xlim and ylim
# to the unit space of the axes (and ``transAxes`` then takes that unit
# space to display space). We can see this in action here
#
# .. sourcecode:: ipython
#
# In [80]: ax = subplot(111)
#
# In [81]: ax.set_xlim(0, 10)
# Out[81]: (0, 10)
#
# In [82]: ax.set_ylim(-1, 1)
# Out[82]: (-1, 1)
#
# In [84]: ax.transLimits.transform((0, -1))
# Out[84]: array([ 0., 0.])
#
# In [85]: ax.transLimits.transform((10, -1))
# Out[85]: array([ 1., 0.])
#
# In [86]: ax.transLimits.transform((10, 1))
# Out[86]: array([ 1., 1.])
#
# In [87]: ax.transLimits.transform((5, 0))
# Out[87]: array([ 0.5, 0.5])
#
# and we can use this same inverted transformation to go from the unit
# `axes` coordinates back to `data` coordinates.
#
# .. sourcecode:: ipython
#
# In [90]: inv.transform((0.25, 0.25))
# Out[90]: array([ 2.5, -0.5])
#
# The final piece is the ``self.transScale`` attribute, which is
# responsible for the optional non-linear scaling of the data, e.g., for
# logarithmic axes. When an Axes is initially setup, this is just set to
# the identity transform, since the basic matplotlib axes has linear
# scale, but when you call a logarithmic scaling function like
# :meth:`~matplotlib.axes.Axes.semilogx` or explicitly set the scale to
# logarithmic with :meth:`~matplotlib.axes.Axes.set_xscale`, then the
# ``ax.transScale`` attribute is set to handle the nonlinear projection.
# The scales transforms are properties of the respective ``xaxis`` and
# ``yaxis`` :class:`~matplotlib.axis.Axis` instances. For example, when
# you call ``ax.set_xscale('log')``, the xaxis updates its scale to a
# :class:`matplotlib.scale.LogScale` instance.
#
# For non-separable axes the PolarAxes, there is one more piece to
# consider, the projection transformation. The ``transData``
# :class:`matplotlib.projections.polar.PolarAxes` is similar to that for
# the typical separable matplotlib Axes, with one additional piece
# ``transProjection``::
#
# self.transData = self.transScale + self.transProjection + \
# (self.transProjectionAffine + self.transAxes)
#
# ``transProjection`` handles the projection from the space,
# e.g., latitude and longitude for map data, or radius and theta for polar
# data, to a separable Cartesian coordinate system. There are several
# projection examples in the ``matplotlib.projections`` package, and the
# best way to learn more is to open the source for those packages and
# see how to make your own, since matplotlib supports extensible axes
# and projections. Michael Droettboom has provided a nice tutorial
# example of creating a hammer projection axes; see
# :ref:`sphx_glr_gallery_api_custom_projection_example.py`.
PK#J)ucc 03_advanced/patheffects_guide.py"""
==================
Path effects guide
==================
Defining paths that objects follow on a canvas.
.. py:module:: matplotlib.patheffects
Matplotlib's :mod:`~matplotlib.patheffects` module provides functionality to
apply a multiple draw stage to any Artist which can be rendered via a
:class:`~matplotlib.path.Path`.
Artists which can have a path effect applied to them include :class:`~matplotlib.patches.Patch`,
:class:`~matplotlib.lines.Line2D`, :class:`~matplotlib.collections.Collection` and even
:class:`~matplotlib.text.Text`. Each artist's path effects can be controlled via the
``set_path_effects`` method (:class:`~matplotlib.artist.Artist.set_path_effects`), which takes
an iterable of :class:`AbstractPathEffect` instances.
The simplest path effect is the :class:`Normal` effect, which simply
draws the artist without any effect:
"""
import matplotlib.pyplot as plt
import matplotlib.patheffects as path_effects
fig = plt.figure(figsize=(5, 1.5))
text = fig.text(0.5, 0.5, 'Hello path effects world!\nThis is the normal '
'path effect.\nPretty dull, huh?',
ha='center', va='center', size=20)
text.set_path_effects([path_effects.Normal()])
plt.show()
###############################################################################
# Whilst the plot doesn't look any different to what you would expect without any path
# effects, the drawing of the text now been changed to use the path effects
# framework, opening up the possibilities for more interesting examples.
#
# Adding a shadow
# ---------------
#
# A far more interesting path effect than :class:`Normal` is the
# drop-shadow, which we can apply to any of our path based artists. The classes
# :class:`SimplePatchShadow` and
# :class:`SimpleLineShadow` do precisely this by drawing either a filled
# patch or a line patch below the original artist:
import matplotlib.patheffects as path_effects
text = plt.text(0.5, 0.5, 'Hello path effects world!',
path_effects=[path_effects.withSimplePatchShadow()])
plt.plot([0, 3, 2, 5], linewidth=5, color='blue',
path_effects=[path_effects.SimpleLineShadow(),
path_effects.Normal()])
plt.show()
###############################################################################
# Notice the two approaches to setting the path effects in this example. The
# first uses the ``with*`` classes to include the desired functionality automatically
# followed with the "normal" effect, whereas the latter explicitly defines the two path
# effects to draw.
#
# Making an artist stand out
# --------------------------
#
# One nice way of making artists visually stand out is to draw an outline in a bold
# color below the actual artist. The :class:`Stroke` path effect
# makes this a relatively simple task:
fig = plt.figure(figsize=(7, 1))
text = fig.text(0.5, 0.5, 'This text stands out because of\n'
'its black border.', color='white',
ha='center', va='center', size=30)
text.set_path_effects([path_effects.Stroke(linewidth=3, foreground='black'),
path_effects.Normal()])
plt.show()
###############################################################################
# It is important to note that this effect only works because we have drawn the text
# path twice; once with a thick black line, and then once with the original text
# path on top.
#
# You may have noticed that the keywords to :class:`Stroke` and
# :class:`SimplePatchShadow` and :class:`SimpleLineShadow` are not the usual Artist
# keywords (such as ``facecolor`` and ``edgecolor`` etc.). This is because with these
# path effects we are operating at lower level of matplotlib. In fact, the keywords
# which are accepted are those for a :class:`matplotlib.backend_bases.GraphicsContextBase`
# instance, which have been designed for making it easy to create new backends - and not
# for its user interface.
#
#
# Greater control of the path effect artist
# -----------------------------------------
#
# As already mentioned, some of the path effects operate at a lower level than most users
# will be used to, meaning that setting keywords such as ``facecolor`` and ``edgecolor``
# raise an AttributeError. Luckily there is a generic :class:`PathPatchEffect` path effect
# which creates a :class:`~matplotlib.patches.PathPatch` class with the original path.
# The keywords to this effect are identical to those of :class:`~matplotlib.patches.PathPatch`:
fig = plt.figure(figsize=(8, 1))
t = fig.text(0.02, 0.5, 'Hatch shadow', fontsize=75, weight=1000, va='center')
t.set_path_effects([path_effects.PathPatchEffect(offset=(4, -4), hatch='xxxx',
facecolor='gray'),
path_effects.PathPatchEffect(edgecolor='white', linewidth=1.1,
facecolor='black')])
plt.show()
###############################################################################
# ..
# Headings for future consideration:
#
# Implementing a custom path effect
# ---------------------------------
#
# What is going on under the hood
# --------------------------------
PK#JG88colors/colors.py"""
*****************
Specifying Colors
*****************
In almost all places in matplotlib where a color can be specified by the user
it can be provided as:
* an RGB or RGBA tuple of float values in ``[0, 1]``
(e.g., ``(0.1, 0.2, 0.5)`` or ``(0.1, 0.2, 0.5, 0.3)``)
* a hex RGB or RGBA string (e.g., ``'#0F0F0F'`` or ``'#0F0F0F0F'``)
* a string representation of a float value in ``[0, 1]``
inclusive for gray level (e.g., ``'0.5'``)
* one of ``{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}``
* a X11/CSS4 color name
* a name from the `xkcd color survey `__
prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``)
* one of ``{'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'}``
* one of ``{'tab:blue', 'tab:orange', 'tab:green',
'tab:red', 'tab:purple', 'tab:brown', 'tab:pink',
'tab:gray', 'tab:olive', 'tab:cyan'}`` which are the Tableau Colors from the
'T10' categorical palette (which is the default color cycle).
All string specifications of color are case-insensitive.
``'CN'`` color selection
------------------------
Color can be specified by a string matching the regex ``C[0-9]``.
This can be passed any place that a color is currently accepted and
can be used as a 'single character color' in format-string to
`matplotlib.Axes.plot`.
The single digit is the index into the default property cycle
(``matplotlib.rcParams['axes.prop_cycle']``). If the property cycle does not
include ``'color'`` then black is returned. The color is evaluated when the
artist is created. For example,
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
th = np.linspace(0, 2*np.pi, 128)
def demo(sty):
mpl.style.use(sty)
fig, ax = plt.subplots(figsize=(3, 3))
ax.set_title('style: {!r}'.format(sty), color='C0')
ax.plot(th, np.cos(th), 'C1', label='C1')
ax.plot(th, np.sin(th), 'C2', label='C2')
ax.legend()
demo('default')
demo('seaborn')
###############################################################################
# will use the first color for the title and then plot using the second
# and third colors of each style's ``mpl.rcParams['axes.prop_cycle']``.
#
#
# xkcd v X11/CSS4
# ---------------
#
# The xkcd colors are derived from a user survey conducted by the
# webcomic xkcd. `Details of the survey are available on the xkcd blog
# `__.
#
# Out of 148 colors in the CSS color list, there are 95 name collisions
# between the X11/CSS4 names and the xkcd names, all but 3 of which have
# different hex values. For example ``'blue'`` maps to ``'#0000FF'``
# where as ``'xkcd:blue'`` maps to ``'#0343DF'``. Due to these name
# collisions all of the xkcd colors have ``'xkcd:'`` prefixed. As noted in
# the blog post, while it might be interesting to re-define the X11/CSS4 names
# based on such a survey, we do not do so unilaterally.
#
# The name collisions are shown in the table below; the color names
# where the hex values agree are shown in bold.
import matplotlib._color_data as mcd
import matplotlib.patches as mpatch
overlap = {name for name in mcd.CSS4_COLORS
if "xkcd:" + name in mcd.XKCD_COLORS}
fig = plt.figure(figsize=[4.8, 16])
ax = fig.add_axes([0, 0, 1, 1])
for j, n in enumerate(sorted(overlap, reverse=True)):
weight = None
cn = mcd.CSS4_COLORS[n]
xkcd = mcd.XKCD_COLORS["xkcd:" + n].upper()
if cn == xkcd:
weight = 'bold'
r1 = mpatch.Rectangle((0, j), 1, 1, color=cn)
r2 = mpatch.Rectangle((1, j), 1, 1, color=xkcd)
txt = ax.text(2, j+.5, ' ' + n, va='center', fontsize=10,
weight=weight)
ax.add_patch(r1)
ax.add_patch(r2)
ax.axhline(j, color='k')
ax.text(.5, j + 1.5, 'X11', ha='center', va='center')
ax.text(1.5, j + 1.5, 'xkcd', ha='center', va='center')
ax.set_xlim(0, 3)
ax.set_ylim(0, j + 2)
ax.axis('off')
PK#J
O B Bcolors/colormaps.py"""
***********************
Colormaps in Matplotlib
***********************
How (and why) to choose a particular colormap.
Overview
========
The idea behind choosing a good colormap is to find a good representation in 3D
colorspace for your data set. The best colormap for any given data set depends
on many things including:
- Whether representing form or metric data ([Ware]_)
- Your knowledge of the data set (*e.g.*, is there a critical value
from which the other values deviate?)
- If there is an intuitive color scheme for the parameter you are plotting
- If there is a standard in the field the audience may be expecting
For many applications, a perceptually uniform colormap is the best
choice --- one in which equal steps in data are perceived as equal
steps in the color space. Researchers have found that the human brain
perceives changes in the lightness parameter as changes in the data
much better than, for example, changes in hue. Therefore, colormaps
which have monotonically increasing lightness through the colormap
will be better interpreted by the viewer. A wonderful example of
perceptually uniform colormaps is [colorcet]_.
Color can be represented in 3D space in various ways. One way to represent color
is using CIELAB. In CIELAB, color space is represented by lightness,
:math:`L^*`; red-green, :math:`a^*`; and yellow-blue, :math:`b^*`. The lightness
parameter :math:`L^*` can then be used to learn more about how the matplotlib
colormaps will be perceived by viewers.
An excellent starting resource for learning about human perception of colormaps
is from [IBM]_.
Classes of colormaps
====================
Colormaps are often split into several categories based on their function (see,
*e.g.*, [Moreland]_):
1. Sequential: change in lightness and often saturation of color
incrementally, often using a single hue; should be used for
representing information that has ordering.
2. Diverging: change in lightness and possibly saturation of two
different colors that meet in the middle at an unsaturated color;
should be used when the information being plotted has a critical
middle value, such as topography or when the data deviates around
zero.
3. Qualitative: often are miscellaneous colors; should be used to
represent information which does not have ordering or
relationships.
"""
# sphinx_gallery_thumbnail_number = 2
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from colorspacious import cspace_converter
from collections import OrderedDict
cmaps = OrderedDict()
###############################################################################
# Sequential
# ----------
#
# For the Sequential plots, the lightness value increases monotonically through
# the colormaps. This is good. Some of the :math:`L^*` values in the colormaps
# span from 0 to 100 (binary and the other grayscale), and others start around
# :math:`L^*=20`. Those that have a smaller range of :math:`L^*` will accordingly
# have a smaller perceptual range. Note also that the :math:`L^*` function varies
# amongst the colormaps: some are approximately linear in :math:`L^*` and others
# are more curved.
cmaps['Perceptually Uniform Sequential'] = ['viridis', 'plasma',
'inferno', 'magma']
cmaps['Sequential'] = [
'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']
###############################################################################
# Sequential2
# -----------
#
# Many of the :math:`L^*` values from the Sequential2 plots are monotonically
# increasing, but some (autumn, cool, spring, and winter) plateau or even go both
# up and down in :math:`L^*` space. Others (afmhot, copper, gist_heat, and hot)
# have kinks in the :math:`L^*` functions. Data that is being represented in a
# region of the colormap that is at a plateau or kink will lead to a perception of
# banding of the data in those values in the colormap (see [mycarta-banding]_ for
# an excellent example of this).
cmaps['Sequential (2)'] = [
'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
'hot', 'afmhot', 'gist_heat', 'copper']
###############################################################################
# Diverging
# ---------
#
# For the Diverging maps, we want to have monotonically increasing :math:`L^*`
# values up to a maximum, which should be close to :math:`L^*=100`, followed by
# monotonically decreasing :math:`L^*` values. We are looking for approximately
# equal minimum :math:`L^*` values at opposite ends of the colormap. By these
# measures, BrBG and RdBu are good options. coolwarm is a good option, but it
# doesn't span a wide range of :math:`L^*` values (see grayscale section below).
cmaps['Diverging'] = [
'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']
###############################################################################
# Qualitative
# -----------
#
# Qualitative colormaps are not aimed at being perceptual maps, but looking at the
# lightness parameter can verify that for us. The :math:`L^*` values move all over
# the place throughout the colormap, and are clearly not monotonically increasing.
# These would not be good options for use as perceptual colormaps.
cmaps['Qualitative'] = ['Pastel1', 'Pastel2', 'Paired', 'Accent',
'Dark2', 'Set1', 'Set2', 'Set3',
'tab10', 'tab20', 'tab20b', 'tab20c']
###############################################################################
# Miscellaneous
# -------------
#
# Some of the miscellaneous colormaps have particular uses for which
# they have been created. For example, gist_earth, ocean, and terrain
# all seem to be created for plotting topography (green/brown) and water
# depths (blue) together. We would expect to see a divergence in these
# colormaps, then, but multiple kinks may not be ideal, such as in
# gist_earth and terrain. CMRmap was created to convert well to
# grayscale, though it does appear to have some small kinks in
# :math:`L^*`. cubehelix was created to vary smoothly in both lightness
# and hue, but appears to have a small hump in the green hue area.
#
# The often-used jet colormap is included in this set of colormaps. We can see
# that the :math:`L^*` values vary widely throughout the colormap, making it a
# poor choice for representing data for viewers to see perceptually. See an
# extension on this idea at [mycarta-jet]_.
cmaps['Miscellaneous'] = [
'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', 'hsv',
'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar']
###############################################################################
# .. _color-colormaps_reference:
#
# First, we'll show the range of each colormap. Note that some seem
# to change more "quickly" than others.
nrows = max(len(cmap_list) for cmap_category, cmap_list in cmaps.items())
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))
def plot_color_gradients(cmap_category, cmap_list, nrows):
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.items():
plot_color_gradients(cmap_category, cmap_list, nrows)
plt.show()
###############################################################################
# Lightness of matplotlib colormaps
# =================================
#
# Here we examine the lightness values of the matplotlib colormaps.
# Note that some documentation on the colormaps is available
# ([list-colormaps]_).
mpl.rcParams.update({'font.size': 12})
# Number of colormap per subplot for particular cmap categories
_DSUBS = {'Perceptually Uniform Sequential': 4, 'Sequential': 6,
'Sequential (2)': 6, 'Diverging': 6, 'Qualitative': 4,
'Miscellaneous': 6}
# Spacing between the colormaps of a subplot
_DC = {'Perceptually Uniform Sequential': 1.4, 'Sequential': 0.7,
'Sequential (2)': 1.4, 'Diverging': 1.4, 'Qualitative': 1.4,
'Miscellaneous': 1.4}
# Indices to step through colormap
x = np.linspace(0.0, 1.0, 100)
# Do plot
for cmap_category, cmap_list in cmaps.items():
# Do subplots so that colormaps have enough space.
# Default is 6 colormaps per subplot.
dsub = _DSUBS.get(cmap_category, 6)
nsubplots = int(np.ceil(len(cmap_list) / float(dsub)))
# squeeze=False to handle similarly the case of a single subplot
fig, axes = plt.subplots(nrows=nsubplots, squeeze=False,
figsize=(7, 2.6*nsubplots))
for i, ax in enumerate(axes.flat):
locs = [] # locations for text labels
for j, cmap in enumerate(cmap_list[i*dsub:(i+1)*dsub]):
# Get RGB values for colormap and convert the colormap in
# CAM02-UCS colorspace. lab[0, :, 0] is the lightness.
rgb = cm.get_cmap(cmap)(x)[np.newaxis, :, :3]
lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb)
# Plot colormap L values. Do separately for each category
# so each plot can be pretty. To make scatter markers change
# color along plot:
# http://stackoverflow.com/questions/8202605/matplotlib-scatterplot-colour-as-a-function-of-a-third-variable
if cmap_category == 'Sequential':
# These colormaps all start at high lightness but we want them
# reversed to look nice in the plot, so reverse the order.
y_ = lab[0, ::-1, 0]
c_ = x[::-1]
else:
y_ = lab[0, :, 0]
c_ = x
dc = _DC.get(cmap_category, 1.4) # cmaps horizontal spacing
ax.scatter(x + j*dc, y_, c=c_, cmap=cmap, s=300, linewidths=0.0)
# Store locations for colormap labels
if cmap_category in ('Perceptually Uniform Sequential',
'Sequential'):
locs.append(x[-1] + j*dc)
elif cmap_category in ('Diverging', 'Qualitative',
'Miscellaneous', 'Sequential (2)'):
locs.append(x[int(x.size/2.)] + j*dc)
# Set up the axis limits:
# * the 1st subplot is used as a reference for the x-axis limits
# * lightness values goes from 0 to 100 (y-axis limits)
ax.set_xlim(axes[0, 0].get_xlim())
ax.set_ylim(0.0, 100.0)
# Set up labels for colormaps
ax.xaxis.set_ticks_position('top')
ticker = mpl.ticker.FixedLocator(locs)
ax.xaxis.set_major_locator(ticker)
formatter = mpl.ticker.FixedFormatter(cmap_list[i*dsub:(i+1)*dsub])
ax.xaxis.set_major_formatter(formatter)
ax.xaxis.set_tick_params(rotation=50)
ax.set_xlabel(cmap_category + ' colormaps', fontsize=14)
fig.text(0.0, 0.55, 'Lightness $L^*$', fontsize=12,
transform=fig.transFigure, rotation=90)
fig.tight_layout(h_pad=0.0, pad=1.5)
plt.show()
###############################################################################
# Grayscale conversion
# ====================
#
# It is important to pay attention to conversion to grayscale for color
# plots, since they may be printed on black and white printers. If not
# carefully considered, your readers may end up with indecipherable
# plots because the grayscale changes unpredictably through the
# colormap.
#
# Conversion to grayscale is done in many different ways [bw]_. Some of the better
# ones use a linear combination of the rgb values of a pixel, but weighted
# according to how we perceive color intensity. A nonlinear method of conversion
# to grayscale is to use the :math:`L^*` values of the pixels. In general, similar
# principles apply for this question as they do for presenting one's information
# perceptually; that is, if a colormap is chosen that is monotonically increasing
# in :math:`L^*` values, it will print in a reasonable manner to grayscale.
#
# With this in mind, we see that the Sequential colormaps have reasonable
# representations in grayscale. Some of the Sequential2 colormaps have decent
# enough grayscale representations, though some (autumn, spring, summer, winter)
# have very little grayscale change. If a colormap like this was used in a plot
# and then the plot was printed to grayscale, a lot of the information may map to
# the same gray values. The Diverging colormaps mostly vary from darker gray on
# the outer edges to white in the middle. Some (PuOr and seismic) have noticably
# darker gray on one side than the other and therefore are not very symmetric.
# coolwarm has little range of gray scale and would print to a more uniform plot,
# losing a lot of detail. Note that overlaid, labeled contours could help
# differentiate between one side of the colormap vs. the other since color cannot
# be used once a plot is printed to grayscale. Many of the Qualitative and
# Miscellaneous colormaps, such as Accent, hsv, and jet, change from darker to
# lighter and back to darker gray throughout the colormap. This would make it
# impossible for a viewer to interpret the information in a plot once it is
# printed in grayscale.
mpl.rcParams.update({'font.size': 14})
# Indices to step through colormap.
x = np.linspace(0.0, 1.0, 100)
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))
def plot_color_gradients(cmap_category, cmap_list):
fig, axes = plt.subplots(nrows=len(cmap_list), ncols=2)
fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99,
wspace=0.05)
fig.suptitle(cmap_category + ' colormaps', fontsize=14, y=1.0, x=0.6)
for ax, name in zip(axes, cmap_list):
# Get RGB values for colormap.
rgb = cm.get_cmap(plt.get_cmap(name))(x)[np.newaxis, :, :3]
# Get colormap in CAM02-UCS colorspace. We want the lightness.
lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb)
L = lab[0, :, 0]
L = np.float32(np.vstack((L, L, L)))
ax[0].imshow(gradient, aspect='auto', cmap=plt.get_cmap(name))
ax[1].imshow(L, aspect='auto', cmap='binary_r', vmin=0., vmax=100.)
pos = list(ax[0].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.flat:
ax.set_axis_off()
plt.show()
for cmap_category, cmap_list in cmaps.items():
plot_color_gradients(cmap_category, cmap_list)
###############################################################################
# Color vision deficiencies
# =========================
#
# There is a lot of information available about color blindness (*e.g.*,
# [colorblindness]_). Additionally, there are tools available to convert images to
# how they look for different types of color vision deficiencies (*e.g.*,
# [vischeck]_).
#
# The most common form of color vision deficiency involves differentiating between
# red and green. Thus, avoiding colormaps with both red and green will avoid many
# problems in general.
#
#
# References
# ==========
#
# .. [colorcet] https://github.com/bokeh/colorcet
# .. [Ware] http://ccom.unh.edu/sites/default/files/publications/Ware_1988_CGA_Color_sequences_univariate_maps.pdf
# .. [Moreland] http://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
# .. [list-colormaps] https://gist.github.com/endolith/2719900#id7
# .. [mycarta-banding] https://mycarta.wordpress.com/2012/10/14/the-rainbow-is-deadlong-live-the-rainbow-part-4-cie-lab-heated-body/
# .. [mycarta-jet] https://mycarta.wordpress.com/2012/10/06/the-rainbow-is-deadlong-live-the-rainbow-part-3/
# .. [bw] http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/
# .. [colorblindness] http://www.color-blindness.com/
# .. [vischeck] http://www.vischeck.com/vischeck/
# .. [IBM] http://www.research.ibm.com/people/l/lloydt/color/color.HTM
PK#J/F@!@!colors/colormapnorms.py"""
Colormap Normalization
======================
Objects that use colormaps by default linearly map the colors in the
colormap from data values *vmin* to *vmax*. For example::
pcm = ax.pcolormesh(x, y, Z, vmin=-1., vmax=1., cmap='RdBu_r')
will map the data in *Z* linearly from -1 to +1, so *Z=0* will
give a color at the center of the colormap *RdBu_r* (white in this
case).
Matplotlib does this mapping in two steps, with a normalization from
[0,1] occurring first, and then mapping onto the indices in the
colormap. Normalizations are classes defined in the
:func:`matplotlib.colors` module. The default, linear normalization is
:func:`matplotlib.colors.Normalize`.
Artists that map data to color pass the arguments *vmin* and *vmax* to
construct a :func:`matplotlib.colors.Normalize` instance, then call it:
.. ipython::
In [1]: import matplotlib as mpl
In [2]: norm = mpl.colors.Normalize(vmin=-1.,vmax=1.)
In [3]: norm(0.)
Out[3]: 0.5
However, there are sometimes cases where it is useful to map data to
colormaps in a non-linear fashion.
Logarithmic
-----------
One of the most common transformations is to plot data by taking
its logarithm (to the base-10). This transformation is useful to
display changes across disparate scales. Using :func:`colors.LogNorm`
normalizes the data via :math:`log_{10}`. In the example below,
there are two bumps, one much smaller than the other. Using
:func:`colors.LogNorm`, the shape and location of each bump can clearly
be seen:
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
# A low hump with a spike coming out of the top right. Needs to have
# z/colour axis on a log scale so we see both hump and spike. linear
# scale only shows the spike.
Z1 = bivariate_normal(X, Y, 0.1, 0.2, 1.0, 1.0) + \
0.1 * bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolor(X, Y, Z1,
norm=colors.LogNorm(vmin=Z1.min(), vmax=Z1.max()),
cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[0], extend='max')
pcm = ax[1].pcolor(X, Y, Z1, cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[1], extend='max')
fig.show()
###############################################################################
# Symmetric logarithmic
# ---------------------
#
# Similarly, it sometimes happens that there is data that is positive
# and negative, but we would still like a logarithmic scaling applied to
# both. In this case, the negative numbers are also scaled
# logarithmically, and mapped to smaller numbers; e.g., if `vmin=-vmax`,
# then they the negative numbers are mapped from 0 to 0.5 and the
# positive from 0.5 to 1.
#
# Since the logarithm of values close to zero tends toward infinity, a
# small range around zero needs to be mapped linearly. The parameter
# *linthresh* allows the user to specify the size of this range
# (-*linthresh*, *linthresh*). The size of this range in the colormap is
# set by *linscale*. When *linscale* == 1.0 (the default), the space used
# for the positive and negative halves of the linear range will be equal
# to one decade in the logarithmic range.
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \
- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z1,
norm=colors.SymLogNorm(linthresh=0.03, linscale=0.03,
vmin=-1.0, vmax=1.0),
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both')
pcm = ax[1].pcolormesh(X, Y, Z1, cmap='RdBu_r', vmin=-np.max(Z1))
fig.colorbar(pcm, ax=ax[1], extend='both')
fig.show()
###############################################################################
# Power-law
# ---------
#
# Sometimes it is useful to remap the colors onto a power-law
# relationship (i.e. :math:`y=x^{\gamma}`, where :math:`\gamma` is the
# power). For this we use the :func:`colors.PowerNorm`. It takes as an
# argument *gamma* (*gamma* == 1.0 will just yield the default linear
# normalization):
#
# .. note::
#
# There should probably be a good reason for plotting the data using
# this type of transformation. Technical viewers are used to linear
# and logarithmic axes and data transformations. Power laws are less
# common, and viewers should explicitly be made aware that they have
# been used.
N = 100
X, Y = np.mgrid[0:3:complex(0, N), 0:2:complex(0, N)]
Z1 = (1 + np.sin(Y * 10.)) * X**(2.)
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z1, norm=colors.PowerNorm(gamma=1./2.),
cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[0], extend='max')
pcm = ax[1].pcolormesh(X, Y, Z1, cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[1], extend='max')
fig.show()
###############################################################################
# Discrete bounds
# ---------------
#
# Another normaization that comes with matplolib is
# :func:`colors.BoundaryNorm`. In addition to *vmin* and *vmax*, this
# takes as arguments boundaries between which data is to be mapped. The
# colors are then linearly distributed between these "bounds". For
# instance:
#
# .. ipython::
#
# In [2]: import matplotlib.colors as colors
#
# In [3]: bounds = np.array([-0.25, -0.125, 0, 0.5, 1])
#
# In [4]: norm = colors.BoundaryNorm(boundaries=bounds, ncolors=4)
#
# In [5]: print(norm([-0.2,-0.15,-0.02, 0.3, 0.8, 0.99]))
# [0 0 1 2 3 3]
#
# Note unlike the other norms, this norm returns values from 0 to *ncolors*-1.
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \
- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03
fig, ax = plt.subplots(3, 1, figsize=(8, 8))
ax = ax.flatten()
# even bounds gives a contour-like effect
bounds = np.linspace(-1, 1, 10)
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[0].pcolormesh(X, Y, Z1,
norm=norm,
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both', orientation='vertical')
# uneven bounds changes the colormapping:
bounds = np.array([-0.25, -0.125, 0, 0.5, 1])
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[1].pcolormesh(X, Y, Z1, norm=norm, cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical')
pcm = ax[2].pcolormesh(X, Y, Z1, cmap='RdBu_r', vmin=-np.max(Z1))
fig.colorbar(pcm, ax=ax[2], extend='both', orientation='vertical')
fig.show()
###############################################################################
# Custom normalization: Two linear ranges
# ---------------------------------------
#
# It is possible to define your own normalization. In the following
# example, we modify :func:`colors:SymLogNorm` to use different linear
# maps for the negative data values and the positive. (Note that this
# example is simple, and does not validate inputs or account for complex
# cases such as masked data)
#
# .. note::
# This may appear soon as :func:`colors.OffsetNorm`.
#
# As above, non-symmetric mapping of data to color is non-standard
# practice for quantitative data, and should only be used advisedly. A
# practical example is having an ocean/land colormap where the land and
# ocean data span different ranges.
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \
- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03
class MidpointNormalize(colors.Normalize):
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
self.midpoint = midpoint
colors.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z1,
norm=MidpointNormalize(midpoint=0.),
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both')
pcm = ax[1].pcolormesh(X, Y, Z1, cmap='RdBu_r', vmin=-np.max(Z1))
fig.colorbar(pcm, ax=ax[1], extend='both')
fig.show()
PK#JAcolors/colorbar_only.py"""
=============================
Customized Colorbars Tutorial
=============================
This tutorial shows how to build colorbars without an attached plot.
Customized Colorbars
====================
:class:`~matplotlib.colorbar.ColorbarBase` derives from
:mod:`~matplotlib.cm.ScalarMappable` and puts a colorbar in a specified axes,
so it has everything needed for a standalone colorbar. It can be used as is to
make a colorbar for a given colormap and does not need a mappable object like
an image. In this tutorial we will explore what can be done with standalone
colorbar.
Basic continuous colorbar
-------------------------
Set the colormap and norm to correspond to the data for which the colorbar
will be used. Then create the colorbar by calling
:class:`~matplotlib.colorbar.ColorbarBase` and specify axis, colormap, norm
and orientation as parameters. Here we create a basic continuous colorbar
with ticks and labels. More information on colorbar api can be found
`here `.
"""
import matplotlib.pyplot as plt
import matplotlib as mpl
fig, ax = plt.subplots()
cmap = mpl.cm.cool
norm = mpl.colors.Normalize(vmin=5, vmax=10)
cb1 = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
norm=norm,
orientation='horizontal')
cb1.set_label('Some Units')
fig.show()
###############################################################################
# Discrete intervals colorbar
# ---------------------------
#
# The second example illustrates the use of a
# :class:`~matplotlib.colors.ListedColormap` which generates a colormap from a
# set of listed colors, :func:`colors.BoundaryNorm` which generates a colormap
# index based on discrete intervals and extended ends to show the "over" and
# "under" value colors. Over and under are used to display data outside of the
# normalized [0,1] range. Here we pass colors as gray shades as a string
# encoding a float in the 0-1 range.
#
# If a :class:`~matplotlib.colors.ListedColormap` is used, the length of the
# bounds array must be one greater than the length of the color list. The
# bounds must be monotonically increasing.
#
# This time we pass some more arguments in addition to previous arguments to
# :class:`~matplotlib.colorbar.ColorbarBase`. For the out-of-range values to
# display on the colorbar, we have to use the *extend* keyword argument. To use
# *extend*, you must specify two extra boundaries. Finally spacing argument
# ensures that intervals are shown on colorbar proportionally.
fig, ax = plt.subplots()
cmap = mpl.colors.ListedColormap(['red', 'green', 'blue', 'cyan'])
cmap.set_over('0.25')
cmap.set_under('0.75')
bounds = [1, 2, 4, 7, 8]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
cb2 = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
norm=norm,
boundaries=[0] + bounds + [13],
extend='both',
ticks=bounds,
spacing='proportional',
orientation='horizontal')
cb2.set_label('Discrete intervals, some other units')
fig.show()
###############################################################################
# Colorbar with custom extension lengths
# --------------------------------------
#
# Here we illustrate the use of custom length colorbar extensions, used on a
# colorbar with discrete intervals. To make the length of each extension same
# as the length of the interior colors, use ``extendfrac='auto'``.
fig, ax = plt.subplots()
cmap = mpl.colors.ListedColormap(['royalblue', 'cyan',
'yellow', 'orange'])
cmap.set_over('red')
cmap.set_under('blue')
bounds = [-1.0, -0.5, 0.0, 0.5, 1.0]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
cb3 = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
norm=norm,
boundaries=[-10] + bounds + [10],
extend='both',
extendfrac='auto',
ticks=bounds,
spacing='uniform',
orientation='horizontal')
cb3.set_label('Custom extension lengths, some other units')
fig.show()
PK#J<text/pgf.py"""
*********************************
Typesetting With XeLaTeX/LuaLaTeX
*********************************
How to typeset text with the ``pgf`` backend in Matplotlib.
Using the ``pgf`` backend, matplotlib can export figures as pgf drawing commands
that can be processed with pdflatex, xelatex or lualatex. XeLaTeX and LuaLaTeX
have full unicode support and can use any font that is installed in the operating
system, making use of advanced typographic features of OpenType, AAT and
Graphite. Pgf pictures created by ``plt.savefig('figure.pgf')`` can be
embedded as raw commands in LaTeX documents. Figures can also be directly
compiled and saved to PDF with ``plt.savefig('figure.pdf')`` by either
switching to the backend
.. code-block:: python
matplotlib.use('pgf')
or registering it for handling pdf output
.. code-block:: python
from matplotlib.backends.backend_pgf import FigureCanvasPgf
matplotlib.backend_bases.register_backend('pdf', FigureCanvasPgf)
The second method allows you to keep using regular interactive backends and to
save xelatex, lualatex or pdflatex compiled PDF files from the graphical user interface.
Matplotlib's pgf support requires a recent LaTeX_ installation that includes
the TikZ/PGF packages (such as TeXLive_), preferably with XeLaTeX or LuaLaTeX
installed. If either pdftocairo or ghostscript is present on your system,
figures can optionally be saved to PNG images as well. The executables
for all applications must be located on your :envvar:`PATH`.
Rc parameters that control the behavior of the pgf backend:
================= =====================================================
Parameter Documentation
================= =====================================================
pgf.preamble Lines to be included in the LaTeX preamble
pgf.rcfonts Setup fonts from rc params using the fontspec package
pgf.texsystem Either "xelatex" (default), "lualatex" or "pdflatex"
================= =====================================================
.. note::
TeX defines a set of special characters, such as::
# $ % & ~ _ ^ \ { }
Generally, these characters must be escaped correctly. For convenience,
some characters (_,^,%) are automatically escaped outside of math
environments.
.. _pgf-rcfonts:
Font specification
==================
The fonts used for obtaining the size of text elements or when compiling
figures to PDF are usually defined in the matplotlib rc parameters. You can
also use the LaTeX default Computer Modern fonts by clearing the lists for
``font.serif``, ``font.sans-serif`` or ``font.monospace``. Please note that
the glyph coverage of these fonts is very limited. If you want to keep the
Computer Modern font face but require extended unicode support, consider
installing the `Computer Modern Unicode `_
fonts *CMU Serif*, *CMU Sans Serif*, etc.
When saving to ``.pgf``, the font configuration matplotlib used for the
layout of the figure is included in the header of the text file.
.. literalinclude:: ../../gallery/userdemo/pgf_fonts_sgskip.py
:end-before: plt.savefig
.. _pgf-preamble:
Custom preamble
===============
Full customization is possible by adding your own commands to the preamble.
Use the ``pgf.preamble`` parameter if you want to configure the math fonts,
using ``unicode-math`` for example, or for loading additional packages. Also,
if you want to do the font configuration yourself instead of using the fonts
specified in the rc parameters, make sure to disable ``pgf.rcfonts``.
.. htmlonly::
.. literalinclude:: ../../gallery/userdemo/pgf_preamble_sgskip.py
:end-before: plt.savefig
.. latexonly::
.. literalinclude:: ../../gallery/userdemo/pgf_preamble_sgskip.py
:end-before: import matplotlib.pyplot as plt
.. _pgf-texsystem:
Choosing the TeX system
=======================
The TeX system to be used by matplotlib is chosen by the ``pgf.texsystem``
parameter. Possible values are ``'xelatex'`` (default), ``'lualatex'`` and
``'pdflatex'``. Please note that when selecting pdflatex the fonts and
unicode handling must be configured in the preamble.
.. literalinclude:: ../../gallery/userdemo/pgf_texsystem_sgskip.py
:end-before: plt.savefig
.. _pgf-troubleshooting:
Troubleshooting
===============
* Please note that the TeX packages found in some Linux distributions and
MiKTeX installations are dramatically outdated. Make sure to update your
package catalog and upgrade or install a recent TeX distribution.
* On Windows, the :envvar:`PATH` environment variable may need to be modified
to include the directories containing the latex, dvipng and ghostscript
executables. See :ref:`environment-variables` and
:ref:`setting-windows-environment-variables` for details.
* A limitation on Windows causes the backend to keep file handles that have
been opened by your application open. As a result, it may not be possible
to delete the corresponding files until the application closes (see
`#1324 `_).
* Sometimes the font rendering in figures that are saved to png images is
very bad. This happens when the pdftocairo tool is not available and
ghostscript is used for the pdf to png conversion.
* Make sure what you are trying to do is possible in a LaTeX document,
that your LaTeX syntax is valid and that you are using raw strings
if necessary to avoid unintended escape sequences.
* The ``pgf.preamble`` rc setting provides lots of flexibility, and lots of
ways to cause problems. When experiencing problems, try to minimalize or
disable the custom preamble.
* Configuring an ``unicode-math`` environment can be a bit tricky. The
TeXLive distribution for example provides a set of math fonts which are
usually not installed system-wide. XeTeX, unlike LuaLatex, cannot find
these fonts by their name, which is why you might have to specify
``\setmathfont{xits-math.otf}`` instead of ``\setmathfont{XITS Math}`` or
alternatively make the fonts available to your OS. See this
`tex.stackexchange.com question `_
for more details.
* If the font configuration used by matplotlib differs from the font setting
in yout LaTeX document, the alignment of text elements in imported figures
may be off. Check the header of your ``.pgf`` file if you are unsure about
the fonts matplotlib used for the layout.
* Vector images and hence ``.pgf`` files can become bloated if there are a lot
of objects in the graph. This can be the case for image processing or very
big scatter graphs. In an extreme case this can cause TeX to run out of
memory: "TeX capacity exceeded, sorry" You can configure latex to increase
the amount of memory available to generate the ``.pdf`` image as discussed on
`tex.stackexchange.com `_.
Another way would be to "rasterize" parts of the graph causing problems
using either the ``rasterized=True`` keyword, or ``.set_rasterized(True)`` as per
`this example `_.
* If you still need help, please see :ref:`reporting-problems`
.. _LaTeX: http://www.tug.org
.. _TeXLive: http://www.tug.org/texlive/
"""
PK#JfdS00text/mathtext.py"""
Writing mathematical expressions
================================
An introduction to writing mathematical expressions in Matplotlib.
You can use a subset TeX markup in any matplotlib text string by
placing it inside a pair of dollar signs ($).
Note that you do not need to have TeX installed, since matplotlib
ships its own TeX expression parser, layout engine and fonts. The
layout engine is a fairly direct adaptation of the layout algorithms
in Donald Knuth's TeX, so the quality is quite good (matplotlib also
provides a ``usetex`` option for those who do want to call out to TeX
to generate their text (see :ref:`sphx_glr_tutorials_text_usetex.py`).
"""
###############################################################################
# Any text element can use math text. You should use raw strings (precede the
# quotes with an ``'r'``), and surround the math text with dollar signs ($), as in
# TeX. Regular text and mathtext can be interleaved within the same string.
# Mathtext can use DejaVu Sans (default), DejaVu Serif, the Computer Modern fonts
# (from (La)TeX), `STIX `_ fonts (with are designed
# to blend well with Times), or a Unicode font that you provide. The mathtext
# font can be selected with the customization variable ``mathtext.fontset`` (see
# :ref:`sphx_glr_tutorials_01_introductory_customizing.py`)
#
# .. note::
# On `"narrow" `_ builds
# of Python, if you use the STIX fonts you should also set
# ``ps.fonttype`` and ``pdf.fonttype`` to 3 (the default), not 42.
# Otherwise `some characters will not be visible
# `_.
#
# Here is a simple example::
#
# # plain text
# plt.title('alpha > beta')
#
# produces "alpha > beta".
#
# Whereas this::
#
# # math text
# plt.title(r'$\alpha > \beta$')
#
# produces ":math:`\alpha > \beta`".
#
# .. note::
# Mathtext should be placed between a pair of dollar signs ($). To
# make it easy to display monetary values, e.g., "$100.00", if a
# single dollar sign is present in the entire string, it will be
# displayed verbatim as a dollar sign. This is a small change from
# regular TeX, where the dollar sign in non-math text would have to
# be escaped ('\\\$').
#
# .. note::
# While the syntax inside the pair of dollar signs ($) aims to be
# TeX-like, the text outside does not. In particular, characters
# such as::
#
# # $ % & ~ _ ^ \ { } \( \) \[ \]
#
# have special meaning outside of math mode in TeX. Therefore, these
# characters will behave differently depending on the rcParam
# ``text.usetex`` flag. See the :ref:`usetex tutorial
# ` for more information.
#
# Subscripts and superscripts
# ---------------------------
#
# To make subscripts and superscripts, use the ``'_'`` and ``'^'`` symbols::
#
# r'$\alpha_i > \beta_i$'
#
# .. math::
#
# \alpha_i > \beta_i
#
# Some symbols automatically put their sub/superscripts under and over
# the operator. For example, to write the sum of :math:`x_i` from :math:`0` to
# :math:`\infty`, you could do::
#
# r'$\sum_{i=0}^\infty x_i$'
#
# .. math::
#
# \sum_{i=0}^\infty x_i
#
# Fractions, binomials and stacked numbers
# ----------------------------------------
#
# Fractions, binomials and stacked numbers can be created with the
# ``\frac{}{}``, ``\binom{}{}`` and ``\stackrel{}{}`` commands,
# respectively::
#
# r'$\frac{3}{4} \binom{3}{4} \stackrel{3}{4}$'
#
# produces
#
# .. math::
#
# \frac{3}{4} \binom{3}{4} \stackrel{3}{4}
#
# Fractions can be arbitrarily nested::
#
# r'$\frac{5 - \frac{1}{x}}{4}$'
#
# produces
#
# .. math::
#
# \frac{5 - \frac{1}{x}}{4}
#
# Note that special care needs to be taken to place parentheses and brackets around
# fractions. Doing things the obvious way produces brackets that are
# too small::
#
# r'$(\frac{5 - \frac{1}{x}}{4})$'
#
# .. math ::
#
# (\frac{5 - \frac{1}{x}}{4})
#
# The solution is to precede the bracket with ``\left`` and ``\right``
# to inform the parser that those brackets encompass the entire object.::
#
# r'$\left(\frac{5 - \frac{1}{x}}{4}\right)$'
#
# .. math ::
#
# \left(\frac{5 - \frac{1}{x}}{4}\right)
#
# Radicals
# --------
#
# Radicals can be produced with the ``\sqrt[]{}`` command. For example::
#
# r'$\sqrt{2}$'
#
# .. math ::
#
# \sqrt{2}
#
# Any base can (optionally) be provided inside square brackets. Note
# that the base must be a simple expression, and can not contain layout
# commands such as fractions or sub/superscripts::
#
# r'$\sqrt[3]{x}$'
#
# .. math ::
#
# \sqrt[3]{x}
#
# .. _mathtext-fonts:
#
# Fonts
# -----
#
# The default font is *italics* for mathematical symbols.
#
# .. note::
#
# This default can be changed using the ``mathtext.default`` rcParam.
# This is useful, for example, to use the same font as regular
# non-math text for math text, by setting it to ``regular``.
#
# To change fonts, e.g., to write "sin" in a Roman font, enclose the text
# in a font command::
#
# r'$s(t) = \mathcal{A}\mathrm{sin}(2 \omega t)$'
#
# .. math::
#
# s(t) = \mathcal{A}\mathrm{sin}(2 \omega t)
#
# More conveniently, many commonly used function names that are typeset in a
# Roman font have shortcuts. So the expression above could be written
# as follows::
#
# r'$s(t) = \mathcal{A}\sin(2 \omega t)$'
#
# .. math::
#
# s(t) = \mathcal{A}\sin(2 \omega t)
#
# Here "s" and "t" are variable in italics font (default), "sin" is in
# Roman font, and the amplitude "A" is in calligraphy font. Note in the
# example above the caligraphy ``A`` is squished into the ``sin``. You
# can use a spacing command to add a little whitespace between them::
#
# s(t) = \mathcal{A}\/\sin(2 \omega t)
#
# .. math::
#
# s(t) = \mathcal{A}\/\sin(2 \omega t)
#
# The choices available with all fonts are:
#
# ============================ ==================================
# Command Result
# ============================ ==================================
# ``\mathrm{Roman}`` :math:`\mathrm{Roman}`
# ``\mathit{Italic}`` :math:`\mathit{Italic}`
# ``\mathtt{Typewriter}`` :math:`\mathtt{Typewriter}`
# ``\mathcal{CALLIGRAPHY}`` :math:`\mathcal{CALLIGRAPHY}`
# ============================ ==================================
#
# .. role:: math-stix(math)
# :fontset: stix
#
# When using the `STIX `_ fonts, you also have the choice of:
#
# ====================================== =========================================
# Command Result
# ====================================== =========================================
# ``\mathbb{blackboard}`` :math-stix:`\mathbb{blackboard}`
# ``\mathrm{\mathbb{blackboard}}`` :math-stix:`\mathrm{\mathbb{blackboard}}`
# ``\mathfrak{Fraktur}`` :math-stix:`\mathfrak{Fraktur}`
# ``\mathsf{sansserif}`` :math-stix:`\mathsf{sansserif}`
# ``\mathrm{\mathsf{sansserif}}`` :math-stix:`\mathrm{\mathsf{sansserif}}`
# ====================================== =========================================
#
# .. htmlonly::
#
# ====================================== =========================================
# ``\mathcircled{circled}`` :math-stix:`\mathcircled{circled}`
# ====================================== =========================================
#
# There are also three global "font sets" to choose from, which are
# selected using the ``mathtext.fontset`` parameter in
# :ref:`matplotlibrc `.
#
# ``cm``: **Computer Modern (TeX)**
#
# .. image:: ../../_static/cm_fontset.png
#
# ``stix``: **STIX** (designed to blend well with Times)
#
# .. image:: ../../_static/stix_fontset.png
#
# ``stixsans``: **STIX sans-serif**
#
# .. image:: ../../_static/stixsans_fontset.png
#
# Additionally, you can use ``\mathdefault{...}`` or its alias
# ``\mathregular{...}`` to use the font used for regular text outside of
# mathtext. There are a number of limitations to this approach, most
# notably that far fewer symbols will be available, but it can be useful
# to make math expressions blend well with other text in the plot.
#
# Custom fonts
# ~~~~~~~~~~~~
#
# mathtext also provides a way to use custom fonts for math. This
# method is fairly tricky to use, and should be considered an
# experimental feature for patient users only. By setting the rcParam
# ``mathtext.fontset`` to ``custom``, you can then set the following
# parameters, which control which font file to use for a particular set
# of math characters.
#
# ============================== =================================
# Parameter Corresponds to
# ============================== =================================
# ``mathtext.it`` ``\mathit{}`` or default italic
# ``mathtext.rm`` ``\mathrm{}`` Roman (upright)
# ``mathtext.tt`` ``\mathtt{}`` Typewriter (monospace)
# ``mathtext.bf`` ``\mathbf{}`` bold italic
# ``mathtext.cal`` ``\mathcal{}`` calligraphic
# ``mathtext.sf`` ``\mathsf{}`` sans-serif
# ============================== =================================
#
# Each parameter should be set to a fontconfig font descriptor (as
# defined in the yet-to-be-written font chapter).
#
# .. TODO: Link to font chapter
#
# The fonts used should have a Unicode mapping in order to find any
# non-Latin characters, such as Greek. If you want to use a math symbol
# that is not contained in your custom fonts, you can set the rcParam
# ``mathtext.fallback_to_cm`` to ``True`` which will cause the mathtext
# system to use characters from the default Computer Modern fonts
# whenever a particular character can not be found in the custom font.
#
# Note that the math glyphs specified in Unicode have evolved over time,
# and many fonts may not have glyphs in the correct place for mathtext.
#
# Accents
# -------
#
# An accent command may precede any symbol to add an accent above it.
# There are long and short forms for some of them.
#
# ============================== =================================
# Command Result
# ============================== =================================
# ``\acute a`` or ``\'a`` :math:`\acute a`
# ``\bar a`` :math:`\bar a`
# ``\breve a`` :math:`\breve a`
# ``\ddot a`` or ``\''a`` :math:`\ddot a`
# ``\dot a`` or ``\.a`` :math:`\dot a`
# ``\grave a`` or ``\`a`` :math:`\grave a`
# ``\hat a`` or ``\^a`` :math:`\hat a`
# ``\tilde a`` or ``\~a`` :math:`\tilde a`
# ``\vec a`` :math:`\vec a`
# ``\overline{abc}`` :math:`\overline{abc}`
# ============================== =================================
#
# In addition, there are two special accents that automatically adjust
# to the width of the symbols below:
#
# ============================== =================================
# Command Result
# ============================== =================================
# ``\widehat{xyz}`` :math:`\widehat{xyz}`
# ``\widetilde{xyz}`` :math:`\widetilde{xyz}`
# ============================== =================================
#
# Care should be taken when putting accents on lower-case i's and j's.
# Note that in the following ``\imath`` is used to avoid the extra dot
# over the i::
#
# r"$\hat i\ \ \hat \imath$"
#
# .. math::
#
# \hat i\ \ \hat \imath
#
# Symbols
# -------
#
# You can also use a large number of the TeX symbols, as in ``\infty``,
# ``\leftarrow``, ``\sum``, ``\int``.
#
# .. math_symbol_table::
#
# If a particular symbol does not have a name (as is true of many of the
# more obscure symbols in the STIX fonts), Unicode characters can
# also be used::
#
# ur'$\u23ce$'
#
# Example
# -------
#
# Here is an example illustrating many of these features in context.
#
# .. figure:: ../../gallery/pyplots/images/sphx_glr_pyplot_mathtext_001.png
# :target: ../../gallery/pyplots/pyplot_mathtext.html
# :align: center
# :scale: 50
#
# Pyplot Mathtext
PK#J36WWtext/annotations.py"""
Annotations
===========
Annotating text with Matplotlib.
.. contents:: Table of Contents
:depth: 3
.. _annotations-tutorial:
Basic annotation
================
The uses of the basic :func:`~matplotlib.pyplot.text` will place text
at an arbitrary position on the Axes. A common use case of text is to
annotate some feature of the plot, and the
:func:`~matplotlib.Axes.annotate` method provides helper functionality
to make annotations easy. In an annotation, there are two points to
consider: the location being annotated represented by the argument
``xy`` and the location of the text ``xytext``. Both of these
arguments are ``(x,y)`` tuples.
.. figure:: ../../gallery/pyplots/images/sphx_glr_annotation_basic_001.png
:target: ../../gallery/pyplots/annotation_basic.html
:align: center
:scale: 50
Annotation Basic
In this example, both the ``xy`` (arrow tip) and ``xytext`` locations
(text location) are in data coordinates. There are a variety of other
coordinate systems one can choose -- you can specify the coordinate
system of ``xy`` and ``xytext`` with one of the following strings for
``xycoords`` and ``textcoords`` (default is 'data')
==================== ====================================================
argument coordinate system
==================== ====================================================
'figure points' points from the lower left corner of the figure
'figure pixels' pixels from the lower left corner of the figure
'figure fraction' 0,0 is lower left of figure and 1,1 is upper right
'axes points' points from lower left corner of axes
'axes pixels' pixels from lower left corner of axes
'axes fraction' 0,0 is lower left of axes and 1,1 is upper right
'data' use the axes data coordinate system
==================== ====================================================
For example to place the text coordinates in fractional axes
coordinates, one could do::
ax.annotate('local max', xy=(3, 1), xycoords='data',
xytext=(0.8, 0.95), textcoords='axes fraction',
arrowprops=dict(facecolor='black', shrink=0.05),
horizontalalignment='right', verticalalignment='top',
)
For physical coordinate systems (points or pixels) the origin is the
bottom-left of the figure or axes.
Optionally, you can enable drawing of an arrow from the text to the annotated
point by giving a dictionary of arrow properties in the optional keyword
argument ``arrowprops``.
==================== =====================================================
``arrowprops`` key description
==================== =====================================================
width the width of the arrow in points
frac the fraction of the arrow length occupied by the head
headwidth the width of the base of the arrow head in points
shrink move the tip and base some percent away from
the annotated point and text
\*\*kwargs any key for :class:`matplotlib.patches.Polygon`,
e.g., ``facecolor``
==================== =====================================================
In the example below, the ``xy`` point is in native coordinates
(``xycoords`` defaults to 'data'). For a polar axes, this is in
(theta, radius) space. The text in this example is placed in the
fractional figure coordinate system. :class:`matplotlib.text.Text`
keyword args like ``horizontalalignment``, ``verticalalignment`` and
``fontsize`` are passed from `~matplotlib.Axes.annotate` to the
``Text`` instance.
.. figure:: ../../gallery/pyplots/images/sphx_glr_annotation_polar_001.png
:target: ../../gallery/pyplots/annotation_polar.html
:align: center
:scale: 50
Annotation Polar
For more on all the wild and wonderful things you can do with
annotations, including fancy arrows, see :ref:`plotting-guide-annotation`
and :ref:`sphx_glr_gallery_text_labels_and_annotations_annotation_demo.py`.
Do not proceed unless you have already read :ref:`annotations-tutorial`,
:func:`~matplotlib.pyplot.text` and :func:`~matplotlib.pyplot.annotate`!
.. _plotting-guide-annotation:
Advanced Annotation
===================
Annotating with Text with Box
-----------------------------
Let's start with a simple example.
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_text_arrow_001.png
:target: ../../gallery/userdemo/annotate_text_arrow.html
:align: center
:scale: 50
Annotate Text Arrow
The :func:`~matplotlib.pyplot.text` function in the pyplot module (or
text method of the Axes class) takes bbox keyword argument, and when
given, a box around the text is drawn. ::
bbox_props = dict(boxstyle="rarrow,pad=0.3", fc="cyan", ec="b", lw=2)
t = ax.text(0, 0, "Direction", ha="center", va="center", rotation=45,
size=15,
bbox=bbox_props)
The patch object associated with the text can be accessed by::
bb = t.get_bbox_patch()
The return value is an instance of FancyBboxPatch and the patch
properties like facecolor, edgewidth, etc. can be accessed and
modified as usual. To change the shape of the box, use the *set_boxstyle*
method. ::
bb.set_boxstyle("rarrow", pad=0.6)
The arguments are the name of the box style with its attributes as
keyword arguments. Currently, following box styles are implemented.
========== ============== ==========================
Class Name Attrs
========== ============== ==========================
Circle ``circle`` pad=0.3
DArrow ``darrow`` pad=0.3
LArrow ``larrow`` pad=0.3
RArrow ``rarrow`` pad=0.3
Round ``round`` pad=0.3,rounding_size=None
Round4 ``round4`` pad=0.3,rounding_size=None
Roundtooth ``roundtooth`` pad=0.3,tooth_size=None
Sawtooth ``sawtooth`` pad=0.3,tooth_size=None
Square ``square`` pad=0.3
========== ============== ==========================
.. figure:: ../../gallery/pylab_examples/images/sphx_glr_fancybox_demo_001.png
:target: ../../gallery/pylab_examples/fancybox_demo.html
:align: center
:scale: 50
Fancybox Demo
Note that the attribute arguments can be specified within the style
name with separating comma (this form can be used as "boxstyle" value
of bbox argument when initializing the text instance) ::
bb.set_boxstyle("rarrow,pad=0.6")
Annotating with Arrow
---------------------
The :func:`~matplotlib.pyplot.annotate` function in the pyplot module
(or annotate method of the Axes class) is used to draw an arrow
connecting two points on the plot. ::
ax.annotate("Annotation",
xy=(x1, y1), xycoords='data',
xytext=(x2, y2), textcoords='offset points',
)
This annotates a point at ``xy`` in the given coordinate (``xycoords``)
with the text at ``xytext`` given in ``textcoords``. Often, the
annotated point is specified in the *data* coordinate and the annotating
text in *offset points*.
See :func:`~matplotlib.pyplot.annotate` for available coordinate systems.
An arrow connecting two points (xy & xytext) can be optionally drawn by
specifying the ``arrowprops`` argument. To draw only an arrow, use
empty string as the first argument. ::
ax.annotate("",
xy=(0.2, 0.2), xycoords='data',
xytext=(0.8, 0.8), textcoords='data',
arrowprops=dict(arrowstyle="->",
connectionstyle="arc3"),
)
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_simple01_001.png
:target: ../../gallery/userdemo/annotate_simple01.html
:align: center
:scale: 50
Annotate Simple01
The arrow drawing takes a few steps.
1. a connecting path between two points are created. This is
controlled by ``connectionstyle`` key value.
2. If patch object is given (*patchA* & *patchB*), the path is clipped to
avoid the patch.
3. The path is further shrunk by given amount of pixels (*shrinkA*
& *shrinkB*)
4. The path is transmuted to arrow patch, which is controlled by the
``arrowstyle`` key value.
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_explain_001.png
:target: ../../gallery/userdemo/annotate_explain.html
:align: center
:scale: 50
Annotate Explain
The creation of the connecting path between two points is controlled by
``connectionstyle`` key and the following styles are available.
========== =============================================
Name Attrs
========== =============================================
``angle`` angleA=90,angleB=0,rad=0.0
``angle3`` angleA=90,angleB=0
``arc`` angleA=0,angleB=0,armA=None,armB=None,rad=0.0
``arc3`` rad=0.0
``bar`` armA=0.0,armB=0.0,fraction=0.3,angle=None
========== =============================================
Note that "3" in ``angle3`` and ``arc3`` is meant to indicate that the
resulting path is a quadratic spline segment (three control
points). As will be discussed below, some arrow style options can only
be used when the connecting path is a quadratic spline.
The behavior of each connection style is (limitedly) demonstrated in the
example below. (Warning : The behavior of the ``bar`` style is currently not
well defined, it may be changed in the future).
.. figure:: ../../gallery/userdemo/images/sphx_glr_connectionstyle_demo_001.png
:target: ../../gallery/userdemo/connectionstyle_demo.html
:align: center
:scale: 50
Connectionstyle Demo
The connecting path (after clipping and shrinking) is then mutated to
an arrow patch, according to the given ``arrowstyle``.
========== =============================================
Name Attrs
========== =============================================
``-`` None
``->`` head_length=0.4,head_width=0.2
``-[`` widthB=1.0,lengthB=0.2,angleB=None
``|-|`` widthA=1.0,widthB=1.0
``-|>`` head_length=0.4,head_width=0.2
``<-`` head_length=0.4,head_width=0.2
``<->`` head_length=0.4,head_width=0.2
``<|-`` head_length=0.4,head_width=0.2
``<|-|>`` head_length=0.4,head_width=0.2
``fancy`` head_length=0.4,head_width=0.4,tail_width=0.4
``simple`` head_length=0.5,head_width=0.5,tail_width=0.2
``wedge`` tail_width=0.3,shrink_factor=0.5
========== =============================================
.. figure:: ../../gallery/pylab_examples/images/sphx_glr_fancyarrow_demo_001.png
:target: ../../gallery/pylab_examples/fancyarrow_demo.html
:align: center
:scale: 50
Fancyarrow Demo
Some arrowstyles only work with connection styles that generate a
quadratic-spline segment. They are ``fancy``, ``simple``, and ``wedge``.
For these arrow styles, you must use the "angle3" or "arc3" connection
style.
If the annotation string is given, the patchA is set to the bbox patch
of the text by default.
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_simple02_001.png
:target: ../../gallery/userdemo/annotate_simple02.html
:align: center
:scale: 50
Annotate Simple02
As in the text command, a box around the text can be drawn using
the ``bbox`` argument.
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_simple03_001.png
:target: ../../gallery/userdemo/annotate_simple03.html
:align: center
:scale: 50
Annotate Simple03
By default, the starting point is set to the center of the text
extent. This can be adjusted with ``relpos`` key value. The values
are normalized to the extent of the text. For example, (0,0) means
lower-left corner and (1,1) means top-right.
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_simple04_001.png
:target: ../../gallery/userdemo/annotate_simple04.html
:align: center
:scale: 50
Annotate Simple04
Placing Artist at the anchored location of the Axes
---------------------------------------------------
There are classes of artists that can be placed at an anchored location
in the Axes. A common example is the legend. This type of artist can
be created by using the OffsetBox class. A few predefined classes are
available in ``mpl_toolkits.axes_grid1.anchored_artists`` others in
``matplotlib.offsetbox`` ::
from matplotlib.offsetbox import AnchoredText
at = AnchoredText("Figure 1a",
prop=dict(size=8), frameon=True,
loc=2,
)
at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
ax.add_artist(at)
.. figure:: ../../gallery/userdemo/images/sphx_glr_anchored_box01_001.png
:target: ../../gallery/userdemo/anchored_box01.html
:align: center
:scale: 50
Anchored Box01
The *loc* keyword has same meaning as in the legend command.
A simple application is when the size of the artist (or collection of
artists) is known in pixel size during the time of creation. For
example, If you want to draw a circle with fixed size of 20 pixel x 20
pixel (radius = 10 pixel), you can utilize
``AnchoredDrawingArea``. The instance is created with a size of the
drawing area (in pixels), and arbitrary artists can added to the
drawing area. Note that the extents of the artists that are added to
the drawing area are not related to the placement of the drawing
area itself. Only the initial size matters. ::
from mpl_toolkits.axes_grid1.anchored_artists import AnchoredDrawingArea
ada = AnchoredDrawingArea(20, 20, 0, 0,
loc=1, pad=0., frameon=False)
p1 = Circle((10, 10), 10)
ada.drawing_area.add_artist(p1)
p2 = Circle((30, 10), 5, fc="r")
ada.drawing_area.add_artist(p2)
The artists that are added to the drawing area should not have a
transform set (it will be overridden) and the dimensions of those
artists are interpreted as a pixel coordinate, i.e., the radius of the
circles in above example are 10 pixels and 5 pixels, respectively.
.. figure:: ../../gallery/userdemo/images/sphx_glr_anchored_box02_001.png
:target: ../../gallery/userdemo/anchored_box02.html
:align: center
:scale: 50
Anchored Box02
Sometimes, you want your artists to scale with the data coordinate (or
coordinates other than canvas pixels). You can use
``AnchoredAuxTransformBox`` class. This is similar to
``AnchoredDrawingArea`` except that the extent of the artist is
determined during the drawing time respecting the specified transform. ::
from mpl_toolkits.axes_grid1.anchored_artists import AnchoredAuxTransformBox
box = AnchoredAuxTransformBox(ax.transData, loc=2)
el = Ellipse((0,0), width=0.1, height=0.4, angle=30) # in data coordinates!
box.drawing_area.add_artist(el)
The ellipse in the above example will have width and height
corresponding to 0.1 and 0.4 in data coordinateing and will be
automatically scaled when the view limits of the axes change.
.. figure:: ../../gallery/userdemo/images/sphx_glr_anchored_box03_001.png
:target: ../../gallery/userdemo/anchored_box03.html
:align: center
:scale: 50
Anchored Box03
As in the legend, the bbox_to_anchor argument can be set. Using the
HPacker and VPacker, you can have an arrangement(?) of artist as in the
legend (as a matter of fact, this is how the legend is created).
.. figure:: ../../gallery/userdemo/images/sphx_glr_anchored_box04_001.png
:target: ../../gallery/userdemo/anchored_box04.html
:align: center
:scale: 50
Anchored Box04
Note that unlike the legend, the ``bbox_transform`` is set
to IdentityTransform by default.
Using Complex Coordinates with Annotations
------------------------------------------
The Annotation in matplotlib supports several types of coordinates as
described in :ref:`annotations-tutorial`. For an advanced user who wants
more control, it supports a few other options.
1. :class:`~matplotlib.transforms.Transform` instance. For example, ::
ax.annotate("Test", xy=(0.5, 0.5), xycoords=ax.transAxes)
is identical to ::
ax.annotate("Test", xy=(0.5, 0.5), xycoords="axes fraction")
With this, you can annotate a point in other axes. ::
ax1, ax2 = subplot(121), subplot(122)
ax2.annotate("Test", xy=(0.5, 0.5), xycoords=ax1.transData,
xytext=(0.5, 0.5), textcoords=ax2.transData,
arrowprops=dict(arrowstyle="->"))
2. :class:`~matplotlib.artist.Artist` instance. The xy value (or
xytext) is interpreted as a fractional coordinate of the bbox
(return value of *get_window_extent*) of the artist. ::
an1 = ax.annotate("Test 1", xy=(0.5, 0.5), xycoords="data",
va="center", ha="center",
bbox=dict(boxstyle="round", fc="w"))
an2 = ax.annotate("Test 2", xy=(1, 0.5), xycoords=an1, # (1,0.5) of the an1's bbox
xytext=(30,0), textcoords="offset points",
va="center", ha="left",
bbox=dict(boxstyle="round", fc="w"),
arrowprops=dict(arrowstyle="->"))
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_simple_coord01_001.png
:target: ../../gallery/userdemo/annotate_simple_coord01.html
:align: center
:scale: 50
Annotation with Simple Coordinates
Note that it is your responsibility that the extent of the
coordinate artist (*an1* in above example) is determined before *an2*
gets drawn. In most cases, it means that *an2* needs to be drawn
later than *an1*.
3. A callable object that returns an instance of either
:class:`~matplotlib.transforms.BboxBase` or
:class:`~matplotlib.transforms.Transform`. If a transform is
returned, it is the same as 1 and if a bbox is returned, it is the same
as 2. The callable object should take a single argument of the
renderer instance. For example, the following two commands give
identical results ::
an2 = ax.annotate("Test 2", xy=(1, 0.5), xycoords=an1,
xytext=(30,0), textcoords="offset points")
an2 = ax.annotate("Test 2", xy=(1, 0.5), xycoords=an1.get_window_extent,
xytext=(30,0), textcoords="offset points")
4. A tuple of two coordinate specifications. The first item is for the
x-coordinate and the second is for the y-coordinate. For example, ::
annotate("Test", xy=(0.5, 1), xycoords=("data", "axes fraction"))
0.5 is in data coordinates, and 1 is in normalized axes coordinates.
You may use an artist or transform as with a tuple. For example,
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_simple_coord02_001.png
:target: ../../gallery/userdemo/annotate_simple_coord02.html
:align: center
:scale: 50
Annotation with Simple Coordinates 2
5. Sometimes, you want your annotation with some "offset points", not from the
annotated point but from some other point.
:class:`~matplotlib.text.OffsetFrom` is a helper class for such cases.
.. figure:: ../../gallery/userdemo/images/sphx_glr_annotate_simple_coord03_001.png
:target: ../../gallery/userdemo/annotate_simple_coord03.html
:align: center
:scale: 50
Annotation with Simple Coordinates 3
You may take a look at this example
:ref:`sphx_glr_gallery_text_labels_and_annotations_annotation_demo.py`.
Using ConnectorPatch
--------------------
The ConnectorPatch is like an annotation without text. While the annotate
function is recommended in most situations, the ConnectorPatch is useful when
you want to connect points in different axes. ::
from matplotlib.patches import ConnectionPatch
xy = (0.2, 0.2)
con = ConnectionPatch(xyA=xy, xyB=xy, coordsA="data", coordsB="data",
axesA=ax1, axesB=ax2)
ax2.add_artist(con)
The above code connects point xy in the data coordinates of ``ax1`` to
point xy in the data coordinates of ``ax2``. Here is a simple example.
.. figure:: ../../gallery/userdemo/images/sphx_glr_connect_simple01_001.png
:target: ../../gallery/userdemo/connect_simple01.html
:align: center
:scale: 50
Connect Simple01
While the ConnectorPatch instance can be added to any axes, you may want to add
it to the axes that is latest in drawing order to prevent overlap by other
axes.
Advanced Topics
~~~~~~~~~~~~~~~
Zoom effect between Axes
------------------------
``mpl_toolkits.axes_grid1.inset_locator`` defines some patch classes useful
for interconnecting two axes. Understanding the code requires some
knowledge of how mpl's transform works. But, utilizing it will be
straight forward.
.. figure:: ../../gallery/pylab_examples/images/sphx_glr_axes_zoom_effect_001.png
:target: ../../gallery/pylab_examples/axes_zoom_effect.html
:align: center
:scale: 50
Axes Zoom Effect
Define Custom BoxStyle
----------------------
You can use a custom box style. The value for the ``boxstyle`` can be a
callable object in the following forms.::
def __call__(self, x0, y0, width, height, mutation_size,
aspect_ratio=1.):
'''
Given the location and size of the box, return the path of
the box around it.
- *x0*, *y0*, *width*, *height* : location and size of the box
- *mutation_size* : a reference scale for the mutation.
- *aspect_ratio* : aspect-ratio for the mutation.
'''
path = ...
return path
Here is a complete example.
.. figure:: ../../gallery/userdemo/images/sphx_glr_custom_boxstyle01_001.png
:target: ../../gallery/userdemo/custom_boxstyle01.html
:align: center
:scale: 50
Custom Boxstyle01
However, it is recommended that you derive from the
matplotlib.patches.BoxStyle._Base as demonstrated below.
.. figure:: ../../gallery/userdemo/images/sphx_glr_custom_boxstyle02_001.png
:target: ../../gallery/userdemo/custom_boxstyle02.html
:align: center
:scale: 50
Custom Boxstyle02
Similarly, you can define a custom ConnectionStyle and a custom ArrowStyle.
See the source code of ``lib/matplotlib/patches.py`` and check
how each style class is defined.
"""
PK#Jb}UUtext/usetex.py"""
*************************
Text rendering With LaTeX
*************************
Rendering text with LaTeX in Matplotlib.
Matplotlib has the option to use LaTeX to manage all text layout. This
option is available with the following backends:
* Agg
* PS
* PDF
The LaTeX option is activated by setting ``text.usetex : True`` in
your rc settings. Text handling with matplotlib's LaTeX support is
slower than matplotlib's very capable :ref:`mathtext
`, but is more flexible, since different LaTeX
packages (font packages, math packages, etc.) can be used. The
results can be striking, especially when you take care to use the same
fonts in your figures as in the main document.
Matplotlib's LaTeX support requires a working LaTeX_ installation, dvipng_
(which may be included with your LaTeX installation), and Ghostscript_
(GPL Ghostscript 8.60 or later is recommended). The executables for these
external dependencies must all be located on your :envvar:`PATH`.
There are a couple of options to mention, which can be changed using :ref:`rc
settings `. Here is an example matplotlibrc file::
font.family : serif
font.serif : Times, Palatino, New Century Schoolbook, Bookman, Computer Modern Roman
font.sans-serif : Helvetica, Avant Garde, Computer Modern Sans serif
font.cursive : Zapf Chancery
font.monospace : Courier, Computer Modern Typewriter
text.usetex : true
The first valid font in each family is the one that will be loaded. If the
fonts are not specified, the Computer Modern fonts are used by default. All of
the other fonts are Adobe fonts. Times and Palatino each have their own
accompanying math fonts, while the other Adobe serif fonts make use of the
Computer Modern math fonts. See the PSNFSS_ documentation for more details.
To use LaTeX and select Helvetica as the default font, without editing
matplotlibrc use::
from matplotlib import rc
rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
## for Palatino and other serif fonts use:
#rc('font',**{'family':'serif','serif':['Palatino']})
rc('text', usetex=True)
Here is the standard example, `tex_demo.py`:
.. figure:: ../../gallery/text_labels_and_annotations/images/sphx_glr_tex_demo_001.png
:target: ../../gallery/text_labels_and_annotations/tex_demo.html
:align: center
:scale: 50
TeX Demo
Note that display math mode (``$$ e=mc^2 $$``) is not supported, but adding the
command ``\displaystyle``, as in `tex_demo.py`, will produce the same
results.
.. note::
Certain characters require special escaping in TeX, such as::
# $ % & ~ _ ^ \ { } \( \) \[ \]
Therefore, these characters will behave differently depending on
the rcParam ``text.usetex`` flag.
.. _usetex-unicode:
usetex with unicode
===================
It is also possible to use unicode strings with the LaTeX text manager, here is
an example taken from `tex_demo.py`. The axis labels include Unicode text:
.. figure:: ../../gallery/text_labels_and_annotations/images/sphx_glr_tex_demo_001.png
:target: ../../gallery/text_labels_and_annotations/tex_demo.html
:align: center
:scale: 50
TeX Unicode Demo
.. _usetex-postscript:
Postscript options
==================
In order to produce encapsulated postscript files that can be embedded in a new
LaTeX document, the default behavior of matplotlib is to distill the output,
which removes some postscript operators used by LaTeX that are illegal in an
eps file. This step produces results which may be unacceptable to some users,
because the text is coarsely rasterized and converted to bitmaps, which are not
scalable like standard postscript, and the text is not searchable. One
workaround is to set ``ps.distiller.res`` to a higher value (perhaps 6000)
in your rc settings, which will produce larger files but may look better and
scale reasonably. A better workaround, which requires Poppler_ or Xpdf_, can be
activated by changing the ``ps.usedistiller`` rc setting to ``xpdf``. This
alternative produces postscript without rasterizing text, so it scales
properly, can be edited in Adobe Illustrator, and searched text in pdf
documents.
.. _usetex-hangups:
Possible hangups
================
* On Windows, the :envvar:`PATH` environment variable may need to be modified
to include the directories containing the latex, dvipng and ghostscript
executables. See :ref:`environment-variables` and
:ref:`setting-windows-environment-variables` for details.
* Using MiKTeX with Computer Modern fonts, if you get odd \*Agg and PNG
results, go to MiKTeX/Options and update your format files
* On Ubuntu and Gentoo, the base texlive install does not ship with
the type1cm package. You may need to install some of the extra
packages to get all the goodies that come bundled with other latex
distributions.
* Some progress has been made so matplotlib uses the dvi files
directly for text layout. This allows latex to be used for text
layout with the pdf and svg backends, as well as the \*Agg and PS
backends. In the future, a latex installation may be the only
external dependency.
.. _usetex-troubleshooting:
Troubleshooting
===============
* Try deleting your :file:`.matplotlib/tex.cache` directory. If you don't know
where to find :file:`.matplotlib`, see :ref:`locating-matplotlib-config-dir`.
* Make sure LaTeX, dvipng and ghostscript are each working and on your
:envvar:`PATH`.
* Make sure what you are trying to do is possible in a LaTeX document,
that your LaTeX syntax is valid and that you are using raw strings
if necessary to avoid unintended escape sequences.
* Most problems reported on the mailing list have been cleared up by
upgrading Ghostscript_. If possible, please try upgrading to the
latest release before reporting problems to the list.
* The ``text.latex.preamble`` rc setting is not officially supported. This
option provides lots of flexibility, and lots of ways to cause
problems. Please disable this option before reporting problems to
the mailing list.
* If you still need help, please see :ref:`reporting-problems`
.. _LaTeX: http://www.tug.org
.. _dvipng: http://www.nongnu.org/dvipng/
.. _Ghostscript: https://ghostscript.com/
.. _PSNFSS: http://www.ctan.org/tex-archive/macros/latex/required/psnfss/psnfss2e.pdf
.. _Poppler: https://poppler.freedesktop.org/
.. _Xpdf: http://www.foolabs.com/xpdf
"""
PK#JFRt\++text/text_props.py"""
============================
Text properties and layout
============================
Controlling properties of text and its layout with Matplotlib.
The :class:`matplotlib.text.Text` instances have a variety of
properties which can be configured via keyword arguments to the text
commands (e.g., :func:`~matplotlib.pyplot.title`,
:func:`~matplotlib.pyplot.xlabel` and :func:`~matplotlib.pyplot.text`).
========================== ======================================================================================================================
Property Value Type
========================== ======================================================================================================================
alpha `float`
backgroundcolor any matplotlib :ref:`color `
bbox `~matplotlib.patches.Rectangle` prop dict plus key ``'pad'`` which is a pad in points
clip_box a matplotlib.transform.Bbox instance
clip_on [True | False]
clip_path a `~matplotlib.path.Path` instance and a `~matplotlib.transforms.Transform` instance, a `~matplotlib.patches.Patch`
color any matplotlib :ref:`color `
family [ ``'serif'`` | ``'sans-serif'`` | ``'cursive'`` | ``'fantasy'`` | ``'monospace'`` ]
fontproperties a `~matplotlib.font_manager.FontProperties` instance
horizontalalignment or ha [ ``'center'`` | ``'right'`` | ``'left'`` ]
label any string
linespacing `float`
multialignment [``'left'`` | ``'right'`` | ``'center'`` ]
name or fontname string e.g., [``'Sans'`` | ``'Courier'`` | ``'Helvetica'`` ...]
picker [None|float|boolean|callable]
position (x, y)
rotation [ angle in degrees | ``'vertical'`` | ``'horizontal'`` ]
size or fontsize [ size in points | relative size, e.g., ``'smaller'``, ``'x-large'`` ]
style or fontstyle [ ``'normal'`` | ``'italic'`` | ``'oblique'`` ]
text string or anything printable with '%s' conversion
transform a `~matplotlib.transforms.Transform` instance
variant [ ``'normal'`` | ``'small-caps'`` ]
verticalalignment or va [ ``'center'`` | ``'top'`` | ``'bottom'`` | ``'baseline'`` ]
visible [True | False]
weight or fontweight [ ``'normal'`` | ``'bold'`` | ``'heavy'`` | ``'light'`` | ``'ultrabold'`` | ``'ultralight'``]
x `float`
y `float`
zorder any number
========================== ======================================================================================================================
You can lay out text with the alignment arguments
``horizontalalignment``, ``verticalalignment``, and
``multialignment``. ``horizontalalignment`` controls whether the x
positional argument for the text indicates the left, center or right
side of the text bounding box. ``verticalalignment`` controls whether
the y positional argument for the text indicates the bottom, center or
top side of the text bounding box. ``multialignment``, for newline
separated strings only, controls whether the different lines are left,
center or right justified. Here is an example which uses the
:func:`~matplotlib.pyplot.text` command to show the various alignment
possibilities. The use of ``transform=ax.transAxes`` throughout the
code indicates that the coordinates are given relative to the axes
bounding box, with 0,0 being the lower left of the axes and 1,1 the
upper right.
"""
import matplotlib.pyplot as plt
import matplotlib.patches as patches
# build a rectangle in axes coords
left, width = .25, .5
bottom, height = .25, .5
right = left + width
top = bottom + height
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
# axes coordinates are 0,0 is bottom left and 1,1 is upper right
p = patches.Rectangle(
(left, bottom), width, height,
fill=False, transform=ax.transAxes, clip_on=False
)
ax.add_patch(p)
ax.text(left, bottom, 'left top',
horizontalalignment='left',
verticalalignment='top',
transform=ax.transAxes)
ax.text(left, bottom, 'left bottom',
horizontalalignment='left',
verticalalignment='bottom',
transform=ax.transAxes)
ax.text(right, top, 'right bottom',
horizontalalignment='right',
verticalalignment='bottom',
transform=ax.transAxes)
ax.text(right, top, 'right top',
horizontalalignment='right',
verticalalignment='top',
transform=ax.transAxes)
ax.text(right, bottom, 'center top',
horizontalalignment='center',
verticalalignment='top',
transform=ax.transAxes)
ax.text(left, 0.5*(bottom+top), 'right center',
horizontalalignment='right',
verticalalignment='center',
rotation='vertical',
transform=ax.transAxes)
ax.text(left, 0.5*(bottom+top), 'left center',
horizontalalignment='left',
verticalalignment='center',
rotation='vertical',
transform=ax.transAxes)
ax.text(0.5*(left+right), 0.5*(bottom+top), 'middle',
horizontalalignment='center',
verticalalignment='center',
fontsize=20, color='red',
transform=ax.transAxes)
ax.text(right, 0.5*(bottom+top), 'centered',
horizontalalignment='center',
verticalalignment='center',
rotation='vertical',
transform=ax.transAxes)
ax.text(left, top, 'rotated\nwith newlines',
horizontalalignment='center',
verticalalignment='center',
rotation=45,
transform=ax.transAxes)
ax.set_axis_off()
plt.show()
###############################################################################
# ==============
# Default Font
# ==============
#
# The base default font is controlled by a set of rcParams. To set the font
# for mathematical expressions, use the rcParams beginning with ``mathtext``
# (see :ref:`mathtext `).
#
# +---------------------+----------------------------------------------------+
# | rcParam | usage |
# +=====================+====================================================+
# | ``'font.family'`` | List of either names of font or ``{'cursive', |
# | | 'fantasy', 'monospace', 'sans', 'sans serif', |
# | | 'sans-serif', 'serif'}``. |
# | | |
# +---------------------+----------------------------------------------------+
# | ``'font.style'`` | The default style, ex ``'normal'``, |
# | | ``'italic'``. |
# | | |
# +---------------------+----------------------------------------------------+
# | ``'font.variant'`` | Default variant, ex ``'normal'``, ``'small-caps'`` |
# | | (untested) |
# +---------------------+----------------------------------------------------+
# | ``'font.stretch'`` | Default stretch, ex ``'normal'``, ``'condensed'`` |
# | | (incomplete) |
# | | |
# +---------------------+----------------------------------------------------+
# | ``'font.weight'`` | Default weight. Either string or integer |
# | | |
# | | |
# +---------------------+----------------------------------------------------+
# | ``'font.size'`` | Default font size in points. Relative font sizes |
# | | (``'large'``, ``'x-small'``) are computed against |
# | | this size. |
# +---------------------+----------------------------------------------------+
#
# The mapping between the family aliases (``{'cursive', 'fantasy',
# 'monospace', 'sans', 'sans serif', 'sans-serif', 'serif'}``) and actual font names
# is controlled by the following rcParams:
#
#
# +------------------------------------------+--------------------------------+
# | family alias | rcParam with mappings |
# +==========================================+================================+
# | ``'serif'`` | ``'font.serif'`` |
# +------------------------------------------+--------------------------------+
# | ``'monospace'`` | ``'font.monospace'`` |
# +------------------------------------------+--------------------------------+
# | ``'fantasy'`` | ``'font.fantasy'`` |
# +------------------------------------------+--------------------------------+
# | ``'cursive'`` | ``'font.cursive'`` |
# +------------------------------------------+--------------------------------+
# | ``{'sans', 'sans serif', 'sans-serif'}`` | ``'font.sans-serif'`` |
# +------------------------------------------+--------------------------------+
#
#
# which are lists of font names.
#
# Text with non-latin glyphs
# ==========================
#
# As of v2.0 the :ref:`default font ` contains
# glyphs for many western alphabets, but still does not cover all of the
# glyphs that may be required by mpl users. For example, DejaVu has no
# coverage of Chinese, Korean, or Japanese.
#
#
# To set the default font to be one that supports the code points you
# need, prepend the font name to ``'font.family'`` or the desired alias
# lists ::
#
# matplotlib.rcParams['font.sans-serif'] = ['Source Han Sans TW', 'sans-serif']
#
# or set it in your :file:`.matplotlibrc` file::
#
# font.sans-serif: Source Han Sans TW, Arial, sans-serif
#
# To control the font used on per-artist basis use the ``'name'``,
# ``'fontname'`` or ``'fontproperties'`` kwargs documented :ref:`above
# `.
#
#
# On linux, `fc-list `__ can be a
# useful tool to discover the font name; for example ::
#
# $ fc-list :lang=zh family
# Noto to Sans Mono CJK TC,Noto Sans Mono CJK TC Bold
# Noto Sans CJK TC,Noto Sans CJK TC Medium
# Noto Sans CJK TC,Noto Sans CJK TC DemiLight
# Noto Sans CJK KR,Noto Sans CJK KR Black
# Noto Sans CJK TC,Noto Sans CJK TC Black
# Noto Sans Mono CJK TC,Noto Sans Mono CJK TC Regular
# Noto Sans CJK SC,Noto Sans CJK SC Light
#
# lists all of the fonts that support Chinese.
#
PK#Jq@ZU
text/text_intro.py"""
Text introduction
=================
Introduction to plotting and working with text in Matplotlib.
Matplotlib has extensive text support, including support for
mathematical expressions, truetype support for raster and
vector outputs, newline separated text with arbitrary
rotations, and unicode support.
Because it embeds fonts directly in output documents, e.g., for postscript
or PDF, what you see on the screen is what you get in the hardcopy.
`FreeType `_ support
produces very nice, antialiased fonts, that look good even at small
raster sizes. matplotlib includes its own
:mod:`matplotlib.font_manager` (thanks to Paul Barrett), which
implements a cross platform, `W3C `
compliant font finding algorithm.
The user has a great deal of control over text properties (font size, font
weight, text location and color, etc.) with sensible defaults set in
the `rc file `.
And significantly, for those interested in mathematical
or scientific figures, matplotlib implements a large number of TeX
math symbols and commands, supporting :ref:`mathematical expressions
` anywhere in your figure.
Basic text commands
===================
The following commands are used to create text in the pyplot
interface
* :func:`~matplotlib.pyplot.text` - add text at an arbitrary location to the ``Axes``;
:meth:`matplotlib.axes.Axes.text` in the API.
* :func:`~matplotlib.pyplot.xlabel` - add a label to the x-axis;
:meth:`matplotlib.axes.Axes.set_xlabel` in the API.
* :func:`~matplotlib.pyplot.ylabel` - add a label to the y-axis;
:meth:`matplotlib.axes.Axes.set_ylabel` in the API.
* :func:`~matplotlib.pyplot.title` - add a title to the ``Axes``;
:meth:`matplotlib.axes.Axes.set_title` in the API.
* :func:`~matplotlib.pyplot.figtext` - add text at an arbitrary location to the ``Figure``;
:meth:`matplotlib.figure.Figure.text` in the API.
* :func:`~matplotlib.pyplot.suptitle` - add a title to the ``Figure``;
:meth:`matplotlib.figure.Figure.suptitle` in the API.
* :func:`~matplotlib.pyplot.annotate` - add an annotation, with
optional arrow, to the ``Axes`` ; :meth:`matplotlib.axes.Axes.annotate`
in the API.
All of these functions create and return a
:func:`matplotlib.text.Text` instance, which can be configured with a
variety of font and other properties. The example below shows all of
these commands in action.
"""
import matplotlib.pyplot as plt
fig = plt.figure()
fig.suptitle('bold figure suptitle', fontsize=14, fontweight='bold')
ax = fig.add_subplot(111)
fig.subplots_adjust(top=0.85)
ax.set_title('axes title')
ax.set_xlabel('xlabel')
ax.set_ylabel('ylabel')
ax.text(3, 8, 'boxed italics text in data coords', style='italic',
bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})
ax.text(2, 6, r'an equation: $E=mc^2$', fontsize=15)
ax.text(3, 2, u'unicode: Institut f\374r Festk\366rperphysik')
ax.text(0.95, 0.01, 'colored text in axes coords',
verticalalignment='bottom', horizontalalignment='right',
transform=ax.transAxes,
color='green', fontsize=15)
ax.plot([2], [1], 'o')
ax.annotate('annotate', xy=(2, 1), xytext=(3, 4),
arrowprops=dict(facecolor='black', shrink=0.05))
ax.axis([0, 10, 0, 10])
plt.show()
PK#J@Ftoolkits/mplot3d.py"""
===================
The mplot3d Toolkit
===================
Generating 3D plots using the mplot3d toolkit.
.. currentmodule:: mpl_toolkits.mplot3d
.. contents::
:backlinks: none
.. _toolkit_mplot3d-tutorial:
Getting started
---------------
An Axes3D object is created just like any other axes using
the projection='3d' keyword.
Create a new :class:`matplotlib.figure.Figure` and
add a new axes to it of type :class:`~mpl_toolkits.mplot3d.Axes3D`::
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
.. versionadded:: 1.0.0
This approach is the preferred method of creating a 3D axes.
.. note::
Prior to version 1.0.0, the method of creating a 3D axes was
different. For those using older versions of matplotlib, change
``ax = fig.add_subplot(111, projection='3d')``
to ``ax = Axes3D(fig)``.
See the :ref:`toolkit_mplot3d-faq` for more information about the mplot3d
toolkit.
.. _plot3d:
Line plots
====================
.. automethod:: Axes3D.plot
.. figure:: ../../gallery/mplot3d/images/sphx_glr_lines3d_001.png
:target: ../../gallery/mplot3d/lines3d.html
:align: center
:scale: 50
Lines3d
.. _scatter3d:
Scatter plots
=============
.. automethod:: Axes3D.scatter
.. figure:: ../../gallery/mplot3d/images/sphx_glr_scatter3d_001.png
:target: ../../gallery/mplot3d/scatter3d.html
:align: center
:scale: 50
Scatter3d
.. _wireframe:
Wireframe plots
===============
.. automethod:: Axes3D.plot_wireframe
.. figure:: ../../gallery/mplot3d/images/sphx_glr_wire3d_001.png
:target: ../../gallery/mplot3d/wire3d.html
:align: center
:scale: 50
Wire3d
.. _surface:
Surface plots
=============
.. automethod:: Axes3D.plot_surface
.. figure:: ../../gallery/mplot3d/images/sphx_glr_surface3d_001.png
:target: ../../gallery/mplot3d/surface3d.html
:align: center
:scale: 50
Surface3d
Surface3d 2
Surface3d 3
.. _trisurface:
Tri-Surface plots
=================
.. automethod:: Axes3D.plot_trisurf
.. figure:: ../../gallery/mplot3d/images/sphx_glr_trisurf3d_001.png
:target: ../../gallery/mplot3d/trisurf3d.html
:align: center
:scale: 50
Trisurf3d
.. _contour3d:
Contour plots
=============
.. automethod:: Axes3D.contour
.. figure:: ../../gallery/mplot3d/images/sphx_glr_contour3d_001.png
:target: ../../gallery/mplot3d/contour3d.html
:align: center
:scale: 50
Contour3d
Contour3d 2
Contour3d 3
.. _contourf3d:
Filled contour plots
====================
.. automethod:: Axes3D.contourf
.. figure:: ../../gallery/mplot3d/images/sphx_glr_contourf3d_001.png
:target: ../../gallery/mplot3d/contourf3d.html
:align: center
:scale: 50
Contourf3d
Contourf3d 2
.. versionadded:: 1.1.0
The feature demoed in the second contourf3d example was enabled as a
result of a bugfix for version 1.1.0.
.. _polygon3d:
Polygon plots
====================
.. automethod:: Axes3D.add_collection3d
.. figure:: ../../gallery/mplot3d/images/sphx_glr_polys3d_001.png
:target: ../../gallery/mplot3d/polys3d.html
:align: center
:scale: 50
Polys3d
.. _bar3d:
Bar plots
====================
.. automethod:: Axes3D.bar
.. figure:: ../../gallery/mplot3d/images/sphx_glr_bars3d_001.png
:target: ../../gallery/mplot3d/bars3d.html
:align: center
:scale: 50
Bars3d
.. _quiver3d:
Quiver
====================
.. automethod:: Axes3D.quiver
.. figure:: ../../gallery/mplot3d/images/sphx_glr_quiver3d_001.png
:target: ../../gallery/mplot3d/quiver3d.html
:align: center
:scale: 50
Quiver3d
.. _2dcollections3d:
2D plots in 3D
====================
.. figure:: ../../gallery/mplot3d/images/sphx_glr_2dcollections3d_001.png
:target: ../../gallery/mplot3d/2dcollections3d.html
:align: center
:scale: 50
2dcollections3d
.. _text3d:
Text
====================
.. automethod:: Axes3D.text
.. figure:: ../../gallery/mplot3d/images/sphx_glr_text3d_001.png
:target: ../../gallery/mplot3d/text3d.html
:align: center
:scale: 50
Text3d
.. _3dsubplots:
Subplotting
====================
Having multiple 3D plots in a single figure is the same
as it is for 2D plots. Also, you can have both 2D and 3D plots
in the same figure.
.. versionadded:: 1.0.0
Subplotting 3D plots was added in v1.0.0. Earlier version can not
do this.
.. figure:: ../../gallery/mplot3d/images/sphx_glr_subplot3d_001.png
:target: ../../gallery/mplot3d/subplot3d.html
:align: center
:scale: 50
Subplot3d
Mixed Subplots
"""
PK#JyƬSStoolkits/axisartist.py"""
==============================
Overview of axisartist toolkit
==============================
The axisartist toolkit tutorial.
.. warning::
*axisartist* uses a custom Axes class
(derived from the mpl's original Axes class).
As a side effect, some commands (mostly tick-related) do not work.
The *axisartist* contains a custom Axes class that is meant to support
curvilinear grids (e.g., the world coordinate system in astronomy).
Unlike mpl's original Axes class which uses Axes.xaxis and Axes.yaxis
to draw ticks, ticklines, etc., axisartist uses a special
artist (AxisArtist) that can handle ticks, ticklines, etc. for
curved coordinate systems.
.. figure:: ../../gallery/axisartist/images/sphx_glr_demo_floating_axis_001.png
:target: ../../gallery/axisartist/demo_floating_axis.html
:align: center
:scale: 50
Demo Floating Axis
Since it uses special artists, some Matplotlib commands that work on
Axes.xaxis and Axes.yaxis may not work.
.. _axisartist_users-guide-index:
axisartist
==========
The *axisartist* module provides a custom (and very experimental) Axes
class, where each axis (left, right, top, and bottom) have a separate
associated artist which is responsible for drawing the axis-line, ticks,
ticklabels, and labels. You can also create your own axis, which can pass
through a fixed position in the axes coordinate, or a fixed position
in the data coordinate (i.e., the axis floats around when viewlimit
changes).
The axes class, by default, has its xaxis and yaxis invisible, and
has 4 additional artists which are responsible for drawing the 4 axis spines in
"left", "right", "bottom", and "top". They are accessed as
ax.axis["left"], ax.axis["right"], and so on, i.e., ax.axis is a
dictionary that contains artists (note that ax.axis is still a
callable method and it behaves as an original Axes.axis method in
Matplotlib).
To create an axes, ::
import mpl_toolkits.axisartist as AA
fig = plt.figure(1)
ax = AA.Axes(fig, [0.1, 0.1, 0.8, 0.8])
fig.add_axes(ax)
or to create a subplot ::
ax = AA.Subplot(fig, 111)
fig.add_subplot(ax)
For example, you can hide the right and top spines using::
ax.axis["right"].set_visible(False)
ax.axis["top"].set_visible(False)
.. figure:: ../../gallery/userdemo/images/sphx_glr_simple_axisline3_001.png
:target: ../../gallery/userdemo/simple_axisline3.html
:align: center
:scale: 50
Simple Axisline3
It is also possible to add a horizontal axis. For example, you may have an
horizontal axis at y=0 (in data coordinate). ::
ax.axis["y=0"] = ax.new_floating_axis(nth_coord=0, value=0)
.. figure:: ../../gallery/userdemo/images/sphx_glr_simple_axisartist1_001.png
:target: ../../gallery/userdemo/simple_axisartist1.html
:align: center
:scale: 50
Simple Axisartist1
Or a fixed axis with some offset ::
# make new (right-side) yaxis, but wth some offset
ax.axis["right2"] = ax.new_fixed_axis(loc="right",
offset=(20, 0))
axisartist with ParasiteAxes
----------------------------
Most commands in the axes_grid1 toolkit can take an axes_class keyword
argument, and the commands create an axes of the given class. For example,
to create a host subplot with axisartist.Axes, ::
import mpl_toolkits.axisartist as AA
from mpl_toolkits.axes_grid1 import host_subplot
host = host_subplot(111, axes_class=AA.Axes)
Here is an example that uses parasiteAxes.
.. figure:: ../../gallery/axisartist/images/sphx_glr_demo_parasite_axes2_001.png
:target: ../../gallery/axisartist/demo_parasite_axes2.html
:align: center
:scale: 50
Demo Parasite Axes2
Curvilinear Grid
----------------
The motivation behind the AxisArtist module is to support a curvilinear grid
and ticks.
.. figure:: ../../gallery/axisartist/images/sphx_glr_demo_curvelinear_grid_001.png
:target: ../../gallery/axisartist/demo_curvelinear_grid.html
:align: center
:scale: 50
Demo Curvelinear Grid
Floating Axes
-------------
AxisArtist also supports a Floating Axes whose outer axes are defined as
floating axis.
.. figure:: ../../gallery/axisartist/images/sphx_glr_demo_floating_axes_001.png
:target: ../../gallery/axisartist/demo_floating_axes.html
:align: center
:scale: 50
Demo Floating Axes
axisartist namespace
====================
The *axisartist* namespace includes a derived Axes implementation. The
biggest difference is that the artists responsible to draw axis line,
ticks, ticklabel and axis labels are separated out from the mpl's Axis
class, which are much more than artists in the original mpl. This
change was strongly motivated to support curvilinear grid. Here are a
few things that mpl_tootlkits.axisartist.Axes is different from original
Axes from mpl.
* Axis elements (axis line(spine), ticks, ticklabel and axis labels)
are drawn by a AxisArtist instance. Unlike Axis, left, right, top
and bottom axis are drawn by separate artists. And each of them may
have different tick location and different tick labels.
* gridlines are drawn by a Gridlines instance. The change was
motivated that in curvilinear coordinate, a gridline may not cross
axis-lines (i.e., no associated ticks). In the original Axes class,
gridlines are tied to ticks.
* ticklines can be rotated if necessary (i.e, along the gridlines)
In summary, all these changes was to support
* a curvilinear grid.
* a floating axis
.. figure:: ../../gallery/axisartist/images/sphx_glr_demo_floating_axis_001.png
:target: ../../gallery/axisartist/demo_floating_axis.html
:align: center
:scale: 50
Demo Floating Axis
*mpl_toolkits.axisartist.Axes* class defines a *axis* attribute, which
is a dictionary of AxisArtist instances. By default, the dictionary
has 4 AxisArtist instances, responsible for drawing of left, right,
bottom and top axis.
xaxis and yaxis attributes are still available, however they are set
to not visible. As separate artists are used for rendering axis, some
axis-related method in mpl may have no effect.
In addition to AxisArtist instances, the mpl_toolkits.axisartist.Axes will
have *gridlines* attribute (Gridlines), which obviously draws grid
lines.
In both AxisArtist and Gridlines, the calculation of tick and grid
location is delegated to an instance of GridHelper class.
mpl_toolkits.axisartist.Axes class uses GridHelperRectlinear as a grid
helper. The GridHelperRectlinear class is a wrapper around the *xaxis*
and *yaxis* of mpl's original Axes, and it was meant to work as the
way how mpl's original axes works. For example, tick location changes
using set_ticks method and etc. should work as expected. But change in
artist properties (e.g., color) will not work in general, although
some effort has been made so that some often-change attributes (color,
etc.) are respected.
AxisArtist
==========
AxisArtist can be considered as a container artist with following
attributes which will draw ticks, labels, etc.
* line
* major_ticks, major_ticklabels
* minor_ticks, minor_ticklabels
* offsetText
* label
line
----
Derived from Line2d class. Responsible for drawing a spinal(?) line.
major_ticks, minor_ticks
------------------------
Derived from Line2d class. Note that ticks are markers.
major_ticklabels, minor_ticklabels
----------------------------------
Derived from Text. Note that it is not a list of Text artist, but a
single artist (similar to a collection).
axislabel
---------
Derived from Text.
Default AxisArtists
===================
By default, following for axis artists are defined.::
ax.axis["left"], ax.axis["bottom"], ax.axis["right"], ax.axis["top"]
The ticklabels and axislabel of the top and the right axis are set to
not visible.
For example, if you want to change the color attributes of
major_ticklabels of the bottom x-axis ::
ax.axis["bottom"].major_ticklabels.set_color("b")
Similarly, to make ticklabels invisible ::
ax.axis["bottom"].major_ticklabels.set_visible(False)
AxisAritst provides a helper method to control the visibility of ticks,
ticklabels, and label. To make ticklabel invisible, ::
ax.axis["bottom"].toggle(ticklabels=False)
To make all of ticks, ticklabels, and (axis) label invisible ::
ax.axis["bottom"].toggle(all=False)
To turn all off but ticks on ::
ax.axis["bottom"].toggle(all=False, ticks=True)
To turn all on but (axis) label off ::
ax.axis["bottom"].toggle(all=True, label=False))
ax.axis's __getitem__ method can take multiple axis names. For
example, to turn ticklabels of "top" and "right" axis on, ::
ax.axis["top","right"].toggle(ticklabels=True))
Note that 'ax.axis["top","right"]' returns a simple proxy object that translate above code to something like below. ::
for n in ["top","right"]:
ax.axis[n].toggle(ticklabels=True))
So, any return values in the for loop are ignored. And you should not
use it anything more than a simple method.
Like the list indexing ":" means all items, i.e., ::
ax.axis[:].major_ticks.set_color("r")
changes tick color in all axis.
HowTo
=====
1. Changing tick locations and label.
Same as the original mpl's axes.::
ax.set_xticks([1,2,3])
2. Changing axis properties like color, etc.
Change the properties of appropriate artists. For example, to change
the color of the ticklabels::
ax.axis["left"].major_ticklabels.set_color("r")
3. To change the attributes of multiple axis::
ax.axis["left","bottom"].major_ticklabels.set_color("r")
or to change the attributes of all axis::
ax.axis[:].major_ticklabels.set_color("r")
4. To change the tick size (length), you need to use
axis.major_ticks.set_ticksize method. To change the direction of
the ticks (ticks are in opposite direction of ticklabels by
default), use axis.major_ticks.set_tick_out method.
To change the pad between ticks and ticklabels, use
axis.major_ticklabels.set_pad method.
To change the pad between ticklabels and axis label,
axis.label.set_pad method.
Rotation and Alignment of TickLabels
====================================
This is also quite different from the original mpl and can be
confusing. When you want to rotate the ticklabels, first consider
using "set_axis_direction" method. ::
ax1.axis["left"].major_ticklabels.set_axis_direction("top")
ax1.axis["right"].label.set_axis_direction("left")
.. figure:: ../../gallery/userdemo/images/sphx_glr_simple_axis_direction01_001.png
:target: ../../gallery/userdemo/simple_axis_direction01.html
:align: center
:scale: 50
Simple Axis Direction01
The parameter for set_axis_direction is one of ["left", "right",
"bottom", "top"].
You must understand some underlying concept of directions.
1. There is a reference direction which is defined as the direction
of the axis line with increasing coordinate. For example, the
reference direction of the left x-axis is from bottom to top.
.. figure:: ../../gallery/userdemo/images/sphx_glr_axis_direction_demo_step01_001.png
:target: ../../gallery/userdemo/axis_direction_demo_step01.html
:align: center
:scale: 50
Axis Direction Demo - Step 01
The direction, text angle, and alignments of the ticks, ticklabels and
axis-label is determined with respect to the reference direction
2. *ticklabel_direction* is either the right-hand side (+) of the
reference direction or the left-hand side (-).
.. figure:: ../../gallery/userdemo/images/sphx_glr_axis_direction_demo_step02_001.png
:target: ../../gallery/userdemo/axis_direction_demo_step02.html
:align: center
:scale: 50
Axis Direction Demo - Step 02
3. same for the *label_direction*
.. figure:: ../../gallery/userdemo/images/sphx_glr_axis_direction_demo_step03_001.png
:target: ../../gallery/userdemo/axis_direction_demo_step03.html
:align: center
:scale: 50
Axis Direction Demo - Step 03
4. ticks are by default drawn toward the opposite direction of the ticklabels.
5. text rotation of ticklabels and label is determined in reference
to the *ticklabel_direction* or *label_direction*,
respectively. The rotation of ticklabels and label is anchored.
.. figure:: ../../gallery/userdemo/images/sphx_glr_axis_direction_demo_step04_001.png
:target: ../../gallery/userdemo/axis_direction_demo_step04.html
:align: center
:scale: 50
Axis Direction Demo - Step 04
On the other hand, there is a concept of "axis_direction". This is a
default setting of above properties for each, "bottom", "left", "top",
and "right" axis.
========== =========== ========= ========== ========= ==========
? ? left bottom right top
---------- ----------- --------- ---------- --------- ----------
axislabel direction '-' '+' '+' '-'
axislabel rotation 180 0 0 180
axislabel va center top center bottom
axislabel ha right center right center
ticklabel direction '-' '+' '+' '-'
ticklabels rotation 90 0 -90 180
ticklabel ha right center right center
ticklabel va center baseline center baseline
========== =========== ========= ========== ========= ==========
And, 'set_axis_direction("top")' means to adjust the text rotation
etc, for settings suitable for "top" axis. The concept of axis
direction can be more clear with curved axis.
.. figure:: ../../gallery/userdemo/images/sphx_glr_demo_axis_direction_001.png
:target: ../../gallery/userdemo/demo_axis_direction.html
:align: center
:scale: 50
Demo Axis Direction
The axis_direction can be adjusted in the AxisArtist level, or in the
level of its child arists, i.e., ticks, ticklabels, and axis-label. ::
ax1.axis["left"].set_axis_direction("top")
changes axis_direction of all the associated artist with the "left"
axis, while ::
ax1.axis["left"].major_ticklabels.set_axis_direction("top")
changes the axis_direction of only the major_ticklabels. Note that
set_axis_direction in the AxisArtist level changes the
ticklabel_direction and label_direction, while changing the
axis_direction of ticks, ticklabels, and axis-label does not affect
them.
If you want to make ticks outward and ticklabels inside the axes,
use invert_ticklabel_direction method. ::
ax.axis[:].invert_ticklabel_direction()
A related method is "set_tick_out". It makes ticks outward (as a
matter of fact, it makes ticks toward the opposite direction of the
default direction). ::
ax.axis[:].major_ticks.set_tick_out(True)
.. figure:: ../../gallery/userdemo/images/sphx_glr_simple_axis_direction03_001.png
:target: ../../gallery/userdemo/simple_axis_direction03.html
:align: center
:scale: 50
Simple Axis Direction03
So, in summary,
* AxisArtist's methods
* set_axis_direction : "left", "right", "bottom", or "top"
* set_ticklabel_direction : "+" or "-"
* set_axislabel_direction : "+" or "-"
* invert_ticklabel_direction
* Ticks' methods (major_ticks and minor_ticks)
* set_tick_out : True or False
* set_ticksize : size in points
* TickLabels' methods (major_ticklabels and minor_ticklabels)
* set_axis_direction : "left", "right", "bottom", or "top"
* set_rotation : angle with respect to the reference direction
* set_ha and set_va : see below
* AxisLabels' methods (label)
* set_axis_direction : "left", "right", "bottom", or "top"
* set_rotation : angle with respect to the reference direction
* set_ha and set_va
Adjusting ticklabels alignment
------------------------------
Alignment of TickLabels are treated specially. See below
.. figure:: ../../gallery/userdemo/images/sphx_glr_demo_ticklabel_alignment_001.png
:target: ../../gallery/userdemo/demo_ticklabel_alignment.html
:align: center
:scale: 50
Demo Ticklabel Alignment
Adjusting pad
--------------
To change the pad between ticks and ticklabels ::
ax.axis["left"].major_ticklabels.set_pad(10)
Or ticklabels and axis-label ::
ax.axis["left"].label.set_pad(10)
.. figure:: ../../gallery/userdemo/images/sphx_glr_simple_axis_pad_001.png
:target: ../../gallery/userdemo/simple_axis_pad.html
:align: center
:scale: 50
Simple Axis Pad
GridHelper
==========
To actually define a curvilinear coordinate, you have to use your own
grid helper. A generalised version of grid helper class is supplied
and this class should suffice in most of cases. A user may provide
two functions which defines a transformation (and its inverse pair)
from the curved coordinate to (rectilinear) image coordinate. Note that
while ticks and grids are drawn for curved coordinate, the data
transform of the axes itself (ax.transData) is still rectilinear
(image) coordinate. ::
from mpl_toolkits.axisartist.grid_helper_curvelinear \
import GridHelperCurveLinear
from mpl_toolkits.axisartist import Subplot
# from curved coordinate to rectlinear coordinate.
def tr(x, y):
x, y = np.asarray(x), np.asarray(y)
return x, y-x
# from rectlinear coordinate to curved coordinate.
def inv_tr(x,y):
x, y = np.asarray(x), np.asarray(y)
return x, y+x
grid_helper = GridHelperCurveLinear((tr, inv_tr))
ax1 = Subplot(fig, 1, 1, 1, grid_helper=grid_helper)
fig.add_subplot(ax1)
You may use matplotlib's Transform instance instead (but a
inverse transformation must be defined). Often, coordinate range in a
curved coordinate system may have a limited range, or may have
cycles. In those cases, a more customized version of grid helper is
required. ::
import mpl_toolkits.axisartist.angle_helper as angle_helper
# PolarAxes.PolarTransform takes radian. However, we want our coordinate
# system in degree
tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform()
# extreme finder : find a range of coordinate.
# 20, 20 : number of sampling points along x, y direction
# The first coordinate (longitude, but theta in polar)
# has a cycle of 360 degree.
# The second coordinate (latitude, but radius in polar) has a minimum of 0
extreme_finder = angle_helper.ExtremeFinderCycle(20, 20,
lon_cycle = 360,
lat_cycle = None,
lon_minmax = None,
lat_minmax = (0, np.inf),
)
# Find a grid values appropriate for the coordinate (degree,
# minute, second). The argument is a approximate number of grids.
grid_locator1 = angle_helper.LocatorDMS(12)
# And also uses an appropriate formatter. Note that,the
# acceptable Locator and Formatter class is a bit different than
# that of mpl's, and you cannot directly use mpl's Locator and
# Formatter here (but may be possible in the future).
tick_formatter1 = angle_helper.FormatterDMS()
grid_helper = GridHelperCurveLinear(tr,
extreme_finder=extreme_finder,
grid_locator1=grid_locator1,
tick_formatter1=tick_formatter1
)
Again, the *transData* of the axes is still a rectilinear coordinate
(image coordinate). You may manually do conversion between two
coordinates, or you may use Parasite Axes for convenience.::
ax1 = SubplotHost(fig, 1, 2, 2, grid_helper=grid_helper)
# A parasite axes with given transform
ax2 = ParasiteAxesAuxTrans(ax1, tr, "equal")
# note that ax2.transData == tr + ax1.transData
# Anthing you draw in ax2 will match the ticks and grids of ax1.
ax1.parasites.append(ax2)
.. figure:: ../../gallery/axisartist/images/sphx_glr_demo_curvelinear_grid_001.png
:target: ../../gallery/axisartist/demo_curvelinear_grid.html
:align: center
:scale: 50
Demo Curvelinear Grid
FloatingAxis
============
A floating axis is an axis one of whose data coordinate is fixed, i.e,
its location is not fixed in Axes coordinate but changes as axes data
limits changes. A floating axis can be created using
*new_floating_axis* method. However, it is your responsibility that
the resulting AxisArtist is properly added to the axes. A recommended
way is to add it as an item of Axes's axis attribute.::
# floating axis whose first (index starts from 0) coordinate
# (theta) is fixed at 60
ax1.axis["lat"] = axis = ax1.new_floating_axis(0, 60)
axis.label.set_text(r"$\theta = 60^{\circ}$")
axis.label.set_visible(True)
See the first example of this page.
Current Limitations and TODO's
==============================
The code need more refinement. Here is a incomplete list of issues and TODO's
* No easy way to support a user customized tick location (for
curvilinear grid). A new Locator class needs to be created.
* FloatingAxis may have coordinate limits, e.g., a floating axis of x
= 0, but y only spans from 0 to 1.
* The location of axislabel of FloatingAxis needs to be optionally
given as a coordinate value. ex, a floating axis of x=0 with label at y=1
"""
PK#J'fBBtoolkits/axes_grid.py"""
==============================
Overview of axes_grid1 toolkit
==============================
Controlling the layout of plots with the axes_grid toolkit.
.. _axes_grid1_users-guide-index:
What is axes_grid1 toolkit?
===========================
*axes_grid1* is a collection of helper classes to ease displaying
(multiple) images with matplotlib. In matplotlib, the axes location
(and size) is specified in the normalized figure coordinates, which
may not be ideal for displaying images that needs to have a given
aspect ratio. For example, it helps if you have a colorbar whose
height always matches that of the image. `ImageGrid`_, `RGB Axes`_ and
`AxesDivider`_ are helper classes that deals with adjusting the
location of (multiple) Axes. They provides a framework to adjust the
position of multiple axes at the drawing time. `ParasiteAxes`_
provides twinx(or twiny)-like features so that you can plot different
data (e.g., different y-scale) in a same Axes. `AnchoredArtists`_
includes custom artists which are placed at some anchored position,
like the legend.
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_demo_axes_grid_001.png
:target: ../../gallery/axes_grid1/demo_axes_grid.html
:align: center
:scale: 50
Demo Axes Grid
axes_grid1
==========
ImageGrid
---------
A class that creates a grid of Axes. In matplotlib, the axes location
(and size) is specified in the normalized figure coordinates. This may
not be ideal for images that needs to be displayed with a given aspect
ratio. For example, displaying images of a same size with some fixed
padding between them cannot be easily done in matplotlib. ImageGrid is
used in such case.
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_simple_axesgrid_001.png
:target: ../../gallery/axes_grid1/simple_axesgrid.html
:align: center
:scale: 50
Simple Axesgrid
* The position of each axes is determined at the drawing time (see
`AxesDivider`_), so that the size of the entire grid fits in the
given rectangle (like the aspect of axes). Note that in this example,
the paddings between axes are fixed even if you changes the figure
size.
* axes in the same column has a same axes width (in figure
coordinate), and similarly, axes in the same row has a same
height. The widths (height) of the axes in the same row (column) are
scaled according to their view limits (xlim or ylim).
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_simple_axesgrid2_001.png
:target: ../../gallery/axes_grid1/simple_axesgrid2.html
:align: center
:scale: 50
Simple Axes Grid
* xaxis are shared among axes in a same column. Similarly, yaxis are
shared among axes in a same row. Therefore, changing axis properties
(view limits, tick location, etc. either by plot commands or using
your mouse in interactive backends) of one axes will affect all
other shared axes.
When initialized, ImageGrid creates given number (*ngrids* or *ncols* *
*nrows* if *ngrids* is None) of Axes instances. A sequence-like
interface is provided to access the individual Axes instances (e.g.,
grid[0] is the first Axes in the grid. See below for the order of
axes).
ImageGrid takes following arguments,
============= ======== ================================================
Name Default Description
============= ======== ================================================
fig
rect
nrows_ncols number of rows and cols. e.g., (2,2)
ngrids None number of grids. nrows x ncols if None
direction "row" increasing direction of axes number. [row|column]
axes_pad 0.02 pad between axes in inches
add_all True Add axes to figures if True
share_all False xaxis & yaxis of all axes are shared if True
aspect True aspect of axes
label_mode "L" location of tick labels thaw will be displayed.
"1" (only the lower left axes),
"L" (left most and bottom most axes),
or "all".
cbar_mode None [None|single|each]
cbar_location "right" [right|top]
cbar_pad None pad between image axes and colorbar axes
cbar_size "5%" size of the colorbar
axes_class None
============= ======== ================================================
*rect*
specifies the location of the grid. You can either specify
coordinates of the rectangle to be used (e.g., (0.1, 0.1, 0.8, 0.8)
as in the Axes), or the subplot-like position (e.g., "121").
*direction*
means the increasing direction of the axes number.
*aspect*
By default (False), widths and heights of axes in the grid are
scaled independently. If True, they are scaled according to their
data limits (similar to aspect parameter in mpl).
*share_all*
if True, xaxis and yaxis of all axes are shared.
*direction*
direction of increasing axes number. For "row",
+---------+---------+
| grid[0] | grid[1] |
+---------+---------+
| grid[2] | grid[3] |
+---------+---------+
For "column",
+---------+---------+
| grid[0] | grid[2] |
+---------+---------+
| grid[1] | grid[3] |
+---------+---------+
You can also create a colorbar (or colorbars). You can have colorbar
for each axes (cbar_mode="each"), or you can have a single colorbar
for the grid (cbar_mode="single"). The colorbar can be placed on your
right, or top. The axes for each colorbar is stored as a *cbar_axes*
attribute.
The examples below show what you can do with ImageGrid.
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_demo_axes_grid_001.png
:target: ../../gallery/axes_grid1/demo_axes_grid.html
:align: center
:scale: 50
Demo Axes Grid
AxesDivider Class
-----------------
Behind the scene, the ImageGrid class and the RGBAxes class utilize the
AxesDivider class, whose role is to calculate the location of the axes
at drawing time. While a more about the AxesDivider is (will be)
explained in (yet to be written) AxesDividerGuide, direct use of the
AxesDivider class will not be necessary for most users. The
axes_divider module provides a helper function make_axes_locatable,
which can be useful. It takes a existing axes instance and create a
divider for it. ::
ax = subplot(1,1,1)
divider = make_axes_locatable(ax)
*make_axes_locatable* returns an instance of the AxesLocator class,
derived from the Locator. It provides *append_axes* method that
creates a new axes on the given side of ("top", "right", "bottom" and
"left") of the original axes.
colorbar whose height (or width) in sync with the master axes
-------------------------------------------------------------
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_simple_colorbar_001.png
:target: ../../gallery/axes_grid1/simple_colorbar.html
:align: center
:scale: 50
Simple Colorbar
scatter_hist.py with AxesDivider
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The "scatter_hist.py" example in mpl can be rewritten using
*make_axes_locatable*. ::
axScatter = subplot(111)
axScatter.scatter(x, y)
axScatter.set_aspect(1.)
# create new axes on the right and on the top of the current axes.
divider = make_axes_locatable(axScatter)
axHistx = divider.append_axes("top", size=1.2, pad=0.1, sharex=axScatter)
axHisty = divider.append_axes("right", size=1.2, pad=0.1, sharey=axScatter)
# the scatter plot:
# histograms
bins = np.arange(-lim, lim + binwidth, binwidth)
axHistx.hist(x, bins=bins)
axHisty.hist(y, bins=bins, orientation='horizontal')
See the full source code below.
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_scatter_hist_001.png
:target: ../../gallery/axes_grid1/scatter_hist.html
:align: center
:scale: 50
Scatter Hist
The scatter_hist using the AxesDivider has some advantage over the
original scatter_hist.py in mpl. For example, you can set the aspect
ratio of the scatter plot, even with the x-axis or y-axis is shared
accordingly.
ParasiteAxes
------------
The ParasiteAxes is an axes whose location is identical to its host
axes. The location is adjusted in the drawing time, thus it works even
if the host change its location (e.g., images).
In most cases, you first create a host axes, which provides a few
method that can be used to create parasite axes. They are *twinx*,
*twiny* (which are similar to twinx and twiny in the matplotlib) and
*twin*. *twin* takes an arbitrary transformation that maps between the
data coordinates of the host axes and the parasite axes. *draw*
method of the parasite axes are never called. Instead, host axes
collects artists in parasite axes and draw them as if they belong to
the host axes, i.e., artists in parasite axes are merged to those of
the host axes and then drawn according to their zorder. The host and
parasite axes modifies some of the axes behavior. For example, color
cycle for plot lines are shared between host and parasites. Also, the
legend command in host, creates a legend that includes lines in the
parasite axes. To create a host axes, you may use *host_suplot* or
*host_axes* command.
Example 1. twinx
~~~~~~~~~~~~~~~~
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_parasite_simple_001.png
:target: ../../gallery/axes_grid1/parasite_simple.html
:align: center
:scale: 50
Parasite Simple
Example 2. twin
~~~~~~~~~~~~~~~
*twin* without a transform argument assumes that the parasite axes has the
same data transform as the host. This can be useful when you want the
top(or right)-axis to have different tick-locations, tick-labels, or
tick-formatter for bottom(or left)-axis. ::
ax2 = ax.twin() # now, ax2 is responsible for "top" axis and "right" axis
ax2.set_xticks([0., .5*np.pi, np.pi, 1.5*np.pi, 2*np.pi])
ax2.set_xticklabels(["0", r"$\frac{1}{2}\pi$",
r"$\pi$", r"$\frac{3}{2}\pi$", r"$2\pi$"])
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_simple_axisline4_001.png
:target: ../../gallery/axes_grid1/simple_axisline4.html
:align: center
:scale: 50
Simple Axisline4
A more sophisticated example using twin. Note that if you change the
x-limit in the host axes, the x-limit of the parasite axes will change
accordingly.
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_parasite_simple2_001.png
:target: ../../gallery/axes_grid1/parasite_simple2.html
:align: center
:scale: 50
Parasite Simple2
AnchoredArtists
---------------
It's a collection of artists whose location is anchored to the (axes)
bbox, like the legend. It is derived from *OffsetBox* in mpl, and
artist need to be drawn in the canvas coordinate. But, there is a
limited support for an arbitrary transform. For example, the ellipse
in the example below will have width and height in the data
coordinate.
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_simple_anchored_artists_001.png
:target: ../../gallery/axes_grid1/simple_anchored_artists.html
:align: center
:scale: 50
Simple Anchored Artists
InsetLocator
------------
:mod:`mpl_toolkits.axes_grid1.inset_locator` provides helper classes
and functions to place your (inset) axes at the anchored position of
the parent axes, similarly to AnchoredArtist.
Using :func:`mpl_toolkits.axes_grid1.inset_locator.inset_axes`, you
can have inset axes whose size is either fixed, or a fixed proportion
of the parent axes. For example,::
inset_axes = inset_axes(parent_axes,
width="30%", # width = 30% of parent_bbox
height=1., # height : 1 inch
loc=3)
creates an inset axes whose width is 30% of the parent axes and whose
height is fixed at 1 inch.
You may creates your inset whose size is determined so that the data
scale of the inset axes to be that of the parent axes multiplied by
some factor. For example, ::
inset_axes = zoomed_inset_axes(ax,
0.5, # zoom = 0.5
loc=1)
creates an inset axes whose data scale is half of the parent axes.
Here is complete examples.
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_inset_locator_demo_001.png
:target: ../../gallery/axes_grid1/inset_locator_demo.html
:align: center
:scale: 50
Inset Locator Demo
For example, :func:`zoomed_inset_axes` can be used when you want the
inset represents the zoom-up of the small portion in the parent axes.
And :mod:`~mpl_toolkits/axes_grid/inset_locator` provides a helper
function :func:`mark_inset` to mark the location of the area
represented by the inset axes.
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_inset_locator_demo2_001.png
:target: ../../gallery/axes_grid1/inset_locator_demo2.html
:align: center
:scale: 50
Inset Locator Demo2
RGB Axes
~~~~~~~~
RGBAxes is a helper class to conveniently show RGB composite
images. Like ImageGrid, the location of axes are adjusted so that the
area occupied by them fits in a given rectangle. Also, the xaxis and
yaxis of each axes are shared. ::
from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes
fig = plt.figure(1)
ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8])
r, g, b = get_rgb() # r,g,b are 2-d images
ax.imshow_rgb(r, g, b,
origin="lower", interpolation="nearest")
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_simple_rgb_001.png
:target: ../../gallery/axes_grid1/simple_rgb.html
:align: center
:scale: 50
Simple Rgb
AxesDivider
===========
The axes_divider module provides helper classes to adjust the axes
positions of a set of images at drawing time.
* :mod:`~mpl_toolkits.axes_grid1.axes_size` provides a class of
units that are used to determine the size of each axes. For example,
you can specify a fixed size.
* :class:`~mpl_toolkits.axes_grid1.axes_size.Divider` is the class
that calculates the axes position. It divides the given
rectangular area into several areas. The divider is initialized by
setting the lists of horizontal and vertical sizes on which the division
will be based. Then use
:meth:`~mpl_toolkits.axes_grid1.axes_size.Divider.new_locator`,
which returns a callable object that can be used to set the
axes_locator of the axes.
First, initialize the divider by specifying its grids, i.e.,
horizontal and vertical.
for example,::
rect = [0.2, 0.2, 0.6, 0.6]
horiz=[h0, h1, h2, h3]
vert=[v0, v1, v2]
divider = Divider(fig, rect, horiz, vert)
where, rect is a bounds of the box that will be divided and h0,..h3,
v0,..v2 need to be an instance of classes in the
:mod:`~mpl_toolkits.axes_grid1.axes_size`. They have *get_size* method
that returns a tuple of two floats. The first float is the relative
size, and the second float is the absolute size. Consider a following
grid.
+-----+-----+-----+-----+
| v0 | | | |
+-----+-----+-----+-----+
| v1 | | | |
+-----+-----+-----+-----+
|h0,v2| h1 | h2 | h3 |
+-----+-----+-----+-----+
* v0 => 0, 2
* v1 => 2, 0
* v2 => 3, 0
The height of the bottom row is always 2 (axes_divider internally
assumes that the unit is inches). The first and the second rows have a
height ratio of 2:3. For example, if the total height of the grid is 6,
then the first and second row will each occupy 2/(2+3) and 3/(2+3) of
(6-1) inches. The widths of the horizontal columns will be similarly
determined. When the aspect ratio is set, the total height (or width) will
be adjusted accordingly.
The :mod:`mpl_toolkits.axes_grid1.axes_size` contains several classes
that can be used to set the horizontal and vertical configurations. For
example, for vertical configuration one could use::
from mpl_toolkits.axes_grid1.axes_size import Fixed, Scaled
vert = [Fixed(2), Scaled(2), Scaled(3)]
After you set up the divider object, then you create a locator
instance that will be given to the axes object.::
locator = divider.new_locator(nx=0, ny=1)
ax.set_axes_locator(locator)
The return value of the new_locator method is an instance of the
AxesLocator class. It is a callable object that returns the
location and size of the cell at the first column and the second row.
You may create a locator that spans over multiple cells.::
locator = divider.new_locator(nx=0, nx=2, ny=1)
The above locator, when called, will return the position and size of
the cells spanning the first and second column and the first row. In
this example, it will return [0:2, 1].
See the example,
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_simple_axes_divider2_001.png
:target: ../../gallery/axes_grid1/simple_axes_divider2.html
:align: center
:scale: 50
Simple Axes Divider2
You can adjust the size of each axes according to its x or y
data limits (AxesX and AxesY).
.. figure:: ../../gallery/axes_grid1/images/sphx_glr_simple_axes_divider3_001.png
:target: ../../gallery/axes_grid1/simple_axes_divider3.html
:align: center
:scale: 50
Simple Axes Divider3
"""
PK#JmOI::01_introductory/customizing.pyPK#JBffv01_introductory/usage.pyPK#J?d,d,.01_introductory/images.pyPK#JQ=FFɯ01_introductory/pyplot.pyPK#J48)8)01_introductory/sample_plots.pyPK#J2ǑF''I 01_introductory/lifecycle.pyPK#J#++7H02_intermediate/legend_guide.pyPK#J`4rr t02_intermediate/artists.pyPK#JX`%%%02_intermediate/tight_layout_guide.pyPK#JI bpp*02_intermediate/gridspec.pyPK#J##%03_advanced/path_tutorial.pyPK#J/@K@K"0D03_advanced/transforms_tutorial.pyPK#J)ucc 03_advanced/patheffects_guide.pyPK#JG88Qcolors/colors.pyPK#J
O B Bcolors/colormaps.pyPK#J/F@!@!colors/colormapnorms.pyPK#JAfcolors/colorbar_only.pyPK#J<(text/pgf.pyPK#JfdS00xEtext/mathtext.pyPK#J36WWtvtext/annotations.pyPK#Jb}UUtext/usetex.pyPK#JFRt\++7text/text_props.pyPK#Jq@ZU
text/text_intro.pyPK#J@Ftoolkits/mplot3d.pyPK#JyƬSS1toolkits/axisartist.pyPK#J'fBBtoolkits/axes_grid.pyPK