diff --git a/.appveyor.yml b/.appveyor.yml
index de0e53931c64..84aa67503d65 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -63,11 +63,11 @@ install:
#
- conda create -q -n test-environment python=%PYTHON_VERSION%
msinttypes freetype=2.6 "libpng>=1.6.21,<1.7" zlib=1.2 tk=8.5
- pip setuptools numpy pandas sphinx tornado
+ pip setuptools numpy sphinx tornado
- activate test-environment
- echo %PYTHON_VERSION% %TARGET_ARCH%
# pytest-cov>=2.3.1 due to https://github.com/pytest-dev/pytest-cov/issues/124
- - pip install -q "pytest>=3.4" "pytest-cov>=2.3.1" pytest-rerunfailures pytest-timeout pytest-xdist
+ - pip install -q "pytest>=3.4" "pytest-cov>=2.3.1" pytest-rerunfailures pytest-timeout pytest-xdist "pandas!=0.25.0"
# Apply patch to `subprocess` on Python versions > 2 and < 3.6.3
# https://github.com/matplotlib/matplotlib/issues/9176
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 015420cdb19d..41bdd1991304 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -14,20 +14,20 @@ apt-run: &apt-install
sudo apt-get -qq update
sudo apt-get install -y \
inkscape \
- libav-tools \
+ ffmpeg \
dvipng \
- pgf \
lmodern \
cm-super \
texlive-latex-base \
texlive-latex-extra \
texlive-fonts-recommended \
texlive-latex-recommended \
+ texlive-pictures \
texlive-xetex \
graphviz \
libgeos-dev \
fonts-crosextra-carlito \
- otf-freefont
+ fonts-freefont-otf
fonts-run: &fonts-install
name: Install custom fonts
@@ -101,7 +101,7 @@ jobs:
- run:
<<: *deps-install
environment:
- NUMPY_VERSION: "==1.11.0"
+ NUMPY_VERSION: "==1.13.0"
- run: *mpl-install
- run: *doc-build
diff --git a/.gitignore b/.gitignore
index c74e7438a387..bb332f00e77b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,6 +54,8 @@ Thumbs.db
###################################
lib/matplotlib/mpl-data/matplotlib.conf
lib/matplotlib/mpl-data/matplotlibrc
+tutorials/intermediate/CL01.png
+tutorials/intermediate/CL02.png
# Documentation generated files #
#################################
diff --git a/INSTALL.rst b/INSTALL.rst
index 80e563501b94..087ff0dd2e3a 100644
--- a/INSTALL.rst
+++ b/INSTALL.rst
@@ -90,10 +90,9 @@ the latest *tar.gz* release file from `the PyPI files page
develop Matplotlib or just need the latest bugfixed version, grab the
latest git version, and see :ref:`install-from-git`.
-The standard environment variables `CC`, `CXX`, `PKG_CONFIG` are respected.
-This means you can set them if your toolchain is prefixed. This may be used for
-cross compiling.
-::
+The standard environment variables :envvar:`CC`, :envvar:`CXX`,
+:envvar:`PKG_CONFIG` are respected. This means you can set them if your
+toolchain is prefixed. This may be used for cross compiling. ::
export CC=x86_64-pc-linux-gnu-gcc
export CXX=x86_64-pc-linux-gnu-g++
@@ -113,13 +112,6 @@ file will be particularly useful to those packaging Matplotlib.
.. _setup.cfg: https://raw.githubusercontent.com/matplotlib/matplotlib/master/setup.cfg.template
-If you have installed prerequisites to nonstandard places and need to
-inform Matplotlib where they are, edit ``setupext.py`` and add the base
-dirs to the ``basedir`` dictionary entry for your ``sys.platform``;
-e.g., if the header of some required library is in
-``/some/path/include/someheader.h``, put ``/some/path`` in the
-``basedir`` list for your platform.
-
.. _install_requirements:
Dependencies
@@ -202,9 +194,9 @@ etc., you can install the following:
The following libraries are shipped with Matplotlib:
- - `Agg`: the Anti-Grain Geometry C++ rendering engine;
- - `qhull`: to compute Delaunay triangulation;
- - `ttconv`: a TrueType font utility.
+ - ``Agg``: the Anti-Grain Geometry C++ rendering engine;
+ - ``qhull``: to compute Delaunay triangulation;
+ - ``ttconv``: a TrueType font utility.
.. _build_linux:
diff --git a/LICENSE/LICENSE_CARLOGO.txt b/LICENSE/LICENSE_CARLOGO.txt
new file mode 100644
index 000000000000..8c99c656a0f5
--- /dev/null
+++ b/LICENSE/LICENSE_CARLOGO.txt
@@ -0,0 +1,45 @@
+----> we renamed carlito -> carlogo to comply with the terms <----
+
+Copyright (c) 2010-2013 by tyPoland Lukasz Dziedzic with Reserved Font Name "Carlito".
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
+
+5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
\ No newline at end of file
diff --git a/doc/_static/fonts/Carlogo-bold.ttf b/doc/_static/fonts/Carlogo-bold.ttf
new file mode 100644
index 000000000000..c16254f57a89
Binary files /dev/null and b/doc/_static/fonts/Carlogo-bold.ttf differ
diff --git a/doc/_static/fonts/Carlogo-boldItalic.ttf b/doc/_static/fonts/Carlogo-boldItalic.ttf
new file mode 100644
index 000000000000..d7d2507a4e6d
Binary files /dev/null and b/doc/_static/fonts/Carlogo-boldItalic.ttf differ
diff --git a/doc/_static/fonts/Carlogo-italic.ttf b/doc/_static/fonts/Carlogo-italic.ttf
new file mode 100644
index 000000000000..de7824c6bd35
Binary files /dev/null and b/doc/_static/fonts/Carlogo-italic.ttf differ
diff --git a/doc/_static/fonts/Carlogo-regular.ttf b/doc/_static/fonts/Carlogo-regular.ttf
new file mode 100644
index 000000000000..6911c4ddf752
Binary files /dev/null and b/doc/_static/fonts/Carlogo-regular.ttf differ
diff --git a/doc/_static/fonts/carlogo-bold.woff b/doc/_static/fonts/carlogo-bold.woff
new file mode 100755
index 000000000000..00c68a81d84e
Binary files /dev/null and b/doc/_static/fonts/carlogo-bold.woff differ
diff --git a/doc/_static/fonts/carlogo-bold.woff2 b/doc/_static/fonts/carlogo-bold.woff2
new file mode 100755
index 000000000000..cff2d45c9000
Binary files /dev/null and b/doc/_static/fonts/carlogo-bold.woff2 differ
diff --git a/doc/_static/fonts/carlogo-bolditalic.woff b/doc/_static/fonts/carlogo-bolditalic.woff
new file mode 100755
index 000000000000..88be19f89771
Binary files /dev/null and b/doc/_static/fonts/carlogo-bolditalic.woff differ
diff --git a/doc/_static/fonts/carlogo-bolditalic.woff2 b/doc/_static/fonts/carlogo-bolditalic.woff2
new file mode 100755
index 000000000000..3ceb3a396837
Binary files /dev/null and b/doc/_static/fonts/carlogo-bolditalic.woff2 differ
diff --git a/doc/_static/fonts/carlogo-italic.woff b/doc/_static/fonts/carlogo-italic.woff
new file mode 100755
index 000000000000..806f239385a8
Binary files /dev/null and b/doc/_static/fonts/carlogo-italic.woff differ
diff --git a/doc/_static/fonts/carlogo-italic.woff2 b/doc/_static/fonts/carlogo-italic.woff2
new file mode 100755
index 000000000000..a70e881db731
Binary files /dev/null and b/doc/_static/fonts/carlogo-italic.woff2 differ
diff --git a/doc/_static/fonts/carlogo-regular.woff b/doc/_static/fonts/carlogo-regular.woff
new file mode 100755
index 000000000000..7a8ab29f96bb
Binary files /dev/null and b/doc/_static/fonts/carlogo-regular.woff differ
diff --git a/doc/_static/fonts/carlogo-regular.woff2 b/doc/_static/fonts/carlogo-regular.woff2
new file mode 100755
index 000000000000..272988a2bc01
Binary files /dev/null and b/doc/_static/fonts/carlogo-regular.woff2 differ
diff --git a/doc/_static/geoplot_nyc_traffic_tickets.png b/doc/_static/geoplot_nyc_traffic_tickets.png
new file mode 100644
index 000000000000..0ee9ba1a298b
Binary files /dev/null and b/doc/_static/geoplot_nyc_traffic_tickets.png differ
diff --git a/doc/_static/mpl.css b/doc/_static/mpl.css
index ac4bde0486f9..10d922b437e4 100644
--- a/doc/_static/mpl.css
+++ b/doc/_static/mpl.css
@@ -3,6 +3,26 @@
* Originally created by Armin Ronacher for Werkzeug, adapted by Georg Brandl.
*/
+/* Carlogo font (simmilar to Calibri in the MPL logo) */
+@font-face {
+ font-family: 'CarlogoRegular';
+ font-style: normal;
+ src: local('Carlito'),
+ url('fonts/carlogo-regular.woff2') format('woff2'),
+ url('fonts/carlogo-regular.woff') format('woff'),
+ url('fonts/carlogo-regular.ttf') format('truetype')
+}
+
+@font-face {
+ font-family: 'CarlogoBold';
+ font-style: bold;
+ src: local('Carlito Bold'),
+ url('fonts/carlogo-bold.woff2') format('woff2'),
+ url('fonts/carlogo-bold.woff') format('woff'),
+ url('fonts/carlogo-bold.ttf') format('truetype')
+}
+
+
body {
font-family: "Helvetica Neue", Helvetica, 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif;
font-size: 14px;
@@ -312,6 +332,11 @@ h3 {
font-size: 1.2em;
}
+h1, h2, h3, h4, h5, h6{
+ font-family: 'CarlogoBold', 'Carlito-bold', sans-serif;
+ font-weight: normal;
+}
+
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
color: black!important;
}
@@ -594,6 +619,10 @@ span.linkdescr {
font-size: 90%;
}
+.highlight span.c1 span.highlighted {
+ background-color: #fce5a6;
+}
+
ul.search {
margin: 10px 0 0 20px;
padding: 0;
@@ -1114,3 +1143,30 @@ div.viewcode-block:target {
.sidebar-announcement p {
margin: 0.4em 0.4em 0.6em 0.4em;
}
+
+/* new main nav */
+nav.main-nav{
+ background-color: #002b47;
+ font-family: 'CarlogoRegular', 'Carlito', sans-serif;
+ font-size: 16px;
+ }
+
+ nav.main-nav ul{
+ margin: 0;
+ padding: 0;
+ display: flex;
+ flex-direction: row;
+ }
+
+ nav.main-nav li{
+ margin: 8px 15px;
+ list-style-type: none;
+ }
+
+ nav.main-nav a{
+ color: white;
+ }
+
+ nav.main-nav a:hover{
+ text-decoration: underline;
+ }
\ No newline at end of file
diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html
index 8e8c7067948e..ccd6676df51c 100644
--- a/doc/_templates/layout.html
+++ b/doc/_templates/layout.html
@@ -38,9 +38,6 @@
The 2019 SciPy John Hunter Excellence in Plotting Contest is accepting submissions!
-
- Apply by June 8th
-
{%- if builder in ('htmlhelp', 'devhelp', 'latex') %}
@@ -236,6 +228,16 @@
{{ _('Navigation') }}
+
+
{%- endblock %}
{%- block footer %}
diff --git a/doc/api/ticker_api.rst b/doc/api/ticker_api.rst
index 8da9ac2988f0..652050dafedc 100644
--- a/doc/api/ticker_api.rst
+++ b/doc/api/ticker_api.rst
@@ -6,3 +6,7 @@
:members:
:undoc-members:
:show-inheritance:
+
+
+.. inheritance-diagram:: matplotlib.ticker
+ :parts: 1
diff --git a/doc/citing.rst b/doc/citing.rst
index 80a07cce041a..100d3a7f0ab4 100644
--- a/doc/citing.rst
+++ b/doc/citing.rst
@@ -27,6 +27,9 @@ pp. 90-95, 2007 `_.
DOIs
----
+v3.1.1
+ .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.3264781.svg
+ :target: https://doi.org/10.5281/zenodo.3264781
v3.1.0
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.2893252.svg
:target: https://doi.org/10.5281/zenodo.2893252
diff --git a/doc/conf.py b/doc/conf.py
index 7c51f2309288..29cdf742a36c 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -218,7 +218,7 @@ def _check_dependencies():
# must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path.
#html_style = 'matplotlib.css'
-html_style = 'mpl.css'
+html_style = f'mpl.css?{SHA}'
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
diff --git a/doc/devel/contributing.rst b/doc/devel/contributing.rst
index d2d1224023f7..b79e83148e10 100644
--- a/doc/devel/contributing.rst
+++ b/doc/devel/contributing.rst
@@ -5,10 +5,13 @@ Contributing
============
This project is a community effort, and everyone is welcome to
-contribute.
+contribute. We follow the `Python Software Foundation Code of Conduct
+`_ in everything we do.
The project is hosted on https://github.com/matplotlib/matplotlib
+.. _coc: http://www.python.org/psf/codeofconduct/
+
Submitting a bug report
=======================
@@ -103,7 +106,15 @@ Copy :file:`setup.cfg.template` to :file:`setup.cfg` and edit it to contain::
tests = True
or set the ``MPLLOCALFREETYPE`` environmental variable to any true
-value.
+value. If you have previously built Matplotlib with a different
+version of Freetype, you will also need to remove the c/c++ build
+products. Do this is to delete the ``build`` folder or ``git clean
+-xfd``. If you are going to be regularly working on Matplotlib,
+consider putting ::
+
+ export MPLLOCALFREETYPE=1
+
+in your shell start up files.
Installing Matplotlib in developer mode
diff --git a/doc/devel/documenting_mpl.rst b/doc/devel/documenting_mpl.rst
index 26b019af7ea7..98d2fd23ad88 100644
--- a/doc/devel/documenting_mpl.rst
+++ b/doc/devel/documenting_mpl.rst
@@ -500,15 +500,8 @@ section of the docstring.
rcParams
~~~~~~~~
rcParams can be referenced with the custom ``:rc:`` role:
-:literal:`:rc:\`foo\`` yields ``rcParams["foo"]``. Use `= [default-val]`
-to indicate the default value of the parameter. The default value should be
-literal, i.e. enclosed in double backticks. For simplicity these may be
-omitted for string default values.
-
-.. code-block:: rst
-
- If not provided, defaults to :rc:`figure.figsize` = ``[6.4, 4.8]``.
- If not provided, defaults to :rc:`figure.facecolor` = 'w'.
+:literal:`:rc:\`foo\`` yields ``rcParams["foo"] = 'default'``, which is a link
+to the :file:`matplotlibrc` file description.
Deprecated formatting conventions
---------------------------------
diff --git a/doc/devel/testing.rst b/doc/devel/testing.rst
index 651bbba8a8a1..c6707f29c19c 100644
--- a/doc/devel/testing.rst
+++ b/doc/devel/testing.rst
@@ -12,9 +12,10 @@ infrastructure are in :mod:`matplotlib.testing`.
.. _Ghostscript: https://www.ghostscript.com/
.. _Inkscape: https://inkscape.org
.. _pytest-cov: https://pytest-cov.readthedocs.io/en/latest/
-.. _pytest-pep8: https://pypi.python.org/pypi/pytest-pep8
-.. _pytest-xdist: https://pypi.python.org/pypi/pytest-xdist
-.. _pytest-timeout: https://pypi.python.org/pypi/pytest-timeout
+.. _pytest-flake8: https://pypi.org/project/pytest-flake8/
+.. _pytest-xdist: https://pypi.org/project/pytest-xdist/
+.. _pytest-timeout: https://pypi.org/project/pytest-timeout/
+.. _flake8: https://pypi.org/project/flake8/
Requirements
------------
@@ -32,7 +33,7 @@ The following software is required to run the tests:
Optionally you can install:
- pytest-cov_ (>=2.3.1) to collect coverage information
-- pytest-pep8_ to test coding standards
+- pytest-flake8_ to test coding standards using flake8_
- pytest-timeout_ to limit runtime in case of stuck tests
- pytest-xdist_ to run tests in parallel
@@ -44,29 +45,20 @@ Running the tests is simple. Make sure you have pytest installed and run::
pytest
-or::
+in the root directory of the repository.
- pytest .
-
-
-in the root directory of the distribution. The script takes a set of
-commands, such as:
-
-======================== ===========
-``--pep8`` Perform pep8 checks (requires pytest-pep8_)
-``-m "not network"`` Disable tests that require network access
-======================== ===========
-
-Additional arguments are passed on to pytest. See the pytest documentation for
-`supported arguments`_. Some of the more important ones are given here:
+`pytest` can be configured via a lot of `commandline parameters`_. Some
+particularly useful ones are:
============================= ===========
-``--verbose`` Be more verbose
-``--n NUM`` Run tests in parallel over NUM
+``-v`` or ``--verbose`` Be more verbose
+``-n NUM`` Run tests in parallel over NUM
processes (requires pytest-xdist_)
``--timeout=SECONDS`` Set timeout for results from each test
process (requires pytest-timeout_)
``--capture=no`` or ``-s`` Do not capture stdout
+``--flake8`` Check coding standards using flake8_
+ (requires pytest-flake8_)
============================= ===========
To run a single test from the command line, you can provide a file path,
@@ -98,7 +90,7 @@ function :func:`matplotlib.test`::
matplotlib.test()
-.. _supported arguments: http://doc.pytest.org/en/latest/usage.html
+.. _commandline parameters: http://doc.pytest.org/en/latest/usage.html
Writing a simple test
diff --git a/doc/faq/howto_faq.rst b/doc/faq/howto_faq.rst
index 39cfc86258cd..66987fc44d68 100644
--- a/doc/faq/howto_faq.rst
+++ b/doc/faq/howto_faq.rst
@@ -1,8 +1,7 @@
-
.. _howto-faq:
******
-How-To
+How-to
******
.. contents::
@@ -11,8 +10,8 @@ How-To
.. _howto-plotting:
-Plotting: howto
-===============
+How-to: Plotting
+================
.. _howto-datetime64:
@@ -38,6 +37,36 @@ If you only want to use the `pandas` converter for `datetime64` values ::
+.. _howto-figure-empty:
+
+Check whether a figure is empty
+-------------------------------
+Empty can actually mean different things. Does the figure contain any artists?
+Does a figure with an empty `~.axes.Axes` still count as empty? Is the figure
+empty if it was rendered pure white (there may be artists present, but they
+could be outside the drawing area or transparent)?
+
+For the purpose here, we define empty as: "The figure does not contain any
+artists except it's background patch." The exception for the background is
+necessary, because by default every figure contains a `.Rectangle` as it's
+background patch. This definition could be checked via::
+
+ def is_empty(figure):
+ """
+ Return whether the figure contains no Artists (other than the default
+ background patch).
+ """
+ contained_artists = figure.get_children()
+ return len(contained_artists) <= 1
+
+We've decided not to include this as a figure method because this is only one
+way of defining empty, and checking the above is only rarely necessary.
+Usually the user or program handling the figure know if they have added
+something to the figure.
+
+Checking whether a figure would render empty cannot be reliably checked except
+by actually rendering the figure and investigating the rendered result.
+
.. _howto-findobj:
Find all objects in a figure of a certain type
@@ -190,7 +219,8 @@ specify the location explicitly::
ax = fig.add_axes([left, bottom, width, height])
where all values are in fractional (0 to 1) coordinates. See
-:doc:`/gallery/subplots_axes_and_figures/axes_demo` for an example of placing axes manually.
+:doc:`/gallery/subplots_axes_and_figures/axes_demo` for an example of
+placing axes manually.
.. _howto-auto-adjust:
@@ -199,8 +229,11 @@ Automatically make room for tick labels
.. note::
This is now easier to handle than ever before.
- Calling :func:`~matplotlib.pyplot.tight_layout` can fix many common
- layout issues. See the :doc:`/tutorials/intermediate/tight_layout_guide`.
+ Calling :func:`~matplotlib.pyplot.tight_layout` or alternatively using
+ ``constrained_layout=True`` argument in :func:`~matplotlib.pyplot.subplots`
+ can fix many common layout issues. See the
+ :doc:`/tutorials/intermediate/tight_layout_guide` and
+ :doc:`/tutorials/intermediate/constrainedlayout_guide` for more details.
The information below is kept here in case it is useful for other
purposes.
@@ -549,8 +582,8 @@ GUI backends *require* being run from the main thread as well.
.. _howto-contribute:
-Contributing: howto
-===================
+How-to: Contributing
+====================
.. _how-to-request-feature:
@@ -637,8 +670,8 @@ or look at the open issues on github.
.. _howto-webapp:
-Matplotlib in a web application server
-======================================
+How to use Matplotlib in a web application server
+=================================================
In general, the simplest solution when using Matplotlib in a web server is
to completely avoid using pyplot (pyplot maintains references to the opened
@@ -690,8 +723,8 @@ contributing to these efforts that would be great.
.. _how-to-search-examples:
-Search examples
-===============
+How to search for examples
+==========================
The nearly 300 code :ref:`examples-index` included with the Matplotlib
source distribution are full-text searchable from the :ref:`search`
diff --git a/doc/index.rst b/doc/index.rst
index 4451adc3537a..361e5d979833 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -46,11 +46,6 @@ particularly when combined with IPython. For the power user, you have full
control of line styles, font properties, axes properties, etc, via an object
oriented interface or via a set of functions familiar to MATLAB users.
-Installation
-------------
-
-Visit the :doc:`Matplotlib installation instructions `.
-
Documentation
-------------
@@ -109,30 +104,40 @@ Other learning resources
There are many :doc:`external learning resources ` available
including printed material, videos and tutorials.
-Need help?
-~~~~~~~~~~
+Join our community!
+~~~~~~~~~~~~~~~~~~~
-Matplotlib is a welcoming, inclusive project, and we try to follow the `Python
+Matplotlib is a welcoming, inclusive project, and we follow the `Python
Software Foundation Code of Conduct `_ in everything we do.
.. _coc: http://www.python.org/psf/codeofconduct/
-Check the :doc:`FAQ ` and the :doc:`API ` docs.
-
-For help, join the `gitter channel`_ and the matplotlib-users_,
-matplotlib-devel_, and matplotlib-announce_ mailing lists, or check out the
-Matplotlib tag on stackoverflow_. The `search `_ tool searches
-all of the documentation, including full text search of over 350 complete
-examples which exercise almost every corner of Matplotlib.
-
+- Join our community at `discourse.matplotlib.org`_ to get help, discuss
+ contributing & development, and share your work.
+- If you have questions, be sure to check the :doc:`FAQ `, the
+ :doc:`API ` docs, and the `search `_ tool
+ searches all of the documentation, including full text search of over 350
+ complete examples which exercise almost every corner of Matplotlib.
+- If its something quick join the `gitter channel`_ to chat with the
+ community.
+- If you prefer email there are the matplotlib-users_, matplotlib-devel_,
+ and matplotlib-announce_ mailing lists.
+- Check out the Matplotlib tag on stackoverflow_.
+- Tweet us at Twitter_! or see cool plots on Instagram_!
+
+.. _discourse.matplotlib.org: https://discourse.matplotlib.org
.. _gitter channel: https://gitter.im/matplotlib/matplotlib
.. _matplotlib-users: https://mail.python.org/mailman/listinfo/matplotlib-users
.. _matplotlib-devel: https://mail.python.org/mailman/listinfo/matplotlib-devel
.. _matplotlib-announce: https://mail.python.org/mailman/listinfo/matplotlib-announce
.. _stackoverflow: http://stackoverflow.com/questions/tagged/matplotlib
+.. _Twitter: https://twitter.com/matplotlib
+.. _Instagram: https://www.instagram.com/matplotart/
You can file bugs, patches and feature requests on the `issue tracker`_, but it
-is a good idea to ping us on the mailing list too.
+is a good idea to ping us on Discourse_ as well.
+
+.. _Discourse: https://discourse.matplotlib.org
To keep up to date with what's going on in Matplotlib, see the :doc:`what's
new ` page or browse the `source code`_. Anything that could
@@ -182,12 +187,25 @@ Open source
style="float:right; margin-left:20px" />
+
+Matplotlib is a Sponsored Project of NumFOCUS, a 501(c)(3) nonprofit
+charity in the United States. NumFOCUS provides Matplotlib with
+fiscal, legal, and administrative support to help ensure the health
+and sustainability of the project. Visit `numfocus.org `_ for more
+information.
+
+Donations to Matplotlib are managed by NumFOCUS. For donors in the
+United States, your gift is tax-deductible to the extent provided by
+law. As with any donation, you should consult with your tax adviser
+about your particular tax situation.
+
Please consider `donating to the Matplotlib project `_ through
the Numfocus organization or to the `John Hunter Technology Fellowship
`_.
.. _donating: https://numfocus.salsalabs.org/donate-to-matplotlib/index.html
.. _jdh-fellowship: https://www.numfocus.org/programs/john-hunter-technology-fellowship/
+.. _nf: https://numfocus.org
The :doc:`Matplotlib license ` is based on the `Python Software
Foundation (PSF) license `_.
diff --git a/doc/sphinxext/custom_roles.py b/doc/sphinxext/custom_roles.py
index 2232f1032424..88dddb6a2e4b 100644
--- a/doc/sphinxext/custom_roles.py
+++ b/doc/sphinxext/custom_roles.py
@@ -1,16 +1,19 @@
from docutils import nodes
from os.path import sep
+from matplotlib import rcParamsDefault
def rcparam_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
- rendered = nodes.Text('rcParams["{}"]'.format(text))
+ param = rcParamsDefault.get(text)
+ rendered = nodes.Text(f'rcParams["{text}"] = {param!r}')
source = inliner.document.attributes['source'].replace(sep, '/')
rel_source = source.split('/doc/', 1)[1]
levels = rel_source.count('/')
refuri = ('../' * levels +
- 'tutorials/introductory/customizing.html#matplotlib-rcparams')
+ 'tutorials/introductory/customizing.html' +
+ f"?highlight={text}#a-sample-matplotlibrc-file")
ref = nodes.reference(rawtext, rendered, refuri=refuri)
return [nodes.literal('', '', ref)], []
diff --git a/doc/thirdpartypackages/index.rst b/doc/thirdpartypackages/index.rst
index 4b29940a7f82..b2a791a220fc 100644
--- a/doc/thirdpartypackages/index.rst
+++ b/doc/thirdpartypackages/index.rst
@@ -35,6 +35,16 @@ data processing tools. An example plot from the `Cartopy gallery
.. image:: /_static/cartopy_hurricane_katrina_01_00.png
:height: 400px
+Geoplot
+=======
+`Geoplot `_ builds on top
+of Matplotlib and Cartopy to provide a "standard library" of simple, powerful,
+and customizable plot types. An example plot from the `Geoplot gallery
+`_:
+
+.. image:: /_static/geoplot_nyc_traffic_tickets.png
+ :height: 400px
+
Ridge Map
=========
`ridge_map `_ uses Matplotlib,
@@ -90,7 +100,7 @@ class that can have a visual break to indicate a discontinuous range.
DeCiDa
======
-`DeCiDa `_ is a library of functions
+`DeCiDa `_ is a library of functions
and classes for electron device characterization, electronic circuit design and
general data visualization and analysis.
@@ -202,6 +212,21 @@ animated plots almost as easy as static ones.
For an animated version of the above picture and more examples, see the
`animatplot gallery. `_
+Rendering backends
+******************
+
+mplcairo
+========
+`mplcairo `_ is a cairo backend for
+Matplotlib, with faster and more accurate marker drawing, support for a wider
+selection of font formats and complex text layout, and various other features.
+
+gr
+==
+`gr `_ is a framework for cross-platform
+visualisation applications, which can be used as a high-performance Matplotlib
+backend.
+
Miscellaneous
*************
@@ -221,12 +246,6 @@ feature.
.. image:: /_static/matplotlib_iterm2_demo.png
-mplcairo
-========
-`mplcairo `_ is a cairo backend for
-Matplotlib, with faster and more accurate marker drawing, support for a wider
-selection of font formats and complex text layout, and various other features.
-
mpl-template
============
`mpl-template `_ provides
diff --git a/doc/users/prev_whats_new/whats_new_1.5.rst b/doc/users/prev_whats_new/whats_new_1.5.rst
index dbb7a67d527b..827076fca466 100644
--- a/doc/users/prev_whats_new/whats_new_1.5.rst
+++ b/doc/users/prev_whats_new/whats_new_1.5.rst
@@ -734,9 +734,9 @@ IPython's ``HTML`` display class::
Prefixed pkg-config for building
--------------------------------
-Handling of `pkg-config` has been fixed in so far as it is now
-possible to set it using the environment variable `PKG_CONFIG`. This
-is important if your toolchain is prefixed. This is done in a simpilar
-way as setting `CC` or `CXX` before building. An example follows.
+Handling of pkg-config has been fixed in so far as it is now possible to set it
+using the environment variable :envvar:`PKG_CONFIG`. This is important if your
+toolchain is prefixed. This is done in a simpilar way as setting :envvar:`CC`
+or :envvar:`CXX` before building. An example follows.
export PKG_CONFIG=x86_64-pc-linux-gnu-pkg-config
diff --git a/examples/lines_bars_and_markers/fill_between_demo.py b/examples/lines_bars_and_markers/fill_between_demo.py
index ada25f0de558..6b9566033472 100644
--- a/examples/lines_bars_and_markers/fill_between_demo.py
+++ b/examples/lines_bars_and_markers/fill_between_demo.py
@@ -3,76 +3,144 @@
Filling the area between lines
==============================
-This example shows how to use ``fill_between`` to color between lines based on
-user-defined logic.
+This example shows how to use `~.axes.Axes.fill_between` to color the area
+between two lines.
"""
import matplotlib.pyplot as plt
import numpy as np
+###############################################################################
+#
+# Basic usage
+# -----------
+# The parameters *y1* and *y2* can be a scalar, indicating a horizontal
+# boundary a the given y-values. If only *y1* is given, *y2* defaults to 0.
+
x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2 * np.pi * x)
-y2 = 1.2 * np.sin(4 * np.pi * x)
+y2 = 0.8 * np.sin(4 * np.pi * x)
-###############################################################################
+fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True, figsize=(6, 6))
-fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True)
-
-ax1.fill_between(x, 0, y1)
-ax1.set_ylabel('between y1 and 0')
+ax1.fill_between(x, y1)
+ax1.set_title('fill between y1 and 0')
ax2.fill_between(x, y1, 1)
-ax2.set_ylabel('between y1 and 1')
+ax2.set_title('fill between y1 and 1')
ax3.fill_between(x, y1, y2)
-ax3.set_ylabel('between y1 and y2')
+ax3.set_title('fill between y1 and y2')
ax3.set_xlabel('x')
+fig.tight_layout()
###############################################################################
-# Now fill between y1 and y2 where a logical condition is met. Note
-# this is different than calling
-# ``fill_between(x[where], y1[where], y2[where] ...)``
-# because of edge effects over multiple contiguous regions.
-
-fig, (ax, ax1) = plt.subplots(2, 1, sharex=True)
-ax.plot(x, y1, x, y2, color='black')
-ax.fill_between(x, y1, y2, where=y2 >= y1, facecolor='green', interpolate=True)
-ax.fill_between(x, y1, y2, where=y2 <= y1, facecolor='red', interpolate=True)
-ax.set_title('fill between where')
-
-# Test support for masked arrays.
-y2 = np.ma.masked_greater(y2, 1.0)
-ax1.plot(x, y1, x, y2, color='black')
-ax1.fill_between(x, y1, y2, where=y2 >= y1,
- facecolor='green', interpolate=True)
-ax1.fill_between(x, y1, y2, where=y2 <= y1,
- facecolor='red', interpolate=True)
-ax1.set_title('Now regions with y2>1 are masked')
+#
+# Example: Confidence bands
+# -------------------------
+# A common application for `~.axes.Axes.fill_between` is the indication of
+# confidence bands.
+#
+# `~.axes.Axes.fill_between` uses the colors of the color cycle as the fill
+# color. These may be a bit strong when applied to fill areas. It is
+# therefore often a good practice to lighten the color by making the area
+# semi-transparent using *alpha*.
+
+# sphinx_gallery_thumbnail_number = 2
+
+N = 21
+x = np.linspace(0, 10, 11)
+y = [3.9, 4.4, 10.8, 10.3, 11.2, 13.1, 14.1, 9.9, 13.9, 15.1, 12.5]
+
+# fit a linear curve an estimate its y-values and their error.
+a, b = np.polyfit(x, y, deg=1)
+y_est = a * x + b
+y_err = x.std() * np.sqrt(1/len(x) +
+ (x - x.mean())**2 / np.sum((x - x.mean())**2))
+
+fig, ax = plt.subplots()
+ax.plot(x, y_est, '-')
+ax.fill_between(x, y_est - y_err, y_est + y_err, alpha=0.2)
+ax.plot(x, y, 'o', color='tab:brown')
###############################################################################
-# This example illustrates a problem; because of the data
-# gridding, there are undesired unfilled triangles at the crossover
-# points. A brute-force solution would be to interpolate all
-# arrays to a very fine grid before plotting.
+#
+# Selectively filling horizontal regions
+# --------------------------------------
+# The parameter *where* allows to specify the x-ranges to fill. It's a boolean
+# array with the same size as *x*.
+#
+# Only x-ranges of contiguous *True* sequences are filled. As a result the
+# range between neighboring *True* and *False* values is never filled. This
+# often undesired when the data points should represent a contiguous quantity.
+# It is therefore recommended to set ``interpolate=True`` unless the
+# x-distance of the data points is fine enough so that the above effect is not
+# noticeable. Interpolation approximates the actual x position at which the
+# *where* condition will change and extends the filling up to there.
+
+x = np.array([0, 1, 2, 3])
+y1 = np.array([0.8, 0.8, 0.2, 0.2])
+y2 = np.array([0, 0, 1, 1])
+
+fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
+
+ax1.set_title('interpolation=False')
+ax1.plot(x, y1, 'o--')
+ax1.plot(x, y2, 'o--')
+ax1.fill_between(x, y1, y2, where=(y1 > y2), color='C0', alpha=0.3)
+ax1.fill_between(x, y1, y2, where=(y1 < y2), color='C1', alpha=0.3)
+
+ax2.set_title('interpolation=True')
+ax2.plot(x, y1, 'o--')
+ax2.plot(x, y2, 'o--')
+ax2.fill_between(x, y1, y2, where=(y1 > y2), color='C0', alpha=0.3,
+ interpolate=True)
+ax2.fill_between(x, y1, y2, where=(y1 <= y2), color='C1', alpha=0.3,
+ interpolate=True)
+fig.tight_layout()
+###############################################################################
+#
+# .. note::
+#
+# Similar gaps will occur if *y1* or *y2* are masked arrays. Since missing
+# values cannot be approximated, *interpolate* has no effect in this case.
+# The gaps around masked values can only be reduced by adding more data
+# points close to the masked values.
###############################################################################
-# Use transforms to create axes spans where a certain condition is satisfied:
+#
+# Selectively marking horizontal regions across the whole Axes
+# ------------------------------------------------------------
+# The same selection mechanism can be applied to fill the full vertical height
+# of the axes. To be independent of y-limits, we add a transform that
+# interprets the x-values in data coorindates and the y-values in axes
+# coordinates.
+#
+# The following example marks the regions in which the y-data are above a
+# given threshold.
fig, ax = plt.subplots()
-y = np.sin(4 * np.pi * x)
+x = np.arange(0, 4 * np.pi, 0.01)
+y = np.sin(x)
ax.plot(x, y, color='black')
-# use data coordinates for the x-axis and the axes coordinates for the y-axis
-import matplotlib.transforms as mtransforms
-trans = mtransforms.blended_transform_factory(ax.transData, ax.transAxes)
-theta = 0.9
-ax.axhline(theta, color='green', lw=2, alpha=0.5)
-ax.axhline(-theta, color='red', lw=2, alpha=0.5)
-ax.fill_between(x, 0, 1, where=y > theta,
- facecolor='green', alpha=0.5, transform=trans)
-ax.fill_between(x, 0, 1, where=y < -theta,
- facecolor='red', alpha=0.5, transform=trans)
-
-
-plt.show()
+threshold = 0.75
+ax.axhline(threshold, color='green', lw=2, alpha=0.7)
+ax.fill_between(x, 0, 1, where=y > threshold,
+ color='green', alpha=0.5, transform=ax.get_xaxis_transform())
+
+#############################################################################
+#
+# ------------
+#
+# References
+# """"""""""
+#
+# The use of the following functions, methods and classes is shown
+# in this example:
+
+import matplotlib
+matplotlib.axes.Axes.fill_between
+matplotlib.pyplot.fill_between
+matplotlib.axes.Axes.get_xaxis_transform
diff --git a/examples/lines_bars_and_markers/horizontal_barchart_distribution.py b/examples/lines_bars_and_markers/horizontal_barchart_distribution.py
index 73367e4b1d60..c851997ad29a 100644
--- a/examples/lines_bars_and_markers/horizontal_barchart_distribution.py
+++ b/examples/lines_bars_and_markers/horizontal_barchart_distribution.py
@@ -70,6 +70,7 @@ def survey(results, category_names):
survey(results, category_names)
+plt.show()
#############################################################################
#
diff --git a/examples/pyplots/fig_x.py b/examples/pyplots/fig_x.py
index 304ff4ed3547..52a8840892cc 100644
--- a/examples/pyplots/fig_x.py
+++ b/examples/pyplots/fig_x.py
@@ -5,15 +5,14 @@
Adding lines to a figure without any axes.
"""
+
import matplotlib.pyplot as plt
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])
-
+fig.add_artist(lines.Line2D([0, 1], [0, 1]))
+fig.add_artist(lines.Line2D([0, 1], [1, 0]))
plt.show()
#############################################################################
diff --git a/examples/shapes_and_collections/fancybox_demo.py b/examples/shapes_and_collections/fancybox_demo.py
index a4b434c1b1c0..eebf1de849c9 100644
--- a/examples/shapes_and_collections/fancybox_demo.py
+++ b/examples/shapes_and_collections/fancybox_demo.py
@@ -1,13 +1,11 @@
"""
-=============
-Fancybox Demo
-=============
+===================
+Drawing fancy boxes
+===================
-Plotting fancy boxes with Matplotlib.
-
-The following examples show how to plot boxes with different
-visual properties.
+The following examples show how to plot boxes with different visual properties.
"""
+
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
import matplotlib.patches as mpatch
@@ -25,10 +23,9 @@
for i, stylename in enumerate(sorted(styles)):
fig.text(0.5, (spacing * (len(styles) - i) - 0.5) / figheight, stylename,
- ha="center",
- size=fontsize,
- transform=fig.transFigure,
- bbox=dict(boxstyle=stylename, fc="w", ec="k"))
+ ha="center",
+ size=fontsize,
+ bbox=dict(boxstyle=stylename, fc="w", ec="k"))
plt.show()
diff --git a/examples/subplots_axes_and_figures/axes_demo.py b/examples/subplots_axes_and_figures/axes_demo.py
index 5b07f2f2d820..972567420434 100644
--- a/examples/subplots_axes_and_figures/axes_demo.py
+++ b/examples/subplots_axes_and_figures/axes_demo.py
@@ -3,7 +3,14 @@
Axes Demo
=========
-Example use of ``plt.axes`` to create inset axes within the main plot axes.
+Example use of ``fig.add_axes`` to create inset axes within the main plot axes.
+
+Please see also the :ref:`axes_grid_examples` section, and the following three
+examples:
+
+ - :doc:`/gallery/subplots_axes_and_figures/zoom_inset_axes`
+ - :doc:`/gallery/axes_grid1/inset_locator_demo`
+ - :doc:`/gallery/axes_grid1/inset_locator_demo2`
"""
import matplotlib.pyplot as plt
import numpy as np
@@ -19,27 +26,27 @@
x = np.random.randn(len(t))
s = np.convolve(x, r)[:len(x)] * dt # colored noise
-# the main axes is subplot(111) by default
-plt.plot(t, s)
-plt.xlim(0, 1)
-plt.ylim(1.1 * np.min(s), 2 * np.max(s))
-plt.xlabel('time (s)')
-plt.ylabel('current (nA)')
-plt.title('Gaussian colored noise')
+fig, main_ax = plt.subplots()
+main_ax.plot(t, s)
+main_ax.set_xlim(0, 1)
+main_ax.set_ylim(1.1 * np.min(s), 2 * np.max(s))
+main_ax.set_xlabel('time (s)')
+main_ax.set_ylabel('current (nA)')
+main_ax.set_title('Gaussian colored noise')
# this is an inset axes over the main axes
-a = plt.axes([.65, .6, .2, .2], facecolor='k')
-n, bins, patches = plt.hist(s, 400, density=True)
-plt.title('Probability')
-plt.xticks([])
-plt.yticks([])
+right_inset_ax = fig.add_axes([.65, .6, .2, .2], facecolor='k')
+right_inset_ax.hist(s, 400, density=True)
+right_inset_ax.set_title('Probability')
+right_inset_ax.set_xticks([])
+right_inset_ax.set_yticks([])
# this is another inset axes over the main axes
-a = plt.axes([0.2, 0.6, .2, .2], facecolor='k')
-plt.plot(t[:len(r)], r)
-plt.title('Impulse response')
-plt.xlim(0, 0.2)
-plt.xticks([])
-plt.yticks([])
+left_inset_ax = fig.add_axes([.2, .6, .2, .2], facecolor='k')
+left_inset_ax.plot(t[:len(r)], r)
+left_inset_ax.set_title('Impulse response')
+left_inset_ax.set_xlim(0, 0.2)
+left_inset_ax.set_xticks([])
+left_inset_ax.set_yticks([])
plt.show()
diff --git a/examples/subplots_axes_and_figures/invert_axes.py b/examples/subplots_axes_and_figures/invert_axes.py
index d8c17a1ba81a..15ec55d430bd 100644
--- a/examples/subplots_axes_and_figures/invert_axes.py
+++ b/examples/subplots_axes_and_figures/invert_axes.py
@@ -12,13 +12,14 @@
t = np.arange(0.01, 5.0, 0.01)
s = np.exp(-t)
-plt.plot(t, s)
-plt.xlim(5, 0) # decreasing time
+fig, ax = plt.subplots()
-plt.xlabel('decreasing time (s)')
-plt.ylabel('voltage (mV)')
-plt.title('Should be growing...')
-plt.grid(True)
+ax.plot(t, s)
+ax.set_xlim(5, 0) # decreasing time
+ax.set_xlabel('decreasing time (s)')
+ax.set_ylabel('voltage (mV)')
+ax.set_title('Should be growing...')
+ax.grid(True)
plt.show()
diff --git a/examples/subplots_axes_and_figures/subplots_demo.py b/examples/subplots_axes_and_figures/subplots_demo.py
index c850cec7be6c..6dddeb26ba07 100644
--- a/examples/subplots_axes_and_figures/subplots_demo.py
+++ b/examples/subplots_axes_and_figures/subplots_demo.py
@@ -1,7 +1,7 @@
"""
-================================================
-Creating multiple subplots using ``plt.subplot``
-================================================
+=================================================
+Creating multiple subplots using ``plt.subplots``
+=================================================
`.pyplot.subplots` creates a figure and a grid of subplots with a single call,
while providing reasonable control over how the individual plots are created.
diff --git a/examples/ticks_and_spines/tick-locators.py b/examples/ticks_and_spines/tick-locators.py
index 7586739558a7..bda576c26ea1 100644
--- a/examples/ticks_and_spines/tick-locators.py
+++ b/examples/ticks_and_spines/tick-locators.py
@@ -3,7 +3,9 @@
Tick locators
=============
-Show the different tick locators.
+Tick locators define the position of the ticks.
+
+This example illustrates the usage and effect of the most common locators.
"""
import numpy as np
@@ -11,91 +13,65 @@
import matplotlib.ticker as ticker
-# Setup a plot such that only the bottom spine is shown
-def setup(ax):
+def setup(ax, title):
+ """Set up common parameters for the Axes in the example."""
+ # only show the bottom spine
+ ax.yaxis.set_major_locator(ticker.NullLocator())
ax.spines['right'].set_color('none')
ax.spines['left'].set_color('none')
- ax.yaxis.set_major_locator(ticker.NullLocator())
ax.spines['top'].set_color('none')
+
ax.xaxis.set_ticks_position('bottom')
- ax.tick_params(which='major', width=1.00)
- ax.tick_params(which='major', length=5)
- ax.tick_params(which='minor', width=0.75)
- ax.tick_params(which='minor', length=2.5)
+ ax.tick_params(which='major', width=1.00, length=5)
+ ax.tick_params(which='minor', width=0.75, length=2.5)
ax.set_xlim(0, 5)
ax.set_ylim(0, 1)
- ax.patch.set_alpha(0.0)
+ ax.text(0.0, 0.2, title, transform=ax.transAxes,
+ fontsize=14, fontname='Monospace', color='tab:blue')
-plt.figure(figsize=(8, 6))
-n = 8
+fig, axs = plt.subplots(8, 1, figsize=(8, 6))
# Null Locator
-ax = plt.subplot(n, 1, 1)
-setup(ax)
-ax.xaxis.set_major_locator(ticker.NullLocator())
-ax.xaxis.set_minor_locator(ticker.NullLocator())
-ax.text(0.0, 0.1, "NullLocator()", fontsize=14, transform=ax.transAxes)
+setup(axs[0], title="NullLocator()")
+axs[0].xaxis.set_major_locator(ticker.NullLocator())
+axs[0].xaxis.set_minor_locator(ticker.NullLocator())
# Multiple Locator
-ax = plt.subplot(n, 1, 2)
-setup(ax)
-ax.xaxis.set_major_locator(ticker.MultipleLocator(0.5))
-ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.1))
-ax.text(0.0, 0.1, "MultipleLocator(0.5)", fontsize=14,
- transform=ax.transAxes)
+setup(axs[1], title="MultipleLocator(0.5)")
+axs[1].xaxis.set_major_locator(ticker.MultipleLocator(0.5))
+axs[1].xaxis.set_minor_locator(ticker.MultipleLocator(0.1))
# Fixed Locator
-ax = plt.subplot(n, 1, 3)
-setup(ax)
-majors = [0, 1, 5]
-ax.xaxis.set_major_locator(ticker.FixedLocator(majors))
-minors = np.linspace(0, 1, 11)[1:-1]
-ax.xaxis.set_minor_locator(ticker.FixedLocator(minors))
-ax.text(0.0, 0.1, "FixedLocator([0, 1, 5])", fontsize=14,
- transform=ax.transAxes)
+setup(axs[2], title="FixedLocator([0, 1, 5])")
+axs[2].xaxis.set_major_locator(ticker.FixedLocator([0, 1, 5]))
+axs[2].xaxis.set_minor_locator(ticker.FixedLocator(np.linspace(0.2, 0.8, 4)))
# Linear Locator
-ax = plt.subplot(n, 1, 4)
-setup(ax)
-ax.xaxis.set_major_locator(ticker.LinearLocator(3))
-ax.xaxis.set_minor_locator(ticker.LinearLocator(31))
-ax.text(0.0, 0.1, "LinearLocator(numticks=3)",
- fontsize=14, transform=ax.transAxes)
+setup(axs[3], title="LinearLocator(numticks=3)")
+axs[3].xaxis.set_major_locator(ticker.LinearLocator(3))
+axs[3].xaxis.set_minor_locator(ticker.LinearLocator(31))
# Index Locator
-ax = plt.subplot(n, 1, 5)
-setup(ax)
-ax.plot(range(0, 5), [0]*5, color='white')
-ax.xaxis.set_major_locator(ticker.IndexLocator(base=.5, offset=.25))
-ax.text(0.0, 0.1, "IndexLocator(base=0.5, offset=0.25)",
- fontsize=14, transform=ax.transAxes)
+setup(axs[4], title="IndexLocator(base=0.5, offset=0.25)")
+axs[4].plot(range(0, 5), [0]*5, color='white')
+axs[4].xaxis.set_major_locator(ticker.IndexLocator(base=0.5, offset=0.25))
# Auto Locator
-ax = plt.subplot(n, 1, 6)
-setup(ax)
-ax.xaxis.set_major_locator(ticker.AutoLocator())
-ax.xaxis.set_minor_locator(ticker.AutoMinorLocator())
-ax.text(0.0, 0.1, "AutoLocator()", fontsize=14, transform=ax.transAxes)
+setup(axs[5], title="AutoLocator()")
+axs[5].xaxis.set_major_locator(ticker.AutoLocator())
+axs[5].xaxis.set_minor_locator(ticker.AutoMinorLocator())
# MaxN Locator
-ax = plt.subplot(n, 1, 7)
-setup(ax)
-ax.xaxis.set_major_locator(ticker.MaxNLocator(4))
-ax.xaxis.set_minor_locator(ticker.MaxNLocator(40))
-ax.text(0.0, 0.1, "MaxNLocator(n=4)", fontsize=14, transform=ax.transAxes)
+setup(axs[6], title="MaxNLocator(n=4)")
+axs[6].xaxis.set_major_locator(ticker.MaxNLocator(4))
+axs[6].xaxis.set_minor_locator(ticker.MaxNLocator(40))
# Log Locator
-ax = plt.subplot(n, 1, 8)
-setup(ax)
-ax.set_xlim(10**3, 10**10)
-ax.set_xscale('log')
-ax.xaxis.set_major_locator(ticker.LogLocator(base=10.0, numticks=15))
-ax.text(0.0, 0.1, "LogLocator(base=10, numticks=15)",
- fontsize=15, transform=ax.transAxes)
-
-# Push the top of the top axes outside the figure because we only show the
-# bottom spine.
-plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=1.05)
+setup(axs[7], title="LogLocator(base=10, numticks=15)")
+axs[7].set_xlim(10**3, 10**10)
+axs[7].set_xscale('log')
+axs[7].xaxis.set_major_locator(ticker.LogLocator(base=10, numticks=15))
+plt.tight_layout()
plt.show()
diff --git a/examples/user_interfaces/svg_histogram_sgskip.py b/examples/user_interfaces/svg_histogram_sgskip.py
index 3791fe1ae939..2332fac8a050 100644
--- a/examples/user_interfaces/svg_histogram_sgskip.py
+++ b/examples/user_interfaces/svg_histogram_sgskip.py
@@ -43,9 +43,8 @@
plt.rcParams['svg.fonttype'] = 'none'
-# Apparently, this `register_namespace` method works only with
-# python 2.7 and up and is necessary to avoid garbling the XML name
-# space with ns0.
+# Apparently, this `register_namespace` method is necessary to avoid garbling
+# the XML namespace with ns0.
ET.register_namespace("", "http://www.w3.org/2000/svg")
# Fixing random state for reproducibility
diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 350d4c554aae..825303171424 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -321,7 +321,8 @@ def impl(args, regex, min_ver=None, ignore_exit_code=False):
# at least min_ver (if set); else, raise FileNotFoundError.
try:
output = subprocess.check_output(
- args, stderr=subprocess.STDOUT, universal_newlines=True)
+ args, stderr=subprocess.STDOUT,
+ universal_newlines=True, errors="replace")
except subprocess.CalledProcessError as _cpe:
if ignore_exit_code:
output = _cpe.output
@@ -911,18 +912,16 @@ def _rc_params_in_file(fname, fail_on_error=False):
Unlike `rc_params_from_file`, the configuration class only contains the
parameters specified in the file (i.e. default values are not filled in).
"""
- cnt = 0
rc_temp = {}
with _open_file_or_url(fname) as fd:
try:
- for line in fd:
- cnt += 1
+ for line_no, line in enumerate(fd, 1):
strippedline = line.split('#', 1)[0].strip()
if not strippedline:
continue
tup = strippedline.split(':', 1)
if len(tup) != 2:
- error_details = _error_details_fmt % (cnt, line, fname)
+ error_details = _error_details_fmt % (line_no, line, fname)
_log.warning('Illegal %s', error_details)
continue
key, val = tup
@@ -930,8 +929,8 @@ def _rc_params_in_file(fname, fail_on_error=False):
val = val.strip()
if key in rc_temp:
_log.warning('Duplicate key in file %r line #%d.',
- fname, cnt)
- rc_temp[key] = (val, line, cnt)
+ fname, line_no)
+ rc_temp[key] = (val, line, line_no)
except UnicodeDecodeError:
_log.warning('Cannot decode configuration file %s with encoding '
'%s, check LANG and LC_* variables.',
@@ -942,7 +941,7 @@ def _rc_params_in_file(fname, fail_on_error=False):
config = RcParams()
- for key, (val, line, cnt) in rc_temp.items():
+ for key, (val, line, line_no) in rc_temp.items():
if key in defaultParams:
if fail_on_error:
config[key] = val # try to convert to proper type or raise
@@ -950,7 +949,7 @@ def _rc_params_in_file(fname, fail_on_error=False):
try:
config[key] = val # try to convert to proper type or skip
except Exception as msg:
- error_details = _error_details_fmt % (cnt, line, fname)
+ error_details = _error_details_fmt % (line_no, line, fname)
_log.warning('Bad val %r on %s\n\t%s',
val, error_details, msg)
elif key in _deprecated_ignore_map:
@@ -959,14 +958,13 @@ def _rc_params_in_file(fname, fail_on_error=False):
version, name=key, alternative=alt_key,
addendum="Please update your matplotlibrc.")
else:
- print("""
-Bad key "%s" on line %d in
-%s.
+ version = 'master' if '.post' in __version__ else f'v{__version__}'
+ print(f"""
+Bad key "{key}" on line {line_no} in
+{fname}.
You probably need to get an updated matplotlibrc file from
-http://github.com/matplotlib/matplotlib/blob/master/matplotlibrc.template
-or from the matplotlib source distribution""" % (key, cnt, fname),
- file=sys.stderr)
-
+https://github.com/matplotlib/matplotlib/blob/{version}/matplotlibrc.template
+or from the matplotlib source distribution""", file=sys.stderr)
return config
diff --git a/lib/matplotlib/_constrained_layout.py b/lib/matplotlib/_constrained_layout.py
index a2a70fdc0212..a79b61be6754 100644
--- a/lib/matplotlib/_constrained_layout.py
+++ b/lib/matplotlib/_constrained_layout.py
@@ -280,7 +280,11 @@ def _make_layout_margins(ax, renderer, h_pad, w_pad):
invTransFig = fig.transFigure.inverted().transform_bbox
pos = ax.get_position(original=True)
tightbbox = ax.get_tightbbox(renderer=renderer)
- bbox = invTransFig(tightbbox)
+ if tightbbox is None:
+ bbox = pos
+ else:
+ bbox = invTransFig(tightbbox)
+
# this can go wrong:
if not (np.isfinite(bbox.width) and np.isfinite(bbox.height)):
# just abort, this is likely a bad set of co-ordinates that
diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py
index 8346a4e7323d..628f23eeee00 100644
--- a/lib/matplotlib/animation.py
+++ b/lib/matplotlib/animation.py
@@ -195,7 +195,7 @@ def setup(self, fig, outfile, dpi=None):
Parameters
----------
- fig : `matplotlib.figure.Figure` instance
+ fig : `~matplotlib.figure.Figure`
The figure object that contains the information for frames
outfile : string
The filename of the resulting movie file
@@ -332,9 +332,9 @@ def setup(self, fig, outfile, dpi=None):
Parameters
----------
- fig : matplotlib.figure.Figure
+ fig : `~matplotlib.figure.Figure`
The figure object that contains the information for frames
- outfile : string
+ outfile : str
The filename of the resulting movie file
dpi : int, optional
The DPI (or resolution) for the file. This controls the size
@@ -442,7 +442,7 @@ def setup(self, fig, outfile, dpi=None, frame_prefix='_tmp',
Parameters
----------
- fig : matplotlib.figure.Figure
+ fig : `~matplotlib.figure.Figure`
The figure to grab the rendered frames from.
outfile : str
The filename of the resulting movie file.
@@ -895,7 +895,7 @@ class Animation(object):
Parameters
----------
- fig : matplotlib.figure.Figure
+ fig : `~matplotlib.figure.Figure`
The figure object that is used to get draw, resize, and any
other needed events.
@@ -1398,7 +1398,7 @@ class TimedAnimation(Animation):
Parameters
----------
- fig : matplotlib.figure.Figure
+ fig : `~matplotlib.figure.Figure`
The figure object that is used to get draw, resize, and any
other needed events.
@@ -1481,7 +1481,7 @@ class ArtistAnimation(TimedAnimation):
Parameters
----------
- fig : matplotlib.figure.Figure
+ fig : `~matplotlib.figure.Figure`
The figure object that is used to get draw, resize, and any
other needed events.
@@ -1558,7 +1558,7 @@ class FuncAnimation(TimedAnimation):
Parameters
----------
- fig : matplotlib.figure.Figure
+ fig : `~matplotlib.figure.Figure`
The figure object that is used to get draw, resize, and any
other needed events.
diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py
index 1536b681a116..89fc3ba576d6 100644
--- a/lib/matplotlib/axes/_axes.py
+++ b/lib/matplotlib/axes/_axes.py
@@ -1020,14 +1020,13 @@ def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
Returns
-------
- rectangle : matplotlib.patches.Polygon
+ rectangle : `~matplotlib.patches.Polygon`
Vertical span (rectangle) from (xmin, ymin) to (xmax, ymax).
Other Parameters
----------------
**kwargs
- Optional parameters are properties of the class
- matplotlib.patches.Polygon.
+ Optional parameters are properties of the class `.Polygon`.
See Also
--------
@@ -2164,12 +2163,12 @@ def _convert_dx(dx, x0, xconv, convert):
# removes the units from unit packages like `pint` that
# wrap numpy arrays.
try:
- x0 = x0[0]
+ x0 = cbook.safe_first_element(x0)
except (TypeError, IndexError, KeyError):
x0 = x0
try:
- x = xconv[0]
+ x = cbook.safe_first_element(xconv)
except (TypeError, IndexError, KeyError):
x = xconv
@@ -4538,63 +4537,60 @@ def hexbin(self, x, y, C=None, gridsize=100, bins=None,
reduce_C_function=np.mean, mincnt=None, marginals=False,
**kwargs):
"""
- Make a hexagonal binning plot.
+ Make a 2D hexagonal binning plot of points *x*, *y*.
- Make a hexagonal binning plot of *x* versus *y*, where *x*,
- *y* are 1-D sequences of the same length, *N*. If *C* is *None*
- (the default), this is a histogram of the number of occurrences
- of the observations at (x[i],y[i]).
-
- If *C* is specified, it specifies values at the coordinate
- (x[i], y[i]). These values are accumulated for each hexagonal
- bin and then reduced according to *reduce_C_function*, which
- defaults to `numpy.mean`. (If *C* is specified, it must also
- be a 1-D sequence of the same length as *x* and *y*.)
+ If *C* is *None*, the value of the hexagon is determined by the number
+ of points in the hexagon. Otherwise, *C* specifies values at the
+ coordinate (x[i], y[i]). For each hexagon, these values are reduced
+ using *reduce_C_function*.
Parameters
----------
- x, y : array or masked array
-
- C : array or masked array, optional, default is *None*
+ x, y : array-like
+ The data positions. *x* and *y* must be of the same length.
- gridsize : int or (int, int), optional, default is 100
- The number of hexagons in the *x*-direction, default is
- 100. The corresponding number of hexagons in the
- *y*-direction is chosen such that the hexagons are
- approximately regular. Alternatively, gridsize can be a
- tuple with two elements specifying the number of hexagons
- in the *x*-direction and the *y*-direction.
+ C : array-like, optional
+ If given, these values are accumulated in the bins. Otherwise,
+ every point has a value of 1. Must be of the same length as *x*
+ and *y*.
- bins : 'log' or int or sequence, optional, default is *None*
- If *None*, no binning is applied; the color of each hexagon
- directly corresponds to its count value.
+ gridsize : int or (int, int), default: 100
+ If a single int, the number of hexagons in the *x*-direction.
+ The number of hexagons in the *y*-direction is chosen such that
+ the hexagons are approximately regular.
- If 'log', use a logarithmic scale for the color
- map. Internally, :math:`log_{10}(i+1)` is used to
- determine the hexagon color.
+ Alternatively, if a tuple (*nx*, *ny*), the number of hexagons
+ in the *x*-direction and the *y*-direction.
- If an integer, divide the counts in the specified number
- of bins, and color the hexagons accordingly.
+ bins : 'log' or int or sequence, default: *None*
+ Discretization of the hexagon values.
- If a sequence of values, the values of the lower bound of
- the bins to be used.
+ - If *None*, no binning is applied; the color of each hexagon
+ directly corresponds to its count value.
+ - If 'log', use a logarithmic scale for the color map.
+ Internally, :math:`log_{10}(i+1)` is used to determine the
+ hexagon color. This is equivalent to ``norm=LogNorm()``.
+ - If an integer, divide the counts in the specified number
+ of bins, and color the hexagons accordingly.
+ - If a sequence of values, the values of the lower bound of
+ the bins to be used.
- xscale : {'linear', 'log'}, optional, default is 'linear'
+ xscale : {'linear', 'log'}, default: 'linear'
Use a linear or log10 scale on the horizontal axis.
- yscale : {'linear', 'log'}, optional, default is 'linear'
+ yscale : {'linear', 'log'}, default: 'linear'
Use a linear or log10 scale on the vertical axis.
- mincnt : int > 0, optional, default is *None*
+ mincnt : int > 0, default: *None*
If not *None*, only display cells with more than *mincnt*
- number of points in the cell
+ number of points in the cell.
- marginals : bool, optional, default is *False*
- if marginals is *True*, plot the marginal density as
+ marginals : bool, default: *False*
+ If marginals is *True*, plot the marginal density as
colormapped rectangles along the bottom of the x-axis and
- left of the y-axis
+ left of the y-axis.
- extent : scalar, optional, default is *None*
+ extent : float, default: *None*
The limits of the bins. The default assigns the limits
based on *gridsize*, *x*, *y*, *xscale* and *yscale*.
@@ -4607,55 +4603,67 @@ def hexbin(self, x, y, C=None, gridsize=100, bins=None,
Other Parameters
----------------
- cmap : object, optional, default is *None*
- a :class:`matplotlib.colors.Colormap` instance. If *None*,
- defaults to rc ``image.cmap``.
+ cmap : str or `~matplotlib.colors.Colormap`, optional
+ The Colormap instance or registered colormap name used to map
+ the bin values to colors. Defaults to :rc:`image.cmap`.
- norm : object, optional, default is *None*
- :class:`matplotlib.colors.Normalize` instance is used to
- scale luminance data to 0,1.
+ norm : `~matplotlib.colors.Normalize`, optional
+ The Normalize instance scales the bin values to the canonical
+ colormap range [0, 1] for mapping to colors. By default, the data
+ range is mapped to the colorbar range using linear scaling.
- vmin, vmax : scalar, optional, default is *None*
- *vmin* and *vmax* are used in conjunction with *norm* to
- normalize luminance data. If *None*, the min and max of the
- color array *C* are used. Note if you pass a norm instance
- your settings for *vmin* and *vmax* will be ignored.
+ vmin, vmax : float, optional, default: None
+ The colorbar range. If *None*, suitable min/max values are
+ automatically chosen by the `~.Normalize` instance (defaults to
+ the respective min/max values of the bins in case of the default
+ linear scaling). This is ignored if *norm* is given.
- alpha : scalar between 0 and 1, optional, default is *None*
- the alpha value for the patches
+ alpha : float between 0 and 1, optional
+ The alpha blending value, between 0 (transparent) and 1 (opaque).
- linewidths : scalar, optional, default is *None*
+ linewidths : float, default: *None*
If *None*, defaults to 1.0.
- edgecolors : {'face', 'none', *None*} or color, optional
+ edgecolors : {'face', 'none', *None*} or color, default: 'face'
+ The color of the hexagon edges. Possible values are:
+
+ - 'face': Draw the edges in the same color as the fill color.
+ - 'none': No edges are drawn. This can sometimes lead to unsightly
+ unpainted pixels between the hexagons.
+ - *None*: Draw outlines in the default color.
+ - An explicit matplotlib color.
- If 'face' (the default), draws the edges in the same color as the
- fill color.
+ reduce_C_function : callable, default is `numpy.mean`
+ The function to aggregate *C* within the bins. It is ignored if
+ *C* is not given. This must have the signature::
- If 'none', no edge is drawn; this can sometimes lead to unsightly
- unpainted pixels between the hexagons.
+ def reduce_C_function(C: array) -> float
- If *None*, draws outlines in the default color.
+ Commonly used functions are:
- If a matplotlib color arg, draws outlines in the specified color.
+ - `numpy.mean`: average of the points
+ - `numpy.sum`: integral of the point values
+ - `numpy.max`: value taken from the largest point
+
+ **kwargs : `~matplotlib.collections.PolyCollection` properties
+ All other keyword arguments are passed on to `.PolyCollection`:
+
+ %(PolyCollection)s
Returns
-------
- polycollection
- A `.PolyCollection` instance; use `.PolyCollection.get_array` on
- this to get the counts in each hexagon.
+ polycollection : `~matplotlib.collections.PolyCollection`
+ A `.PolyCollection` defining the hexagonal bins.
+
+ - `.PolyCollection.get_offset` contains a Mx2 array containing
+ the x, y positions of the M hexagon centers.
+ - `.PolyCollection.get_array` contains the values of the M
+ hexagons.
If *marginals* is *True*, horizontal
bar and vertical bar (both PolyCollections) will be attached
to the return collection as attributes *hbar* and *vbar*.
- Notes
- -----
- The standard descriptions of all the
- :class:`~matplotlib.collections.Collection` parameters:
-
- %(Collection)s
-
"""
self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py
index 6ad721561b8e..c2a4d2f42c81 100644
--- a/lib/matplotlib/axes/_base.py
+++ b/lib/matplotlib/axes/_base.py
@@ -3267,7 +3267,8 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False,
reverse = left > right
left, right = self.xaxis.get_major_locator().nonsingular(left, right)
left, right = self.xaxis.limit_range_for_scale(left, right)
- left, right = sorted([left, right], reverse=reverse)
+ # cast to bool to avoid bad interaction between python 3.8 and np.bool_
+ left, right = sorted([left, right], reverse=bool(reverse))
self.viewLim.intervalx = (left, right)
if auto is not None:
@@ -3649,7 +3650,8 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False,
reverse = bottom > top
bottom, top = self.yaxis.get_major_locator().nonsingular(bottom, top)
bottom, top = self.yaxis.limit_range_for_scale(bottom, top)
- bottom, top = sorted([bottom, top], reverse=reverse)
+ # cast to bool to avoid bad interaction between python 3.8 and np.bool_
+ bottom, top = sorted([bottom, top], reverse=bool(reverse))
self.viewLim.intervaly = (bottom, top)
if auto is not None:
@@ -4333,9 +4335,9 @@ def get_tightbbox(self, renderer, call_axes_locator=True,
See Also
--------
- matplotlib.axis.Axes.get_window_extent
+ matplotlib.axes.Axes.get_window_extent
matplotlib.axis.Axis.get_tightbbox
- matplotlib.spines.get_window_extent
+ matplotlib.spines.Spine.get_window_extent
"""
diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py
index f645b4b44a0f..e23b5748cf7c 100644
--- a/lib/matplotlib/axis.py
+++ b/lib/matplotlib/axis.py
@@ -1892,7 +1892,7 @@ def setter(self, vmin, vmax, ignore=False):
setter(self, min(vmin, vmax, oldmin), max(vmin, vmax, oldmax),
ignore=True)
else:
- setter(self, max(vmin, vmax, oldmax), min(vmin, vmax, oldmin),
+ setter(self, max(vmin, vmax, oldmin), min(vmin, vmax, oldmax),
ignore=True)
self.stale = True
@@ -2156,7 +2156,8 @@ def get_minpos(self):
def set_inverted(self, inverted):
# docstring inherited
a, b = self.get_view_interval()
- self.axes.set_xlim(sorted((a, b), reverse=inverted), auto=None)
+ # cast to bool to avoid bad interaction between python 3.8 and np.bool_
+ self.axes.set_xlim(sorted((a, b), reverse=bool(inverted)), auto=None)
def set_default_intervals(self):
# docstring inherited
@@ -2463,7 +2464,8 @@ def get_minpos(self):
def set_inverted(self, inverted):
# docstring inherited
a, b = self.get_view_interval()
- self.axes.set_ylim(sorted((a, b), reverse=inverted), auto=None)
+ # cast to bool to avoid bad interaction between python 3.8 and np.bool_
+ self.axes.set_ylim(sorted((a, b), reverse=bool(inverted)), auto=None)
def set_default_intervals(self):
# docstring inherited
diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py
index 08357ab0b99a..0be54ae14fd7 100644
--- a/lib/matplotlib/backend_bases.py
+++ b/lib/matplotlib/backend_bases.py
@@ -1532,6 +1532,20 @@ def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
self.key = key
+def _is_non_interactive_terminal_ipython(ip):
+ """
+ Return whether we are in a a terminal IPython, but non interactive.
+
+ When in _terminal_ IPython, ip.parent will have and `interact` attribute,
+ if this attribute is False we do not setup eventloop integration as the
+ user will _not_ interact with IPython. In all other case (ZMQKernel, or is
+ interactive), we do.
+ """
+ return (hasattr(ip, 'parent')
+ and (ip.parent is not None)
+ and getattr(ip.parent, 'interact', None) is False)
+
+
class FigureCanvasBase(object):
"""
The canvas the figure renders into.
@@ -1620,15 +1634,8 @@ def _fix_ipython_backend2gui(cls):
backend2gui_rif = {"qt5": "qt", "qt4": "qt", "gtk3": "gtk3",
"wx": "wx", "macosx": "osx"}.get(rif)
if backend2gui_rif:
- pt.backend2gui[get_backend()] = backend2gui_rif
- # Work around pylabtools.find_gui_and_backend always reading from
- # rcParamsOrig.
- orig_origbackend = mpl.rcParamsOrig["backend"]
- try:
- mpl.rcParamsOrig["backend"] = mpl.rcParams["backend"]
- ip.enable_matplotlib()
- finally:
- mpl.rcParamsOrig["backend"] = orig_origbackend
+ if _is_non_interactive_terminal_ipython(ip):
+ ip.enable_gui(backend2gui_rif)
@contextmanager
def _idle_draw_cntx(self):
diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py
index b4562db7f207..f3d1c6459900 100644
--- a/lib/matplotlib/backends/backend_qt5.py
+++ b/lib/matplotlib/backends/backend_qt5.py
@@ -492,7 +492,8 @@ def draw_idle(self):
# current event loop in order to ensure thread affinity and to
# accumulate multiple draw requests from event handling.
# TODO: queued signal connection might be safer than singleShot
- if not (self._draw_pending or self._is_drawing):
+ if not (getattr(self, '_draw_pending', False) or
+ getattr(self, '_is_drawing', False)):
self._draw_pending = True
QtCore.QTimer.singleShot(0, self._draw_idle)
@@ -745,14 +746,14 @@ def buttons(self):
def adj_window(self):
return None
- if is_pyqt5():
- # For some reason, self.setMinimumHeight doesn't seem to carry over to
- # the actual sizeHint, so override it instead in order to make the
- # aesthetic adjustments noted above.
- def sizeHint(self):
- size = super().sizeHint()
+ def sizeHint(self):
+ size = super().sizeHint()
+ if is_pyqt5() and self.canvas._dpi_ratio > 1:
+ # For some reason, self.setMinimumHeight doesn't seem to carry over
+ # to the actual sizeHint, so override it instead in order to make
+ # the aesthetic adjustments noted above.
size.setHeight(max(48, size.height()))
- return size
+ return size
def edit_parameters(self):
axes = self.canvas.figure.get_axes()
diff --git a/lib/matplotlib/backends/backend_qt5agg.py b/lib/matplotlib/backends/backend_qt5agg.py
index 4dec3b9cb0c4..f1fc3555863d 100644
--- a/lib/matplotlib/backends/backend_qt5agg.py
+++ b/lib/matplotlib/backends/backend_qt5agg.py
@@ -38,16 +38,21 @@ def paintEvent(self, event):
painter = QtGui.QPainter(self)
- rect = event.rect()
- left = rect.left()
- top = rect.top()
- width = rect.width()
- height = rect.height()
# See documentation of QRect: bottom() and right() are off by 1, so use
# left() + width() and top() + height().
- bbox = Bbox(
- [[left, self.renderer.height - (top + height * self._dpi_ratio)],
- [left + width * self._dpi_ratio, self.renderer.height - top]])
+ rect = event.rect()
+ # scale rect dimensions using the screen dpi ratio to get
+ # correct values for the Figure coordinates (rather than QT5's coords)
+ width = rect.width() * self._dpi_ratio
+ height = rect.height() * self._dpi_ratio
+ left, top = self.mouseEventCoords(rect.topLeft())
+ # shift the "top" by the height of the image to get the
+ # correct corner for our coordinate system
+ bottom = top - height
+ # same with the right side of the image
+ right = left + width
+ # create a buffer using the image bounding box
+ bbox = Bbox([[left, bottom], [right, top]])
reg = self.copy_from_bbox(bbox)
buf = cbook._unmultiplied_rgba8888_to_premultiplied_argb32(
memoryview(reg))
@@ -60,8 +65,9 @@ def paintEvent(self, event):
if hasattr(qimage, 'setDevicePixelRatio'):
# Not available on Qt4 or some older Qt5.
qimage.setDevicePixelRatio(self._dpi_ratio)
- origin = QtCore.QPoint(left, top)
- painter.drawImage(origin / self._dpi_ratio, qimage)
+ # set origin using original QT coordinates
+ origin = QtCore.QPoint(rect.left(), rect.top())
+ painter.drawImage(origin, qimage)
# Adjust the buf reference count to work around a memory
# leak bug in QImage under PySide on Python 3.
if QT_API in ('PySide', 'PySide2'):
diff --git a/lib/matplotlib/backends/web_backend/js/nbagg_mpl.js b/lib/matplotlib/backends/web_backend/js/nbagg_mpl.js
index a389e79183db..a66e450cd90c 100644
--- a/lib/matplotlib/backends/web_backend/js/nbagg_mpl.js
+++ b/lib/matplotlib/backends/web_backend/js/nbagg_mpl.js
@@ -166,12 +166,9 @@ mpl.figure.prototype._key_event_extra = function(event, name) {
// Check for shift+enter
if (event.shiftKey && event.which == 13) {
this.canvas_div.blur();
- event.shiftKey = false;
- // Send a "J" for go to next cell
- event.which = 74;
- event.keyCode = 74;
- manager.command_mode();
- manager.handle_keydown(event);
+ // select the cell after this one
+ var index = IPython.notebook.find_cell_index(this.cell_info[0]);
+ IPython.notebook.select(index + 1);
}
}
diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py
index e2ba3948679d..ed08c5be2ce5 100644
--- a/lib/matplotlib/cbook/__init__.py
+++ b/lib/matplotlib/cbook/__init__.py
@@ -1399,7 +1399,13 @@ def _check_1d(x):
return np.atleast_1d(x)
else:
try:
- x[:, None]
+ ndim = x[:, None].ndim
+ # work around https://github.com/pandas-dev/pandas/issues/27775
+ # which mean the shape is not as expected. That this ever worked
+ # was an unintentional quirk of pandas the above line will raise
+ # an exception in the future.
+ if ndim < 2:
+ return np.atleast_1d(x)
return x
except (IndexError, TypeError):
return np.atleast_1d(x)
diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py
index b7a7219cae75..74c8b936da4d 100644
--- a/lib/matplotlib/collections.py
+++ b/lib/matplotlib/collections.py
@@ -1470,12 +1470,15 @@ def __init__(self,
.. plot:: gallery/lines_bars_and_markers/eventcollection_demo.py
"""
-
+ if positions is None:
+ raise ValueError('positions must be an array-like object')
+ # Force a copy of positions
+ positions = np.array(positions, copy=True)
segment = (lineoffset + linelength / 2.,
lineoffset - linelength / 2.)
- if positions is None or len(positions) == 0:
+ if positions.size == 0:
segments = []
- elif hasattr(positions, 'ndim') and positions.ndim > 1:
+ elif positions.ndim > 1:
raise ValueError('positions cannot be an array with more than '
'one dimension.')
elif (orientation is None or orientation.lower() == 'none' or
diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py
index 1e47c00c79b2..585381d9a7a8 100644
--- a/lib/matplotlib/colors.py
+++ b/lib/matplotlib/colors.py
@@ -1685,7 +1685,7 @@ def shade_normals(self, normals, fraction=1.):
# visually appears better than a "hard" clip.
intensity -= imin
intensity /= (imax - imin)
- intensity = np.clip(intensity, 0, 1, intensity)
+ intensity = np.clip(intensity, 0, 1)
return intensity
diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py
index 46ba5f8defb1..45b222154076 100644
--- a/lib/matplotlib/contour.py
+++ b/lib/matplotlib/contour.py
@@ -1696,7 +1696,7 @@ def _initialize_x_y(self, z):
maps the level values to colors.
Defaults to :rc:`image.cmap`.
- If given, *colors* take precedence over *cmap*.
+ If both *colors* and *cmap* are given, an error is raised.
norm : `~matplotlib.colors.Normalize`, optional
If a colormap is used, the `.Normalize` instance scales the level
diff --git a/lib/matplotlib/dates.py b/lib/matplotlib/dates.py
index fc87dca2e52f..54f903ddc6b3 100644
--- a/lib/matplotlib/dates.py
+++ b/lib/matplotlib/dates.py
@@ -9,7 +9,7 @@
----------------------
Matplotlib represents dates using floating point numbers specifying the number
of days since 0001-01-01 UTC, plus 1. For example, 0001-01-01, 06:00 is 1.25,
-not 0.25. Values < 1, i.e. dates before 0001-01-01 UTC are not supported.
+not 0.25. Values < 1, i.e. dates before 0001-01-01 UTC, are not supported.
There are a number of helper functions to convert between :mod:`datetime`
objects and Matplotlib dates:
@@ -45,10 +45,10 @@
Out[1]: 732401
All the Matplotlib date converters, tickers and formatters are timezone aware.
-If no explicit timezone is provided, the rcParam ``timezone`` is assumed. If
-you want to use a custom time zone, pass a :class:`datetime.tzinfo` instance
-with the tz keyword argument to :func:`num2date`, :func:`.plot_date`, and any
-custom date tickers or locators you create.
+If no explicit timezone is provided, :rc:`timezone` is assumed. If you want to
+use a custom time zone, pass a `datetime.tzinfo` instance with the tz keyword
+argument to `num2date`, `~.Axes.plot_date`, and any custom date tickers or
+locators you create.
A wide range of specific and general purpose date tick locators and
formatters are provided in this module. See
@@ -86,54 +86,51 @@
rule = rrulewrapper(YEARLY, byeaster=1, interval=5)
loc = RRuleLocator(rule)
-Here are all the date tickers:
+The available date tickers are:
- * :class:`MicrosecondLocator`: locate microseconds
+* `MicrosecondLocator`: locate microseconds
- * :class:`SecondLocator`: locate seconds
+* `SecondLocator`: locate seconds
- * :class:`MinuteLocator`: locate minutes
+* `MinuteLocator`: locate minutes
- * :class:`HourLocator`: locate hours
+* `HourLocator`: locate hours
- * :class:`DayLocator`: locate specified days of the month
+* `DayLocator`: locate specified days of the month
- * :class:`WeekdayLocator`: Locate days of the week, e.g., MO, TU
+* `WeekdayLocator`: Locate days of the week, e.g., MO, TU
- * :class:`MonthLocator`: locate months, e.g., 7 for july
+* `MonthLocator`: locate months, e.g., 7 for july
- * :class:`YearLocator`: locate years that are multiples of base
+* `YearLocator`: locate years that are multiples of base
- * :class:`RRuleLocator`: locate using a `matplotlib.dates.rrulewrapper`.
- `.rrulewrapper` is a simple wrapper around dateutil_'s `dateutil.rrule`
- which allow almost arbitrary date tick specifications. See :doc:`rrule
- example `.
+* `RRuleLocator`: locate using a `matplotlib.dates.rrulewrapper`.
+ `.rrulewrapper` is a simple wrapper around dateutil_'s `dateutil.rrule` which
+ allow almost arbitrary date tick specifications. See :doc:`rrule example
+ `.
- * :class:`AutoDateLocator`: On autoscale, this class picks the best
- :class:`DateLocator` (e.g., :class:`RRuleLocator`)
- to set the view limits and the tick
- locations. If called with ``interval_multiples=True`` it will
- make ticks line up with sensible multiples of the tick intervals. E.g.
- if the interval is 4 hours, it will pick hours 0, 4, 8, etc as ticks.
- This behaviour is not guaranteed by default.
+* `AutoDateLocator`: On autoscale, this class picks the best `DateLocator`
+ (e.g., `RRuleLocator`) to set the view limits and the tick locations. If
+ called with ``interval_multiples=True`` it will make ticks line up with
+ sensible multiples of the tick intervals. E.g. if the interval is 4 hours,
+ it will pick hours 0, 4, 8, etc as ticks. This behaviour is not guaranteed
+ by default.
Date formatters
---------------
-Here all all the date formatters:
+The available date formatters are:
- * :class:`AutoDateFormatter`: attempts to figure out the best format
- to use. This is most useful when used with the :class:`AutoDateLocator`.
+* `AutoDateFormatter`: attempts to figure out the best format to use. This is
+ most useful when used with the `AutoDateLocator`.
- * :class:`ConciseDateFormatter`: also attempts to figure out the best
- format to use, and to make the format as compact as possible while
- still having complete date information. This is most useful when used
- with the :class:`AutoDateLocator`.
+* `ConciseDateFormatter`: also attempts to figure out the best format to use,
+ and to make the format as compact as possible while still having complete
+ date information. This is most useful when used with the `AutoDateLocator`.
- * :class:`DateFormatter`: use :func:`strftime` format strings
+* `DateFormatter`: use `strftime` format strings.
- * :class:`IndexDateFormatter`: date plots with implicit *x*
- indexing.
+* `IndexDateFormatter`: date plots with implicit *x* indexing.
"""
import datetime
@@ -839,7 +836,7 @@ def __init__(self, locator, tz=None, formats=None, offset_formats=None,
# like 1 Jan can just be labled "Jan". 02:02:00 can
# just be labeled 02:02.
if zero_formats:
- if len(formats) != 6:
+ if len(zero_formats) != 6:
raise ValueError('zero_formats argument must be a list of '
'6 format strings (or None)')
self.zero_formats = zero_formats
diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py
index 1b31edcdd41c..953adbc6195a 100644
--- a/lib/matplotlib/image.py
+++ b/lib/matplotlib/image.py
@@ -1359,8 +1359,8 @@ def imread(fname, format=None):
Parameters
----------
fname : str or file-like
- The image file to read. This can be a filename, a URL or a Python
- file-like object opened in read-binary mode.
+ The image file to read: a filename, a URL or a file-like object opened
+ in read-binary mode.
format : str, optional
The image file format assumed for reading the data. If not
given, the format is deduced from the filename. If nothing can
@@ -1443,8 +1443,8 @@ def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None,
Parameters
----------
- fname : str or PathLike file-like
- A path or a Python file-like object to store the image in.
+ fname : str or PathLike or file-like
+ A path or a file-like object to store the image in.
If *format* is not set, then the output format is inferred from the
extension of *fname*, if any, and from :rc:`savefig.format` otherwise.
If *format* is set, it determines the output format.
diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py
index 4737b5d88056..22941d05d0e8 100644
--- a/lib/matplotlib/lines.py
+++ b/lib/matplotlib/lines.py
@@ -1099,6 +1099,7 @@ def set_linewidth(self, w):
Parameters
----------
w : float
+ Line width, in points.
"""
w = float(w)
@@ -1231,6 +1232,7 @@ def set_markeredgewidth(self, ew):
Parameters
----------
ew : float
+ Marker edge width, in points.
"""
if ew is None:
ew = rcParams['lines.markeredgewidth']
@@ -1273,6 +1275,7 @@ def set_markersize(self, sz):
Parameters
----------
sz : float
+ Marker size, in points.
"""
sz = float(sz)
if self._markersize != sz:
diff --git a/lib/matplotlib/offsetbox.py b/lib/matplotlib/offsetbox.py
index 2d5d6cb37906..a74bc2e9c803 100644
--- a/lib/matplotlib/offsetbox.py
+++ b/lib/matplotlib/offsetbox.py
@@ -147,9 +147,11 @@ def __init__(self, *args, **kwargs):
def set_figure(self, fig):
"""
- Set the figure
+ Set the `.Figure` for the `.OffsetBox` and all its children.
- accepts a class:`~matplotlib.figure.Figure` instance
+ Parameters
+ ----------
+ fig : `~matplotlib.figure.Figure`
"""
martist.Artist.set_figure(self, fig)
for c in self.get_children():
@@ -164,6 +166,29 @@ def axes(self, ax):
c.axes = ax
def contains(self, mouseevent):
+ """
+ Delegate the mouse event contains-check to the children.
+
+ As a container, the `.OffsetBox` does not respond itself to
+ mouseevents.
+
+ Parameters
+ ----------
+ mouseevent : `matplotlib.backend_bases.MouseEvent`
+
+ Returns
+ -------
+ contains : bool
+ Whether any values are within the radius.
+ details : dict
+ An artist-specific dictionary of details of the event context,
+ such as which points are contained in the pick radius. See the
+ individual Artist subclasses for details.
+
+ See Also
+ --------
+ .Artist.contains
+ """
for c in self.get_children():
a, b = c.contains(mouseevent)
if a:
@@ -177,8 +202,10 @@ def set_offset(self, xy):
Parameters
----------
xy : (float, float) or callable
- The (x,y) coordinates of the offset in display units.
- A callable must have the signature::
+ The (x, y) coordinates of the offset in display units. These can
+ either be given explicitly as a tuple (x, y), or by providing a
+ function that converts the extent into the offset. This function
+ must have the signature::
def offset(width, height, xdescent, ydescent, renderer) \
-> (float, float)
@@ -188,9 +215,18 @@ def offset(width, height, xdescent, ydescent, renderer) \
def get_offset(self, width, height, xdescent, ydescent, renderer):
"""
- Get the offset
+ Return the offset as a tuple (x, y).
+
+ The extent parameters have to be provided to handle the case where the
+ offset is dynamically determined by a callable (see
+ `~.OffsetBox.set_offset`).
+
+ Parameters
+ ----------
+ width, height, xdescent, ydescent
+ Extent parameters.
+ renderer : `.RendererBase` subclass
- accepts extent of the box
"""
return (self._offset(width, height, xdescent, ydescent, renderer)
if callable(self._offset)
@@ -198,48 +234,60 @@ def get_offset(self, width, height, xdescent, ydescent, renderer):
def set_width(self, width):
"""
- Set the width
+ Set the width of the box.
- accepts float
+ Parameters
+ ----------
+ width : float
"""
self.width = width
self.stale = True
def set_height(self, height):
"""
- Set the height
+ Set the height of the box.
- accepts float
+ Parameters
+ ----------
+ height : float
"""
self.height = height
self.stale = True
def get_visible_children(self):
- """
- Return a list of visible artists it contains.
- """
+ r"""Return a list of the visible child `.Artist`\s."""
return [c for c in self._children if c.get_visible()]
def get_children(self):
- """
- Return a list of artists it contains.
- """
+ r"""Return a list of the child `.Artist`\s."""
return self._children
def get_extent_offsets(self, renderer):
- raise Exception("")
-
- def get_extent(self, renderer):
"""
- Return with, height, xdescent, ydescent of box
+ Update offset of the children and return the extent of the box.
+
+ Parameters
+ ----------
+ renderer : `.RendererBase` subclass
+
+ Returns
+ -------
+ width
+ height
+ xdescent
+ ydescent
+ list of (xoffset, yoffset) pairs
"""
+ raise NotImplementedError(
+ "get_extent_offsets must be overridden in derived classes.")
+
+ def get_extent(self, renderer):
+ """Return a tuple ``width, height, xdescent, ydescent`` of the box."""
w, h, xd, yd, offsets = self.get_extent_offsets(renderer)
return w, h, xd, yd
def get_window_extent(self, renderer):
- '''
- get the bounding box in display space.
- '''
+ """Return the bounding box (`.Bbox`) in display space."""
w, h, xd, yd, offsets = self.get_extent_offsets(renderer)
px, py = self.get_offset(w, h, xd, yd, renderer)
return mtransforms.Bbox.from_bounds(px - xd, py - yd, w, h)
@@ -249,7 +297,6 @@ def draw(self, renderer):
Update the location of children if necessary and draw them
to the given *renderer*.
"""
-
width, height, xdescent, ydescent, offsets = self.get_extent_offsets(
renderer)
@@ -271,23 +318,29 @@ def __init__(self, pad=None, sep=None, width=None, height=None,
Parameters
----------
pad : float, optional
- Boundary pad.
+ The boundary padding in points.
sep : float, optional
- Spacing between items.
+ The spacing between items in points.
- width : float, optional
+ width, height : float, optional
+ Width and height of the container box in pixels, calculated if
+ *None*.
+
+ align : {'top', 'bottom', 'left', 'right', 'center', 'baseline'}
+ Alignment of boxes.
- height : float, optional
- Width and height of the container box, calculated if
- `None`.
+ mode : {'fixed', 'expand', 'equal'}
+ The packing mode.
- align : str, optional
- Alignment of boxes. Can be one of ``top``, ``bottom``,
- ``left``, ``right``, ``center`` and ``baseline``
+ - 'fixed' packs the given `.Artists` tight with *sep* spacing.
+ - 'expand' uses the maximal available space to distribute the
+ artists with equal spacing in between.
+ - 'equal': Each artist an equal fraction of the available space
+ and is left-aligned (or top-aligned) therein.
- mode : str, optional
- Packing mode.
+ children : list of `.Artist`
+ The artists to pack.
Notes
-----
@@ -319,23 +372,29 @@ def __init__(self, pad=None, sep=None, width=None, height=None,
Parameters
----------
pad : float, optional
- Boundary pad.
+ The boundary padding in points.
sep : float, optional
- Spacing between items.
+ The spacing between items in points.
- width : float, optional
+ width, height : float, optional
+ Width and height of the container box in pixels, calculated if
+ *None*.
- height : float, optional
+ align : {'top', 'bottom', 'left', 'right', 'center', 'baseline'}
+ Alignment of boxes.
- width and height of the container box, calculated if
- `None`.
+ mode : {'fixed', 'expand', 'equal'}
+ The packing mode.
- align : str, optional
- Alignment of boxes.
+ - 'fixed' packs the given `.Artists` tight with *sep* spacing.
+ - 'expand' uses the maximal available space to distribute the
+ artists with equal spacing in between.
+ - 'equal': Each artist an equal fraction of the available space
+ and is left-aligned (or top-aligned) therein.
- mode : str, optional
- Packing mode.
+ children : list of `.Artist`
+ The artists to pack.
Notes
-----
@@ -346,10 +405,7 @@ def __init__(self, pad=None, sep=None, width=None, height=None,
super().__init__(pad, sep, width, height, align, mode, children)
def get_extent_offsets(self, renderer):
- """
- update offset of childrens and return the extents of the box
- """
-
+ # docstring inherited
dpicor = renderer.points_to_pixels(1.)
pad = self.pad * dpicor
sep = self.sep * dpicor
@@ -395,22 +451,29 @@ def __init__(self, pad=None, sep=None, width=None, height=None,
Parameters
----------
pad : float, optional
- Boundary pad.
+ The boundary padding in points.
sep : float, optional
- Spacing between items.
+ The spacing between items in points.
+
+ width, height : float, optional
+ Width and height of the container box in pixels, calculated if
+ *None*.
- width : float, optional
+ align : {'top', 'bottom', 'left', 'right', 'center', 'baseline'}
+ Alignment of boxes.
- height : float, optional
- Width and height of the container box, calculated if
- `None`.
+ mode : {'fixed', 'expand', 'equal'}
+ The packing mode.
- align : str
- Alignment of boxes.
+ - 'fixed' packs the given `.Artists` tight with *sep* spacing.
+ - 'expand' uses the maximal available space to distribute the
+ artists with equal spacing in between.
+ - 'equal': Each artist an equal fraction of the available space
+ and is left-aligned (or top-aligned) therein.
- mode : str
- Packing mode.
+ children : list of `.Artist`
+ The artists to pack.
Notes
-----
@@ -421,9 +484,7 @@ def __init__(self, pad=None, sep=None, width=None, height=None,
super().__init__(pad, sep, width, height, align, mode, children)
def get_extent_offsets(self, renderer):
- """
- update offset of children and return the extents of the box
- """
+ # docstring inherited
dpicor = renderer.points_to_pixels(1.)
pad = self.pad * dpicor
sep = self.sep * dpicor
@@ -458,20 +519,30 @@ def get_extent_offsets(self, renderer):
return (width + 2 * pad, height + 2 * pad,
xdescent + pad, ydescent + pad,
- list(zip(xoffsets, yoffsets)))
+ list(zip(xoffsets, yoffsets)))
class PaddedBox(OffsetBox):
+ """
+ A container to add a padding around an `.Artist`.
+
+ The `.PaddedBox` contains a `.FancyBboxPatch` that is used to visualize
+ it when rendering.
+ """
def __init__(self, child, pad=None, draw_frame=False, patch_attrs=None):
"""
- *pad* : boundary pad
-
- .. note::
- *pad* need to given in points and will be
- scale with the renderer dpi, while *width* and *height*
- need to be in pixels.
+ Parameters
+ ----------
+ child : `~matplotlib.artist.Artist`
+ The contained `.Artist`.
+ pad : float
+ The padding in points. This will be scaled with the renderer dpi.
+ In contrast *width* and *hight* are in *pixel* and thus not scaled.
+ draw_frame : bool
+ Whether to draw the contained `.FancyBboxPatch`.
+ patch_attrs : dict or None
+ Additional parameters passed to the contained `.FancyBboxPatch`.
"""
-
super().__init__()
self.pad = pad
@@ -492,10 +563,7 @@ def __init__(self, child, pad=None, draw_frame=False, patch_attrs=None):
self._drawFrame = draw_frame
def get_extent_offsets(self, renderer):
- """
- update offset of childrens and return the extents of the box
- """
-
+ # docstring inherited.
dpicor = renderer.points_to_pixels(1.)
pad = self.pad * dpicor
@@ -510,7 +578,6 @@ def draw(self, renderer):
Update the location of children if necessary and draw them
to the given *renderer*.
"""
-
width, height, xdescent, ydescent, offsets = self.get_extent_offsets(
renderer)
diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py
index dcbb84750862..b581de840dd9 100644
--- a/lib/matplotlib/patches.py
+++ b/lib/matplotlib/patches.py
@@ -1497,7 +1497,7 @@ def _recompute_transform(self):
def get_path(self):
"""
- Return the vertices of the rectangle
+ Return the path of the ellipse
"""
return self._path
@@ -4592,7 +4592,11 @@ def _check_xy(self, renderer):
if b or (b is None and self.coords1 == "data"):
x, y = self.xy1
xy_pixel = self._get_xy(x, y, self.coords1, self.axesA)
- if not self.axes.contains_point(xy_pixel):
+ if self.axesA is None:
+ axes = self.axes
+ else:
+ axes = self.axesA
+ if not axes.contains_point(xy_pixel):
return False
if b or (b is None and self.coords2 == "data"):
diff --git a/lib/matplotlib/projections/polar.py b/lib/matplotlib/projections/polar.py
index e8837a7a7340..566edac10146 100644
--- a/lib/matplotlib/projections/polar.py
+++ b/lib/matplotlib/projections/polar.py
@@ -445,11 +445,11 @@ class _ThetaShift(mtransforms.ScaledTranslation):
Parameters
----------
- axes : matplotlib.axes.Axes
+ axes : `~matplotlib.axes.Axes`
The owning axes; used to determine limits.
pad : float
The padding to apply, in points.
- start : str, {'min', 'max', 'rlabel'}
+ mode : {'min', 'max', 'rlabel'}
Whether to shift away from the start (``'min'``) or the end (``'max'``)
of the axes, or using the rlabel position (``'rlabel'``).
"""
diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py
index ce66bd894838..88d13ed3eab4 100644
--- a/lib/matplotlib/pyplot.py
+++ b/lib/matplotlib/pyplot.py
@@ -790,7 +790,7 @@ def axes(arg=None, **kwargs):
Parameters
----------
- arg : { None, 4-tuple, Axes }
+ arg : None or 4-tuple
The exact behavior of this function depends on the type:
- *None*: A new full window axes is added using
@@ -798,18 +798,11 @@ def axes(arg=None, **kwargs):
- 4-tuple of floats *rect* = ``[left, bottom, width, height]``.
A new axes is added with dimensions *rect* in normalized
(0, 1) units using `~.Figure.add_axes` on the current figure.
- - `~.axes.Axes`: This is equivalent to `.pyplot.sca`.
- It sets the current axes to *arg*. Note: This implicitly
- changes the current figure to the parent of *arg*.
-
- .. note:: The use of an `.axes.Axes` as an argument is deprecated
- and will be removed in v3.0. Please use `.pyplot.sca`
- instead.
projection : {None, 'aitoff', 'hammer', 'lambert', 'mollweide', \
'polar', 'rectilinear', str}, optional
The projection type of the `~.axes.Axes`. *str* is the name of
- a costum projection, see `~matplotlib.projections`. The default
+ a custom projection, see `~matplotlib.projections`. The default
None results in a 'rectilinear' projection.
polar : boolean, optional
@@ -961,7 +954,7 @@ def subplot(*args, **kwargs):
projection : {None, 'aitoff', 'hammer', 'lambert', 'mollweide', \
'polar', 'rectilinear', str}, optional
The projection type of the subplot (`~.axes.Axes`). *str* is the name
- of a costum projection, see `~matplotlib.projections`. The default
+ of a custom projection, see `~matplotlib.projections`. The default
None results in a 'rectilinear' projection.
polar : boolean, optional
@@ -2348,7 +2341,8 @@ def getname_val(identifier):
# requested, ignore rcParams['backend'] and force selection of a backend that
# is compatible with the current running interactive framework.
if (rcParams["backend_fallback"]
- and dict.__getitem__(rcParams, "backend") in _interactive_bk
+ and dict.__getitem__(rcParams, "backend") in (
+ set(_interactive_bk) - {'WebAgg', 'nbAgg'})
and _get_running_interactive_framework()):
dict.__setitem__(rcParams, "backend", rcsetup._auto_backend_sentinel)
# Set up the backend.
diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py
index 17d5d7a6dc47..25de00219dc0 100644
--- a/lib/matplotlib/rcsetup.py
+++ b/lib/matplotlib/rcsetup.py
@@ -461,6 +461,19 @@ def validate_fontsize(s):
validate_fontsizelist = _listify_validator(validate_fontsize)
+def validate_fontweight(s):
+ weights = [
+ 'ultralight', 'light', 'normal', 'regular', 'book', 'medium', 'roman',
+ 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 'black']
+ # Note: Historically, weights have been case-sensitive in Matplotlib
+ if s in weights:
+ return s
+ try:
+ return int(s)
+ except (ValueError, TypeError):
+ raise ValueError(f'{s} is not a valid font weight.')
+
+
def validate_font_properties(s):
parse_fontconfig_pattern(s)
return s
@@ -1113,7 +1126,7 @@ def _validate_linestyle(ls):
'font.style': ['normal', validate_string],
'font.variant': ['normal', validate_string],
'font.stretch': ['normal', validate_string],
- 'font.weight': ['normal', validate_string],
+ 'font.weight': ['normal', validate_fontweight],
'font.size': [10, validate_float], # Base font size in points
'font.serif': [['DejaVu Serif', 'Bitstream Vera Serif',
'Computer Modern Roman',
@@ -1190,7 +1203,7 @@ def _validate_linestyle(ls):
'axes.titlesize': ['large', validate_fontsize], # fontsize of the
# axes title
- 'axes.titleweight': ['normal', validate_string], # font weight of axes title
+ 'axes.titleweight': ['normal', validate_fontweight], # font weight of axes title
'axes.titlepad': [6.0, validate_float], # pad from axes top to title in points
'axes.grid': [False, validate_bool], # display grid or not
'axes.grid.which': ['major', validate_axis_locator], # set whether the gid are by
@@ -1202,7 +1215,7 @@ def _validate_linestyle(ls):
'axes.labelsize': ['medium', validate_fontsize], # fontsize of the
# x any y labels
'axes.labelpad': [4.0, validate_float], # space between label and axis
- 'axes.labelweight': ['normal', validate_string], # fontsize of the x any y labels
+ 'axes.labelweight': ['normal', validate_fontweight], # fontsize of the x any y labels
'axes.labelcolor': ['black', validate_color], # color of axis label
'axes.formatter.limits': [[-7, 7], validate_nseq_int(2)],
# use scientific notation if log10
@@ -1340,7 +1353,7 @@ def _validate_linestyle(ls):
## figure props
# figure title
'figure.titlesize': ['large', validate_fontsize],
- 'figure.titleweight': ['normal', validate_string],
+ 'figure.titleweight': ['normal', validate_fontweight],
# figure size in inches: width by height
'figure.figsize': [[6.4, 4.8], validate_nseq_float(2)],
diff --git a/lib/matplotlib/sphinxext/plot_directive.py b/lib/matplotlib/sphinxext/plot_directive.py
index 8d9996c13830..5ca7b8e66d30 100644
--- a/lib/matplotlib/sphinxext/plot_directive.py
+++ b/lib/matplotlib/sphinxext/plot_directive.py
@@ -367,7 +367,7 @@ def remove_coding(text):
TEMPLATE = """
{{ source_code }}
-{{ only_html }}
+.. only:: html
{% if source_link or (html_show_formats and not multi_image) %}
(
@@ -403,27 +403,15 @@ def remove_coding(text):
{{ caption }}
{% endfor %}
-{{ only_latex }}
+.. only:: not html
{% for img in images %}
- {% if 'pdf' in img.formats -%}
- .. figure:: {{ build_dir }}/{{ img.basename }}.pdf
+ .. figure:: {{ build_dir }}/{{ img.basename }}.*
{% for option in options -%}
{{ option }}
{% endfor %}
{{ caption }}
- {% endif -%}
- {% endfor %}
-
-{{ only_texinfo }}
-
- {% for img in images %}
- .. image:: {{ build_dir }}/{{ img.basename }}.png
- {% for option in options -%}
- {{ option }}
- {% endfor %}
-
{% endfor %}
"""
@@ -794,10 +782,6 @@ def run(arguments, content, options, state_machine, state, lineno):
':%s: %s' % (key, val) for key, val in options.items()
if key in ('alt', 'height', 'width', 'scale', 'align', 'class')]
- only_html = ".. only:: html"
- only_latex = ".. only:: latex"
- only_texinfo = ".. only:: texinfo"
-
# Not-None src_link signals the need for a source link in the generated
# html
if j == 0 and config.plot_html_show_source_link:
@@ -811,9 +795,6 @@ def run(arguments, content, options, state_machine, state, lineno):
build_dir=build_dir_link,
source_link=src_link,
multi_image=len(images) > 1,
- only_html=only_html,
- only_latex=only_latex,
- only_texinfo=only_texinfo,
options=opts,
images=images,
source_code=source_code,
diff --git a/lib/matplotlib/table.py b/lib/matplotlib/table.py
index 8fb5c4708cd7..c2f4379d9a9e 100644
--- a/lib/matplotlib/table.py
+++ b/lib/matplotlib/table.py
@@ -712,7 +712,7 @@ def table(ax,
colColours : list of matplotlib color specs, optional
The colors of the column header cells.
- rowLoc : {'left', 'center', 'right'}, optional, default: 'left'
+ colLoc : {'left', 'center', 'right'}, optional, default: 'left'
The text alignment of the column header cells.
loc : str, optional
diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py
index 3ffcde798c96..8ff5ac45d27d 100644
--- a/lib/matplotlib/tests/test_axes.py
+++ b/lib/matplotlib/tests/test_axes.py
@@ -1592,6 +1592,14 @@ def test_bar_pandas(pd):
ax.plot(dates, baseline, color='orange', lw=4)
+def test_bar_pandas_indexed(pd):
+ # Smoke test for indexed pandas
+ df = pd.DataFrame({"x": [1., 2., 3.], "width": [.2, .4, .6]},
+ index=[1, 2, 3])
+ fig, ax = plt.subplots()
+ ax.bar(df.x, 1., width=df.width)
+
+
@image_comparison(baseline_images=['hist_log'],
remove_text=True)
def test_hist_log():
@@ -5522,6 +5530,12 @@ def test_pandas_errorbar_indexing(pd):
ax.errorbar('x', 'y', xerr='xe', yerr='ye', data=df)
+def test_pandas_index_shape(pd):
+ df = pd.DataFrame({"XX": [4, 5, 6], "YY": [7, 1, 2]})
+ fig, ax = plt.subplots()
+ ax.plot(df.index, df['YY'])
+
+
def test_pandas_indexing_hist(pd):
ser_1 = pd.Series(data=[1, 2, 2, 3, 3, 4, 4, 4, 4, 5])
ser_2 = ser_1.iloc[1:]
@@ -6411,3 +6425,10 @@ def test_bar_errbar_zorder():
assert capline.zorder > bar.zorder
for barlinecol in barlinecols:
assert barlinecol.zorder > bar.zorder
+
+
+def test_set_ticks_inverted():
+ fig, ax = plt.subplots()
+ ax.invert_xaxis()
+ ax.set_xticks([.3, .7])
+ assert ax.get_xlim() == (1, 0)
diff --git a/lib/matplotlib/tests/test_backend_qt.py b/lib/matplotlib/tests/test_backend_qt.py
index f6493cfb9c38..0d4f1bec56a6 100644
--- a/lib/matplotlib/tests/test_backend_qt.py
+++ b/lib/matplotlib/tests/test_backend_qt.py
@@ -307,3 +307,23 @@ def test_figureoptions():
"matplotlib.backends.qt_editor._formlayout.FormDialog.exec_",
lambda self: None):
fig.canvas.manager.toolbar.edit_parameters()
+
+
+@pytest.mark.backend("Qt5Agg")
+def test_canvas_reinit():
+ import matplotlib.pyplot as plt
+ from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
+ from functools import partial
+
+ called = False
+
+ def crashing_callback(fig, stale):
+ nonlocal called
+ fig.canvas.draw_idle()
+ called = True
+
+ fig, ax = plt.subplots()
+ fig.stale_callback = crashing_callback
+ # this should not raise
+ canvas = FigureCanvasQTAgg(fig)
+ assert called
diff --git a/lib/matplotlib/tests/test_backend_webagg.py b/lib/matplotlib/tests/test_backend_webagg.py
new file mode 100644
index 000000000000..220670aa4da2
--- /dev/null
+++ b/lib/matplotlib/tests/test_backend_webagg.py
@@ -0,0 +1,28 @@
+import subprocess
+import os
+import sys
+import pytest
+
+
+@pytest.mark.parametrize("backend", ["webagg", "nbagg"])
+def test_webagg_fallback(backend):
+ if backend == "nbagg":
+ pytest.importorskip("IPython")
+ env = {}
+ if os.name == "nt":
+ env = dict(os.environ)
+ else:
+ env = {"DISPLAY": ""}
+
+ env["MPLBACKEND"] = backend
+
+ test_code = (
+ "import os;"
+ + f"assert os.environ['MPLBACKEND'] == '{backend}';"
+ + "import matplotlib.pyplot as plt; "
+ + "print(plt.get_backend());"
+ f"assert '{backend}' == plt.get_backend().lower();"
+ )
+ ret = subprocess.call([sys.executable, "-c", test_code], env=env)
+
+ assert ret == 0
diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py
index c12ed7004d61..773093100349 100644
--- a/lib/matplotlib/tests/test_collections.py
+++ b/lib/matplotlib/tests/test_collections.py
@@ -721,3 +721,10 @@ def test_pathcollection_legend_elements():
ax.add_artist(l)
fig.canvas.draw()
+
+
+def test_EventCollection_nosort():
+ # Check that EventCollection doesn't modify input in place
+ arr = np.array([3, 2, 1, 10])
+ coll = EventCollection(arr)
+ np.testing.assert_array_equal(arr, np.array([3, 2, 1, 10]))
diff --git a/lib/matplotlib/tests/test_constrainedlayout.py b/lib/matplotlib/tests/test_constrainedlayout.py
index df3e5cf18def..8769fcec3537 100644
--- a/lib/matplotlib/tests/test_constrainedlayout.py
+++ b/lib/matplotlib/tests/test_constrainedlayout.py
@@ -404,3 +404,16 @@ def test_colorbar_location():
fig.colorbar(pcm, ax=axs[-2, 3:], shrink=0.5, location='top')
fig.colorbar(pcm, ax=axs[0, 0], shrink=0.5, location='left')
fig.colorbar(pcm, ax=axs[1:3, 2], shrink=0.5, location='right')
+
+
+def test_hidden_axes():
+ # test that if we make an axes not visible that constrained_layout
+ # still works. Note the axes still takes space in the layout
+ # (as does a gridspec slot that is empty)
+ fig, axs = plt.subplots(2, 2, constrained_layout=True)
+ axs[0, 1].set_visible(False)
+ fig.canvas.draw()
+ extents1 = np.copy(axs[0, 0].get_position().extents)
+
+ np.testing.assert_allclose(extents1,
+ [0.045552, 0.548288, 0.47319, 0.982638], rtol=1e-5)
diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py
index ae803000ddee..22cd78d46820 100644
--- a/lib/matplotlib/tests/test_image.py
+++ b/lib/matplotlib/tests/test_image.py
@@ -989,3 +989,18 @@ def test_deprecation():
with pytest.warns(MatplotlibDeprecationWarning):
# Enough arguments to pass "shape" positionally.
obj.imshow(data, *[None] * 10)
+
+
+def test_image_cursor_formatting():
+ fig, ax = plt.subplots()
+ # Create a dummy image to be able to call format_cursor_data
+ im = ax.imshow(np.zeros((4, 4)))
+
+ data = np.ma.masked_array([0], mask=[True])
+ assert im.format_cursor_data(data) == '[]'
+
+ data = np.ma.masked_array([0], mask=[False])
+ assert im.format_cursor_data(data) == '[0]'
+
+ data = np.nan
+ assert im.format_cursor_data(data) == '[nan]'
diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py
index 13c5dd1a83eb..31c240a605af 100644
--- a/lib/matplotlib/tests/test_patches.py
+++ b/lib/matplotlib/tests/test_patches.py
@@ -402,6 +402,18 @@ def test_connection_patch():
ax2.add_artist(con)
+def test_connection_patch_fig():
+ # Test that connection patch can be added as figure artist
+ fig, (ax1, ax2) = plt.subplots(1, 2)
+ xy = (0.3, 0.2)
+ con = mpatches.ConnectionPatch(xyA=xy, xyB=xy,
+ coordsA="data", coordsB="data",
+ axesA=ax1, axesB=ax2,
+ arrowstyle="->", shrinkB=5)
+ fig.add_artist(con)
+ fig.canvas.draw()
+
+
def test_datetime_rectangle():
# Check that creating a rectangle with timedeltas doesn't fail
from datetime import datetime, timedelta
diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py
index 123ffe4ae3c3..d8fe73cebc2a 100644
--- a/lib/matplotlib/tests/test_rcparams.py
+++ b/lib/matplotlib/tests/test_rcparams.py
@@ -17,6 +17,7 @@
validate_colorlist,
validate_color,
validate_bool,
+ validate_fontweight,
validate_nseq_int,
validate_nseq_float,
validate_cycler,
@@ -412,6 +413,26 @@ def test_validator_invalid(validator, arg, exception_type):
validator(arg)
+@pytest.mark.parametrize('weight, parsed_weight', [
+ ('bold', 'bold'),
+ ('BOLD', ValueError), # weight is case-sensitive
+ (100, 100),
+ ('100', 100),
+ (np.array(100), 100),
+ # fractional fontweights are not defined. This should actually raise a
+ # ValueError, but historically did not.
+ (20.6, 20),
+ ('20.6', ValueError),
+ ([100], ValueError),
+])
+def test_validate_fontweight(weight, parsed_weight):
+ if parsed_weight is ValueError:
+ with pytest.raises(ValueError):
+ validate_fontweight(weight)
+ else:
+ assert validate_fontweight(weight) == parsed_weight
+
+
def test_keymaps():
key_list = [k for k in mpl.rcParams if 'keymap' in k]
for k in key_list:
diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py
index 69a5cda0183d..44a8d90d3dea 100644
--- a/lib/matplotlib/text.py
+++ b/lib/matplotlib/text.py
@@ -1630,14 +1630,14 @@ def set_transform(self, t):
Parameters
----------
- t : matplotlib.transforms.Transform
+ t : `~matplotlib.transforms.Transform`
"""
Text.set_transform(self, t)
self.dashline.set_transform(t)
self.stale = True
def get_figure(self):
- 'return the figure instance the artist belongs to'
+ """Return the figure instance the artist belongs to."""
return self.figure
def set_figure(self, fig):
@@ -1646,7 +1646,7 @@ def set_figure(self, fig):
Parameters
----------
- fig : matplotlib.figure.Figure
+ fig : `~matplotlib.figure.Figure`
"""
Text.set_figure(self, fig)
self.dashline.set_figure(fig)
diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py
index 3f6130164814..d1aa0c7fd112 100644
--- a/lib/matplotlib/ticker.py
+++ b/lib/matplotlib/ticker.py
@@ -181,10 +181,11 @@
'LogFormatterExponent', 'LogFormatterMathtext',
'IndexFormatter', 'LogFormatterSciNotation',
'LogitFormatter', 'EngFormatter', 'PercentFormatter',
+ 'OldScalarFormatter',
'Locator', 'IndexLocator', 'FixedLocator', 'NullLocator',
'LinearLocator', 'LogLocator', 'AutoLocator',
'MultipleLocator', 'MaxNLocator', 'AutoMinorLocator',
- 'SymmetricalLogLocator', 'LogitLocator')
+ 'SymmetricalLogLocator', 'LogitLocator', 'OldAutoLocator')
def _mathdefault(s):
@@ -628,6 +629,8 @@ def format_data_short(self, value):
"""
if self._useLocale:
return locale.format_string('%-12g', (value,))
+ elif isinstance(value, np.ma.MaskedArray) and value.mask:
+ return ''
else:
return '%-12g' % value
diff --git a/lib/matplotlib/tri/triinterpolate.py b/lib/matplotlib/tri/triinterpolate.py
index bd893608a397..176e66ad2be0 100644
--- a/lib/matplotlib/tri/triinterpolate.py
+++ b/lib/matplotlib/tri/triinterpolate.py
@@ -1309,28 +1309,28 @@ def _cg(A, b, x0=None, tol=1.e-10, maxiter=1000):
Parameters
----------
- A: _Sparse_Matrix_coo
+ A : _Sparse_Matrix_coo
*A* must have been compressed before by compress_csc or
compress_csr method.
- b: array
+ b : array
Right hand side of the linear system.
Returns
-------
- x: array.
+ x : array
The converged solution.
- err: float
+ err : float
The absolute error np.linalg.norm(A.dot(x) - b)
Other parameters
----------------
- x0: array.
+ x0 : array
Starting guess for the solution.
- tol: float.
+ tol : float
Tolerance to achieve. The algorithm terminates when the relative
residual is below tol.
- maxiter: integer.
+ maxiter : integer
Maximum number of iterations. Iteration will stop
after maxiter steps even if the specified tolerance has not
been achieved.
diff --git a/lib/matplotlib/widgets.py b/lib/matplotlib/widgets.py
index 641fa0909f97..1f614587e943 100644
--- a/lib/matplotlib/widgets.py
+++ b/lib/matplotlib/widgets.py
@@ -155,9 +155,8 @@ def __init__(self, ax, label, image=None,
"""
Parameters
----------
- ax : matplotlib.axes.Axes
- The :class:`matplotlib.axes.Axes` instance the button
- will be placed into.
+ ax : `~matplotlib.axes.Axes`
+ The `~.axes.Axes` instance the button will be placed into.
label : str
The button text. Accepts string.
@@ -168,10 +167,10 @@ def __init__(self, ax, label, image=None,
matplotlib Image instance, or Pillow Image).
color : color
- The color of the button when not activated
+ The color of the button when not activated.
hovercolor : color
- The color of the button when the mouse is over it
+ The color of the button when the mouse is over it.
"""
AxesWidget.__init__(self, ax)
@@ -692,24 +691,23 @@ def __init__(self, ax, label, initial='',
"""
Parameters
----------
- ax : matplotlib.axes.Axes
- The :class:`matplotlib.axes.Axes` instance the button
- will be placed into.
+ ax : `~matplotlib.axes.Axes`
+ The `~.axes.Axes` instance the button will be placed into.
label : str
Label for this text box. Accepts string.
initial : str
- Initial value in the text box
+ Initial value in the text box.
color : color
- The color of the box
+ The color of the box.
hovercolor : color
- The color of the box when the mouse is over it
+ The color of the box when the mouse is over it.
label_pad : float
- the distance between the label and the right side of the textbox
+ The distance between the label and the right side of the textbox.
"""
AxesWidget.__init__(self, ax)
diff --git a/lib/mpl_toolkits/axes_grid1/axes_grid.py b/lib/mpl_toolkits/axes_grid1/axes_grid.py
index 2fcad75cefaa..5da0d12071a5 100644
--- a/lib/mpl_toolkits/axes_grid1/axes_grid.py
+++ b/lib/mpl_toolkits/axes_grid1/axes_grid.py
@@ -491,7 +491,7 @@ def __init__(self, fig,
if ngrids is None:
ngrids = self._nrows * self._ncols
else:
- if not 0 <= ngrids < self._nrows * self._ncols:
+ if not 0 < ngrids <= self._nrows * self._ncols:
raise Exception
self.ngrids = ngrids
diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py
index 4202be9a1138..047234b365f5 100644
--- a/lib/mpl_toolkits/mplot3d/axes3d.py
+++ b/lib/mpl_toolkits/mplot3d/axes3d.py
@@ -626,7 +626,8 @@ def set_xlim3d(self, left=None, right=None, emit=True, auto=False,
reverse = left > right
left, right = self.xaxis.get_major_locator().nonsingular(left, right)
left, right = self.xaxis.limit_range_for_scale(left, right)
- left, right = sorted([left, right], reverse=reverse)
+ # cast to bool to avoid bad interaction between python 3.8 and np.bool_
+ left, right = sorted([left, right], reverse=bool(reverse))
self.xy_viewLim.intervalx = (left, right)
if auto is not None:
diff --git a/lib/mpl_toolkits/tests/test_axes_grid1.py b/lib/mpl_toolkits/tests/test_axes_grid1.py
index fef2ebc210b1..95b1ae5a3d78 100644
--- a/lib/mpl_toolkits/tests/test_axes_grid1.py
+++ b/lib/mpl_toolkits/tests/test_axes_grid1.py
@@ -105,6 +105,7 @@ def test_axesgrid_colorbar_log_smoketest():
fig = plt.figure()
grid = AxesGrid(fig, 111, # modified to be only subplot
nrows_ncols=(1, 1),
+ ngrids=1,
label_mode="L",
cbar_location="top",
cbar_mode="single",
diff --git a/requirements/testing/travis36.txt b/requirements/testing/travis36.txt
index 0667058cd533..6b961fb5a6e4 100644
--- a/requirements/testing/travis36.txt
+++ b/requirements/testing/travis36.txt
@@ -2,5 +2,5 @@
ipykernel
nbconvert[execute]
-pandas
+pandas!=0.25.0
pytz
diff --git a/setup.py b/setup.py
index d5ff91c43def..adabf1753797 100644
--- a/setup.py
+++ b/setup.py
@@ -22,6 +22,7 @@
import os
from string import Template
import urllib.request
+import shutil
from zipfile import ZipFile
from setuptools import setup, Extension
@@ -124,6 +125,16 @@ def build_extensions(self):
def _download_jquery_to(dest):
+ if os.path.exists(os.path.join(dest, "jquery-ui-1.12.1")):
+ return
+
+ # If we are installing from an sdist, use the already downloaded jquery-ui
+ sdist_src = os.path.join(
+ "lib/matplotlib/backends/web_backend", "jquery-ui-1.12.1")
+ if os.path.exists(sdist_src):
+ shutil.copytree(sdist_src, os.path.join(dest, "jquery-ui-1.12.1"))
+ return
+
# Note: When bumping the jquery-ui version, also update the versions in
# single_figure.html and all_figures.html.
url = "https://jqueryui.com/resources/download/jquery-ui-1.12.1.zip"
diff --git a/tutorials/advanced/patheffects_guide.py b/tutorials/advanced/patheffects_guide.py
index 4f2c89cf3315..ed35571053a0 100644
--- a/tutorials/advanced/patheffects_guide.py
+++ b/tutorials/advanced/patheffects_guide.py
@@ -5,7 +5,7 @@
Defining paths that objects follow on a canvas.
-.. py:module:: matplotlib.patheffects
+.. py:currentmodule:: matplotlib.patheffects
Matplotlib's :mod:`~matplotlib.patheffects` module provides functionality to
diff --git a/tutorials/intermediate/color_cycle.py b/tutorials/intermediate/color_cycle.py
index 9adbdbcd7341..cc400e3e7dac 100644
--- a/tutorials/intermediate/color_cycle.py
+++ b/tutorials/intermediate/color_cycle.py
@@ -35,10 +35,10 @@
###############################################################################
# So ``yy[:, i]`` will give you the ``i``-th offset sine curve. Let's set the
-# default prop_cycle using :func:`matplotlib.pyplot.rc`. We'll combine a color
-# cycler and a linestyle cycler by adding (``+``) two ``cycler``'s together.
-# See the bottom of this tutorial for more information about combining
-# different cyclers.
+# default ``prop_cycle`` using :func:`matplotlib.pyplot.rc`. We'll combine a
+# color cycler and a linestyle cycler by adding (``+``) two ``cycler``'s
+# together. See the bottom of this tutorial for more information about
+# combining different cyclers.
default_cycler = (cycler(color=['r', 'g', 'b', 'y']) +
cycler(linestyle=['-', '--', ':', '-.']))
@@ -48,7 +48,7 @@
###############################################################################
# Now we'll generate a figure with two axes, one on top of the other. On the
# first axis, we'll plot with the default cycler. On the second axis, we'll
-# set the prop_cycler using :func:`matplotlib.axes.Axes.set_prop_cycle`
+# set the ``prop_cycle`` using :func:`matplotlib.axes.Axes.set_prop_cycle`,
# which will only set the ``prop_cycle`` for this :mod:`matplotlib.axes.Axes`
# instance. We'll use a second ``cycler`` that combines a color cycler and a
# linewidth cycler.
@@ -67,16 +67,16 @@
plt.show()
###############################################################################
-# Setting ``prop_cycler`` in the ``matplotlibrc`` file or style files
-# -------------------------------------------------------------------
+# Setting ``prop_cycle`` in the ``matplotlibrc`` file or style files
+# ------------------------------------------------------------------
#
-# Remember, if you want to set a custom ``prop_cycler`` in your
+# Remember, if you want to set a custom cycler in your
# ``.matplotlibrc`` file or a style file (``style.mplstyle``), you can set the
# ``axes.prop_cycle`` property:
#
# .. code-block:: python
#
-# axes.prop_cycle : cycler(color='bgrcmyk')
+# axes.prop_cycle : cycler(color='bgrcmyk')
#
# Cycling through multiple properties
# -----------------------------------
diff --git a/tutorials/intermediate/constrainedlayout_guide.py b/tutorials/intermediate/constrainedlayout_guide.py
index 621a0dbe33f2..535f85006fb5 100644
--- a/tutorials/intermediate/constrainedlayout_guide.py
+++ b/tutorials/intermediate/constrainedlayout_guide.py
@@ -284,7 +284,7 @@ def example_plot(ax, fontsize=12, nodec=False):
# Spacing between subplots is set by ``wspace`` and ``hspace``. There are
# specified as a fraction of the size of the subplot group as a whole.
# If the size of the figure is changed, then these spaces change in
-# proportion. Note in the blow how the space at the edges doesn't change from
+# proportion. Note in the below how the space at the edges doesn't change from
# the above, but the space between subplots does.
fig, axs = plt.subplots(2, 2, constrained_layout=True)
diff --git a/tutorials/intermediate/gridspec.py b/tutorials/intermediate/gridspec.py
index df46971cd164..f0f99a3574de 100644
--- a/tutorials/intermediate/gridspec.py
+++ b/tutorials/intermediate/gridspec.py
@@ -137,14 +137,14 @@
gs_kw = dict(width_ratios=widths, height_ratios=heights)
fig6, f6_axes = plt.subplots(ncols=3, nrows=3, constrained_layout=True,
- gridspec_kw=gs_kw)
+ gridspec_kw=gs_kw)
for r, row in enumerate(f6_axes):
for c, ax in enumerate(row):
label = 'Width: {}\nHeight: {}'.format(widths[c], heights[r])
ax.annotate(label, (0.1, 0.5), xycoords='axes fraction', va='center')
############################################################################
-# The ``subplots`` and ``gridspec`` methods can be combined since it is
+# The ``subplots`` and ``get_gridspec`` methods can be combined since it is
# sometimes more convenient to make most of the subplots using ``subplots``
# and then remove some and combine them. Here we create a layout with
# the bottom two axes in the last column combined.
diff --git a/tutorials/introductory/usage.py b/tutorials/introductory/usage.py
index d42f6ead859e..dd21c3c5078c 100644
--- a/tutorials/introductory/usage.py
+++ b/tutorials/introductory/usage.py
@@ -98,7 +98,7 @@
# :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
+# The :class:`Axes` class and its member functions are the primary entry
# point to working with the OO interface.
#
# :class:`~matplotlib.axis.Axis`
@@ -406,6 +406,9 @@ def my_plotter(ax, data1, data2, param_dict):
# :term:`svg`
# ============= ============ ================================================
#
+# To save plots using the non-interactive backends, use the
+# ``matplotlib.pyplot.savefig('filename')`` method.
+#
# 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
@@ -706,7 +709,7 @@ def my_plotter(ax, data1, data2, param_dict):
# line segments. Marker simplification is only available
# to :class:`~matplotlib.lines.Line2D` objects (through the
# ``markevery`` property). Wherever
-# :class:`~matplotlib.lines.Line2D` construction parameter
+# :class:`~matplotlib.lines.Line2D` construction parameters
# are passed through, such as
# :func:`matplotlib.pyplot.plot` and
# :meth:`matplotlib.axes.Axes.plot`, the ``markevery``
@@ -726,7 +729,7 @@ def my_plotter(ax, data1, data2, param_dict):
# then you can make use of the ``agg.path.chunksize`` rc parameter.
# This allows you to specify a chunk size, and any lines with
# greater than that many vertices will be split into multiple
-# lines, each of which have no more than ``agg.path.chunksize``
+# lines, each of which has no more than ``agg.path.chunksize``
# many vertices. (Unless ``agg.path.chunksize`` is zero, in
# which case there is no chunking.) For some kind of data,
# chunking the line up into reasonable sizes can greatly
diff --git a/tutorials/text/text_intro.py b/tutorials/text/text_intro.py
index 34336c52e5d2..333a31e41d40 100644
--- a/tutorials/text/text_intro.py
+++ b/tutorials/text/text_intro.py
@@ -69,15 +69,19 @@
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)
+
+# Set titles for the figure and the subplot respectively
+fig.suptitle('bold figure suptitle', fontsize=14, fontweight='bold')
ax.set_title('axes title')
ax.set_xlabel('xlabel')
ax.set_ylabel('ylabel')
+# Set both x- and y-axis limits to [0, 10] instead of default [0, 1]
+ax.axis([0, 10, 0, 10])
+
ax.text(3, 8, 'boxed italics text in data coords', style='italic',
bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})
@@ -90,13 +94,10 @@
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()
###############################################################################
@@ -157,8 +158,7 @@
fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
-ax.set_xlabel('time [s]', position=(0., 1e6),
- horizontalalignment='left')
+ax.set_xlabel('time [s]', position=(0., 1e6), horizontalalignment='left')
ax.set_ylabel('Damped oscillation [V]')
plt.show()
@@ -226,34 +226,33 @@
# ====================
#
# Placing ticks and ticklabels is a very tricky aspect of making a figure.
-# Matplotlib does the best it can automatically, but it also offers a very
-# flexible framework for determining the choices for tick locations, and
-# how they are labelled.
+# Matplotlib does its best to accomplish the task automatically, but it also
+# offers a very flexible framework for determining the choices for tick
+# locations, and how they are labelled.
#
# Terminology
# ~~~~~~~~~~~
#
-# *Axes* have an `matplotlib.axis` object for the ``ax.xaxis``
-# and ``ax.yaxis`` that
-# contain the information about how the labels in the axis are laid out.
+# *Axes* have a `matplotlib.axis` object for the ``ax.xaxis`` and ``ax.yaxis``
+# that contain the information about how the labels in the axis are laid out.
#
# The axis API is explained in detail in the documentation to
# `~matplotlib.axis`.
#
-# An Axis object has major and minor ticks. The Axis has a
+# An Axis object has major and minor ticks. The Axis has
# `matplotlib.xaxis.set_major_locator` and
# `matplotlib.xaxis.set_minor_locator` methods that use the data being plotted
# to determine
# the location of major and minor ticks. There are also
# `matplotlib.xaxis.set_major_formatter` and
-# `matplotlib.xaxis.set_minor_formatters` methods that format the tick labels.
+# `matplotlib.xaxis.set_minor_formatter` methods that format the tick labels.
#
# Simple ticks
# ~~~~~~~~~~~~
#
# It often is convenient to simply define the
# tick values, and sometimes the tick labels, overriding the default
-# locators and formatters. This is discouraged because it breaks itneractive
+# locators and formatters. This is discouraged because it breaks interactive
# navigation of the plot. It also can reset the axis limits: note that
# the second plot has the ticks we asked for, including ones that are
# well outside the automatic view limits.
@@ -285,8 +284,9 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Instead of making a list of all the tickalbels, we could have
-# used a `matplotlib.ticker.FormatStrFormatter` and passed it to the
-# ``ax.xaxis``
+# used `matplotlib.ticker.StrMethodFormatter` (new-style ``str.format()``
+# format string) or `matplotlib.ticker.FormatStrFormatter` (old-style '%'
+# format string) and passed it to the ``ax.xaxis``.
fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
@@ -362,6 +362,7 @@ def formatoddticks(x, pos):
else:
return ''
+
fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.plot(x1, y1)
formatter = matplotlib.ticker.FuncFormatter(formatoddticks)
@@ -383,17 +384,17 @@ def formatoddticks(x, pos):
#
# A simple example is as follows. Note how we have to rotate the
# tick labels so that they don't over-run each other.
+
import datetime
fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
base = datetime.datetime(2017, 1, 1, 0, 0, 1)
-time = [base + datetime.timedelta(days=x) for x in range(len(y1))]
+time = [base + datetime.timedelta(days=x) for x in range(len(x1))]
ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()
-
##############################################################################
# We can pass a format
# to `matplotlib.dates.DateFormatter`. Also note that the 29th and the