From 19b735378ffbce204c34655f1d096e213d9ecbb7 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Mon, 11 Oct 2021 15:12:16 +0200 Subject: [PATCH 1/7] DOC: move usage tutorial info to Users guide rst [skip actions] [skip azp] --- doc/users/backends.rst | 250 +++++++++++++++ doc/users/getting_started.rst | 6 + doc/users/index.rst | 4 + doc/users/performance.rst | 151 +++++++++ tutorials/introductory/usage.py | 541 +------------------------------- 5 files changed, 412 insertions(+), 540 deletions(-) create mode 100644 doc/users/backends.rst create mode 100644 doc/users/performance.rst diff --git a/doc/users/backends.rst b/doc/users/backends.rst new file mode 100644 index 000000000000..24fe007173f1 --- /dev/null +++ b/doc/users/backends.rst @@ -0,0 +1,250 @@ +.. _backends: + +======== +Backends +======== + +.. _what-is-a-backend: + +What is a backend? +------------------ + +A lot of documentation on the website and in the mailing lists refers +to the "backend" and many new users are confused by this term. +Matplotlib targets many different use cases and output formats. Some +people use Matplotlib interactively from the Python shell and have +plotting windows pop up when they type commands. Some people run +`Jupyter `_ notebooks and draw inline plots for +quick data analysis. Others embed Matplotlib into graphical user +interfaces like PyQt or PyGObject to build rich applications. Some +people use Matplotlib in batch scripts to generate postscript images +from numerical simulations, and still others run web application +servers to dynamically serve up graphs. + +To support all of these use cases, Matplotlib can target different +outputs, and each of these capabilities is called a backend; the +"frontend" is the user facing code, i.e., the plotting code, whereas the +"backend" does all the hard work behind-the-scenes to make the figure. +There are two types of backends: user interface backends (for use in +PyQt/PySide, PyGObject, Tkinter, wxPython, or macOS/Cocoa); also referred to +as "interactive backends") and hardcopy backends to make image files +(PNG, SVG, PDF, PS; also referred to as "non-interactive backends"). + +Selecting a backend +------------------- + +There are three ways to configure your backend: + +- The :rc:`backend` parameter in your :file:`matplotlibrc` file +- The :envvar:`MPLBACKEND` environment variable +- The function :func:`matplotlib.use` + +Below is a more detailed description. + +If there is more than one configuration present, the last one from the +list takes precedence; e.g. calling :func:`matplotlib.use()` will override +the setting in your :file:`matplotlibrc`. + +Without a backend explicitly set, Matplotlib automatically detects a usable +backend based on what is available on your system and on whether a GUI event +loop is already running. The first usable backend in the following list is +selected: MacOSX, QtAgg, GTK4Agg, Gtk3Agg, TkAgg, WxAgg, Agg. The last, Agg, +is a non-interactive backend that can only write to files. It is used on +Linux, if Matplotlib cannot connect to either an X display or a Wayland +display. + +Here is a detailed description of the configuration methods: + +#. Setting :rc:`backend` in your :file:`matplotlibrc` file:: + + backend : qtagg # use pyqt with antigrain (agg) rendering + + See also :doc:`/tutorials/introductory/customizing`. + +#. Setting the :envvar:`MPLBACKEND` environment variable: + + You can set the environment variable either for your current shell or for + a single script. + + On Unix:: + + > export MPLBACKEND=qtagg + > python simple_plot.py + + > MPLBACKEND=qtagg python simple_plot.py + + On Windows, only the former is possible:: + + > set MPLBACKEND=qtagg + > python simple_plot.py + + Setting this environment variable will override the ``backend`` parameter + in *any* :file:`matplotlibrc`, even if there is a :file:`matplotlibrc` in + your current working directory. Therefore, setting :envvar:`MPLBACKEND` + globally, e.g. in your :file:`.bashrc` or :file:`.profile`, is discouraged + as it might lead to counter-intuitive behavior. + +#. If your script depends on a specific backend you can use the function + :func:`matplotlib.use`:: + + import matplotlib + matplotlib.use('qtagg') + + This should be done before any figure is created, otherwise Matplotlib may + fail to switch the backend and raise an ImportError. + + Using `~matplotlib.use` will require changes in your code if users want to + use a different backend. Therefore, you should avoid explicitly calling + `~matplotlib.use` unless absolutely necessary. + +.. _the-builtin-backends: + +The builtin backends +-------------------- + +By default, Matplotlib should automatically select a default backend which +allows both interactive work and plotting from scripts, with output to the +screen and/or to a file, so at least initially, you will not need to worry +about the backend. The most common exception is if your Python distribution +comes without :mod:`tkinter` and you have no other GUI toolkit installed. +This happens on certain Linux distributions, where you need to install a +Linux package named ``python-tk`` (or similar). + +If, however, you want to write graphical user interfaces, or a web +application server +(:doc:`/gallery/user_interfaces/web_application_server_sgskip`), or need a +better understanding of what is going on, read on. To make things easily +more customizable for graphical user interfaces, Matplotlib separates +the concept of the renderer (the thing that actually does the drawing) +from the canvas (the place where the drawing goes). The canonical +renderer for user interfaces is ``Agg`` which uses the `Anti-Grain +Geometry`_ C++ library to make a raster (pixel) image of the figure; it +is used by the ``QtAgg``, ``GTK4Agg``, ``GTK3Agg``, ``wxAgg``, ``TkAgg``, and +``macosx`` backends. An alternative renderer is based on the Cairo library, +used by ``QtCairo``, etc. + +For the rendering engines, users can also distinguish between `vector +`_ or `raster +`_ renderers. Vector +graphics languages issue drawing commands like "draw a line from this +point to this point" and hence are scale free. Raster backends +generate a pixel representation of the line whose accuracy depends on a +DPI setting. + +Here is a summary of the Matplotlib renderers (there is an eponymous +backend for each; these are *non-interactive backends*, capable of +writing to a file): + +======== ========= ======================================================= +Renderer Filetypes Description +======== ========= ======================================================= +AGG png raster_ graphics -- high quality images using the + `Anti-Grain Geometry`_ engine +PDF pdf vector_ graphics -- `Portable Document Format`_ +PS ps, eps vector_ graphics -- Postscript_ output +SVG svg vector_ graphics -- `Scalable Vector Graphics`_ +PGF pgf, pdf vector_ graphics -- using the pgf_ package +Cairo png, ps, raster_ or vector_ graphics -- using the Cairo_ library + pdf, svg +======== ========= ======================================================= + +To save plots using the non-interactive backends, use the +``matplotlib.pyplot.savefig('filename')`` method. + +These are the user interfaces and renderer combinations supported; +these are *interactive backends*, capable of displaying to the screen +and using appropriate renderers from the table above to write to +a file: + +========= ================================================================ +Backend Description +========= ================================================================ +QtAgg Agg rendering in a Qt_ canvas (requires PyQt_ or `Qt for Python`_, + a.k.a. PySide). This backend can be activated in IPython with + ``%matplotlib qt``. +ipympl Agg rendering embedded in a Jupyter widget. (requires ipympl). + This backend can be enabled in a Jupyter notebook with + ``%matplotlib ipympl``. +GTK3Agg Agg rendering to a GTK_ 3.x canvas (requires PyGObject_, + and pycairo_ or cairocffi_). This backend can be activated in + IPython with ``%matplotlib gtk3``. +GTK4Agg Agg rendering to a GTK_ 4.x canvas (requires PyGObject_, + and pycairo_ or cairocffi_). This backend can be activated in + IPython with ``%matplotlib gtk4``. +macosx Agg rendering into a Cocoa canvas in OSX. This backend can be + activated in IPython with ``%matplotlib osx``. +TkAgg Agg rendering to a Tk_ canvas (requires TkInter_). This + backend can be activated in IPython with ``%matplotlib tk``. +nbAgg Embed an interactive figure in a Jupyter classic notebook. This + backend can be enabled in Jupyter notebooks via + ``%matplotlib notebook``. +WebAgg On ``show()`` will start a tornado server with an interactive + figure. +GTK3Cairo Cairo rendering to a GTK_ 3.x canvas (requires PyGObject_, + and pycairo_ or cairocffi_). +GTK4Cairo Cairo rendering to a GTK_ 4.x canvas (requires PyGObject_, + and pycairo_ or cairocffi_). +wxAgg Agg rendering to a wxWidgets_ canvas (requires wxPython_ 4). + This backend can be activated in IPython with ``%matplotlib wx``. +========= ================================================================ + +.. note:: + The names of builtin backends case-insensitive; e.g., 'QtAgg' and + 'qtagg' are equivalent. + +.. _`Anti-Grain Geometry`: http://agg.sourceforge.net/antigrain.com/ +.. _`Portable Document Format`: https://en.wikipedia.org/wiki/Portable_Document_Format +.. _Postscript: https://en.wikipedia.org/wiki/PostScript +.. _`Scalable Vector Graphics`: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics +.. _pgf: https://ctan.org/pkg/pgf +.. _Cairo: https://www.cairographics.org +.. _PyGObject: https://wiki.gnome.org/action/show/Projects/PyGObject +.. _pycairo: https://www.cairographics.org/pycairo/ +.. _cairocffi: https://pythonhosted.org/cairocffi/ +.. _wxPython: https://www.wxpython.org/ +.. _TkInter: https://docs.python.org/3/library/tk.html +.. _PyQt: https://riverbankcomputing.com/software/pyqt/intro +.. _`Qt for Python`: https://doc.qt.io/qtforpython/ +.. _Qt: https://qt.io/ +.. _GTK: https://www.gtk.org/ +.. _Tk: https://www.tcl.tk/ +.. _wxWidgets: https://www.wxwidgets.org/ + +ipympl +^^^^^^ + +The Jupyter widget ecosystem is moving too fast to support directly in +Matplotlib. To install ipympl: + +.. code-block:: bash + + pip install ipympl + jupyter nbextension enable --py --sys-prefix ipympl + +or + +.. code-block:: bash + + conda install ipympl -c conda-forge + +See `jupyter-matplotlib `__ +for more details. + +.. _QT_API-usage: + +How do I select PyQt5 or PySide2? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :envvar:`QT_API` environment variable can be set to either ``pyqt5`` or +``pyside2`` to use ``PyQt5`` or ``PySide2``, respectively. + +Since the default value for the bindings to be used is ``PyQt5``, Matplotlib +first tries to import it. If the import fails, it tries to import +``PySide2``. + +Using non-builtin backends +-------------------------- +More generally, any importable backend can be selected by using any of the +methods above. If ``name.of.the.backend`` is the module containing the +backend, use ``module://name.of.the.backend`` as the backend name, e.g. +``matplotlib.use('module://name.of.the.backend')``. \ No newline at end of file diff --git a/doc/users/getting_started.rst b/doc/users/getting_started.rst index 241f103f09be..d48b6b454ba7 100644 --- a/doc/users/getting_started.rst +++ b/doc/users/getting_started.rst @@ -24,6 +24,12 @@ Installation Further details are available in the :doc:`Installation Guide `. +Choosing a backend +------------------ + +Matplotlib needs a "backend" to render your figure, either in its own GUI window, +as part of a notebook, or saved as an image to disk. If you need more information on +choosing a backend, see :ref:`backends`. Draw a first plot ----------------- diff --git a/doc/users/index.rst b/doc/users/index.rst index f3ca47bf82ac..09ea86ef5eb8 100644 --- a/doc/users/index.rst +++ b/doc/users/index.rst @@ -11,7 +11,11 @@ Usage guide ../tutorials/index.rst ../gallery/index.rst getting_started.rst + backends.rst + performance.rst + ../gallery/usage.rst explain.rst ../faq/index.rst ../api/index.rst ../resources/index.rst + \ No newline at end of file diff --git a/doc/users/performance.rst b/doc/users/performance.rst new file mode 100644 index 000000000000..aa291f407c1e --- /dev/null +++ b/doc/users/performance.rst @@ -0,0 +1,151 @@ +.. _performance: + +Performance +=========== + +Whether exploring data in interactive mode or programmatically +saving lots of plots, rendering performance can be a challenging +bottleneck in your pipeline. Matplotlib provides multiple +ways to greatly reduce rendering time at the cost of a slight +change (to a settable tolerance) in your plot's appearance. +The methods available to reduce rendering time depend on the +type of plot that is being created. + +Line segment simplification +--------------------------- + +For plots that have line segments (e.g. typical line plots, outlines +of polygons, etc.), rendering performance can be controlled by +:rc:`path.simplify` and :rc:`path.simplify_threshold`, which +can be defined e.g. in the :file:`matplotlibrc` file (see +:doc:`/tutorials/introductory/customizing` for more information about +the :file:`matplotlibrc` file). :rc:`path.simplify` is a Boolean +indicating whether or not line segments are simplified at all. +:rc:`path.simplify_threshold` controls how much line segments are simplified; +higher thresholds result in quicker rendering. + +The following script will first display the data without any +simplification, and then display the same data with simplification. +Try interacting with both of them:: + + import numpy as np + import matplotlib.pyplot as plt + import matplotlib as mpl + + # Setup, and create the data to plot + y = np.random.rand(100000) + y[50000:] *= 2 + y[np.geomspace(10, 50000, 400).astype(int)] = -1 + mpl.rcParams['path.simplify'] = True + + mpl.rcParams['path.simplify_threshold'] = 0.0 + plt.plot(y) + plt.show() + + mpl.rcParams['path.simplify_threshold'] = 1.0 + plt.plot(y) + plt.show() + +Matplotlib currently defaults to a conservative simplification +threshold of ``1/9``. To change default settings to use a different +value, change the :file:`matplotlibrc` file. Alternatively, users +can create a new style for interactive plotting (with maximal +simplification) and another style for publication quality plotting +(with minimal simplification) and activate them as necessary. See +:doc:`/tutorials/introductory/customizing` for instructions on +how to perform these actions. + + +The simplification works by iteratively merging line segments +into a single vector until the next line segment's perpendicular +distance to the vector (measured in display-coordinate space) +is greater than the ``path.simplify_threshold`` parameter. + +.. note:: + Changes related to how line segments are simplified were made + in version 2.1. Rendering time will still be improved by these + parameters prior to 2.1, but rendering time for some kinds of + data will be vastly improved in versions 2.1 and greater. + +Marker simplification +--------------------- + +Markers can also be simplified, albeit less robustly than +line segments. Marker simplification is only available +to :class:`~matplotlib.lines.Line2D` objects (through the +``markevery`` property). Wherever +:class:`~matplotlib.lines.Line2D` construction parameters +are passed through, such as +:func:`matplotlib.pyplot.plot` and +:meth:`matplotlib.axes.Axes.plot`, the ``markevery`` +parameter can be used:: + + plt.plot(x, y, markevery=10) + +The ``markevery`` argument allows for naive subsampling, or an +attempt at evenly spaced (along the *x* axis) sampling. See the +:doc:`/gallery/lines_bars_and_markers/markevery_demo` +for more information. + +Splitting lines into smaller chunks +----------------------------------- + +If you are using the Agg backend (see :ref:`what-is-a-backend`), +then you can make use of :rc:`agg.path.chunksize` +This allows users to specify a chunk size, and any lines with +greater than that many vertices will be split into multiple +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 +decrease rendering time. + +The following script will first display the data without any +chunk size restriction, and then display the same data with +a chunk size of 10,000. The difference can best be seen when +the figures are large, try maximizing the GUI and then +interacting with them:: + + import numpy as np + import matplotlib.pyplot as plt + import matplotlib as mpl + mpl.rcParams['path.simplify_threshold'] = 1.0 + + # Setup, and create the data to plot + y = np.random.rand(100000) + y[50000:] *= 2 + y[np.geomspace(10, 50000, 400).astype(int)] = -1 + mpl.rcParams['path.simplify'] = True + + mpl.rcParams['agg.path.chunksize'] = 0 + plt.plot(y) + plt.show() + + mpl.rcParams['agg.path.chunksize'] = 10000 + plt.plot(y) + plt.show() + +Legends +------- + +The default legend behavior for axes attempts to find the location +that covers the fewest data points (``loc='best'``). This can be a +very expensive computation if there are lots of data points. In +this case, you may want to provide a specific location. + +Using the *fast* style +---------------------- + +The *fast* style can be used to automatically set +simplification and chunking parameters to reasonable +settings to speed up plotting large amounts of data. +The following code runs it:: + + import matplotlib.style as mplstyle + mplstyle.use('fast') + +It is very lightweight, so it works well with other +styles. Be sure the fast style is applied last +so that other styles do not overwrite the settings:: + + mplstyle.use(['dark_background', 'ggplot', 'fast']) diff --git a/tutorials/introductory/usage.py b/tutorials/introductory/usage.py index 233445877767..d40dcb3fd325 100644 --- a/tutorials/introductory/usage.py +++ b/tutorials/introductory/usage.py @@ -249,543 +249,4 @@ def my_plotter(ax, data1, data2, param_dict): ############################################################################### # These examples provide convenience for more complex graphs. -# -# -# .. _backends: -# -# Backends -# ======== -# -# .. _what-is-a-backend: -# -# What is a backend? -# ------------------ -# -# A lot of documentation on the website and in the mailing lists refers -# to the "backend" and many new users are confused by this term. -# Matplotlib targets many different use cases and output formats. Some -# people use Matplotlib interactively from the Python shell and have -# plotting windows pop up when they type commands. Some people run -# `Jupyter `_ notebooks and draw inline plots for -# quick data analysis. Others embed Matplotlib into graphical user -# interfaces like PyQt or PyGObject to build rich applications. Some -# people use Matplotlib in batch scripts to generate postscript images -# from numerical simulations, and still others run web application -# servers to dynamically serve up graphs. -# -# To support all of these use cases, Matplotlib can target different -# outputs, and each of these capabilities is called a backend; the -# "frontend" is the user facing code, i.e., the plotting code, whereas the -# "backend" does all the hard work behind-the-scenes to make the figure. -# There are two types of backends: user interface backends (for use in -# PyQt/PySide, PyGObject, Tkinter, wxPython, or macOS/Cocoa); also referred to -# as "interactive backends") and hardcopy backends to make image files -# (PNG, SVG, PDF, PS; also referred to as "non-interactive backends"). -# -# Selecting a backend -# ------------------- -# -# There are three ways to configure your backend: -# -# - The :rc:`backend` parameter in your :file:`matplotlibrc` file -# - The :envvar:`MPLBACKEND` environment variable -# - The function :func:`matplotlib.use` -# -# Below is a more detailed description. -# -# If there is more than one configuration present, the last one from the -# list takes precedence; e.g. calling :func:`matplotlib.use()` will override -# the setting in your :file:`matplotlibrc`. -# -# Without a backend explicitly set, Matplotlib automatically detects a usable -# backend based on what is available on your system and on whether a GUI event -# loop is already running. The first usable backend in the following list is -# selected: MacOSX, QtAgg, GTK4Agg, Gtk3Agg, TkAgg, WxAgg, Agg. The last, Agg, -# is a non-interactive backend that can only write to files. It is used on -# Linux, if Matplotlib cannot connect to either an X display or a Wayland -# display. -# -# Here is a detailed description of the configuration methods: -# -# #. Setting :rc:`backend` in your :file:`matplotlibrc` file:: -# -# backend : qtagg # use pyqt with antigrain (agg) rendering -# -# See also :doc:`/tutorials/introductory/customizing`. -# -# #. Setting the :envvar:`MPLBACKEND` environment variable: -# -# You can set the environment variable either for your current shell or for -# a single script. -# -# On Unix:: -# -# > export MPLBACKEND=qtagg -# > python simple_plot.py -# -# > MPLBACKEND=qtagg python simple_plot.py -# -# On Windows, only the former is possible:: -# -# > set MPLBACKEND=qtagg -# > python simple_plot.py -# -# Setting this environment variable will override the ``backend`` parameter -# in *any* :file:`matplotlibrc`, even if there is a :file:`matplotlibrc` in -# your current working directory. Therefore, setting :envvar:`MPLBACKEND` -# globally, e.g. in your :file:`.bashrc` or :file:`.profile`, is discouraged -# as it might lead to counter-intuitive behavior. -# -# #. If your script depends on a specific backend you can use the function -# :func:`matplotlib.use`:: -# -# import matplotlib -# matplotlib.use('qtagg') -# -# This should be done before any figure is created, otherwise Matplotlib may -# fail to switch the backend and raise an ImportError. -# -# Using `~matplotlib.use` will require changes in your code if users want to -# use a different backend. Therefore, you should avoid explicitly calling -# `~matplotlib.use` unless absolutely necessary. -# -# .. _the-builtin-backends: -# -# The builtin backends -# -------------------- -# -# By default, Matplotlib should automatically select a default backend which -# allows both interactive work and plotting from scripts, with output to the -# screen and/or to a file, so at least initially, you will not need to worry -# about the backend. The most common exception is if your Python distribution -# comes without :mod:`tkinter` and you have no other GUI toolkit installed. -# This happens on certain Linux distributions, where you need to install a -# Linux package named ``python-tk`` (or similar). -# -# If, however, you want to write graphical user interfaces, or a web -# application server -# (:doc:`/gallery/user_interfaces/web_application_server_sgskip`), or need a -# better understanding of what is going on, read on. To make things easily -# more customizable for graphical user interfaces, Matplotlib separates -# the concept of the renderer (the thing that actually does the drawing) -# from the canvas (the place where the drawing goes). The canonical -# renderer for user interfaces is ``Agg`` which uses the `Anti-Grain -# Geometry`_ C++ library to make a raster (pixel) image of the figure; it -# is used by the ``QtAgg``, ``GTK4Agg``, ``GTK3Agg``, ``wxAgg``, ``TkAgg``, and -# ``macosx`` backends. An alternative renderer is based on the Cairo library, -# used by ``QtCairo``, etc. -# -# For the rendering engines, users can also distinguish between `vector -# `_ or `raster -# `_ renderers. Vector -# graphics languages issue drawing commands like "draw a line from this -# point to this point" and hence are scale free. Raster backends -# generate a pixel representation of the line whose accuracy depends on a -# DPI setting. -# -# Here is a summary of the Matplotlib renderers (there is an eponymous -# backend for each; these are *non-interactive backends*, capable of -# writing to a file): -# -# ======== ========= ======================================================= -# Renderer Filetypes Description -# ======== ========= ======================================================= -# AGG png raster_ graphics -- high quality images using the -# `Anti-Grain Geometry`_ engine -# PDF pdf vector_ graphics -- `Portable Document Format`_ -# PS ps, eps vector_ graphics -- Postscript_ output -# SVG svg vector_ graphics -- `Scalable Vector Graphics`_ -# PGF pgf, pdf vector_ graphics -- using the pgf_ package -# Cairo png, ps, raster_ or vector_ graphics -- using the Cairo_ library -# pdf, svg -# ======== ========= ======================================================= -# -# To save plots using the non-interactive backends, use the -# ``matplotlib.pyplot.savefig('filename')`` method. -# -# These are the user interfaces and renderer combinations supported; -# these are *interactive backends*, capable of displaying to the screen -# and using appropriate renderers from the table above to write to -# a file: -# -# ========= ================================================================ -# Backend Description -# ========= ================================================================ -# QtAgg Agg rendering in a Qt_ canvas (requires PyQt_ or `Qt for Python`_, -# a.k.a. PySide). This backend can be activated in IPython with -# ``%matplotlib qt``. -# ipympl Agg rendering embedded in a Jupyter widget. (requires ipympl). -# This backend can be enabled in a Jupyter notebook with -# ``%matplotlib ipympl``. -# GTK3Agg Agg rendering to a GTK_ 3.x canvas (requires PyGObject_, -# and pycairo_ or cairocffi_). This backend can be activated in -# IPython with ``%matplotlib gtk3``. -# GTK4Agg Agg rendering to a GTK_ 4.x canvas (requires PyGObject_, -# and pycairo_ or cairocffi_). This backend can be activated in -# IPython with ``%matplotlib gtk4``. -# macosx Agg rendering into a Cocoa canvas in OSX. This backend can be -# activated in IPython with ``%matplotlib osx``. -# TkAgg Agg rendering to a Tk_ canvas (requires TkInter_). This -# backend can be activated in IPython with ``%matplotlib tk``. -# nbAgg Embed an interactive figure in a Jupyter classic notebook. This -# backend can be enabled in Jupyter notebooks via -# ``%matplotlib notebook``. -# WebAgg On ``show()`` will start a tornado server with an interactive -# figure. -# GTK3Cairo Cairo rendering to a GTK_ 3.x canvas (requires PyGObject_, -# and pycairo_ or cairocffi_). -# GTK4Cairo Cairo rendering to a GTK_ 4.x canvas (requires PyGObject_, -# and pycairo_ or cairocffi_). -# wxAgg Agg rendering to a wxWidgets_ canvas (requires wxPython_ 4). -# This backend can be activated in IPython with ``%matplotlib wx``. -# ========= ================================================================ -# -# .. note:: -# The names of builtin backends case-insensitive; e.g., 'QtAgg' and -# 'qtagg' are equivalent. -# -# .. _`Anti-Grain Geometry`: http://agg.sourceforge.net/antigrain.com/ -# .. _`Portable Document Format`: https://en.wikipedia.org/wiki/Portable_Document_Format -# .. _Postscript: https://en.wikipedia.org/wiki/PostScript -# .. _`Scalable Vector Graphics`: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics -# .. _pgf: https://ctan.org/pkg/pgf -# .. _Cairo: https://www.cairographics.org -# .. _PyGObject: https://wiki.gnome.org/action/show/Projects/PyGObject -# .. _pycairo: https://www.cairographics.org/pycairo/ -# .. _cairocffi: https://pythonhosted.org/cairocffi/ -# .. _wxPython: https://www.wxpython.org/ -# .. _TkInter: https://docs.python.org/3/library/tk.html -# .. _PyQt: https://riverbankcomputing.com/software/pyqt/intro -# .. _`Qt for Python`: https://doc.qt.io/qtforpython/ -# .. _Qt: https://qt.io/ -# .. _GTK: https://www.gtk.org/ -# .. _Tk: https://www.tcl.tk/ -# .. _wxWidgets: https://www.wxwidgets.org/ -# -# ipympl -# ^^^^^^ -# -# The Jupyter widget ecosystem is moving too fast to support directly in -# Matplotlib. To install ipympl: -# -# .. code-block:: bash -# -# pip install ipympl -# jupyter nbextension enable --py --sys-prefix ipympl -# -# or -# -# .. code-block:: bash -# -# conda install ipympl -c conda-forge -# -# See `jupyter-matplotlib `__ -# for more details. -# -# .. _QT_API-usage: -# -# How do I select PyQt5 or PySide2? -# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -# -# The :envvar:`QT_API` environment variable can be set to either ``pyqt5`` or -# ``pyside2`` to use ``PyQt5`` or ``PySide2``, respectively. -# -# Since the default value for the bindings to be used is ``PyQt5``, Matplotlib -# first tries to import it. If the import fails, it tries to import -# ``PySide2``. -# -# Using non-builtin backends -# -------------------------- -# More generally, any importable backend can be selected by using any of the -# methods above. If ``name.of.the.backend`` is the module containing the -# backend, use ``module://name.of.the.backend`` as the backend name, e.g. -# ``matplotlib.use('module://name.of.the.backend')``. -# -# -# .. _interactive-mode: -# -# What is interactive mode? -# ========================= -# -# Use of an interactive backend (see :ref:`what-is-a-backend`) -# permits--but does not by itself require or ensure--plotting -# to the screen. Whether and when plotting to the screen occurs, -# and whether a script or shell session continues after a plot -# is drawn on the screen, depends on the functions and methods -# that are called, and on a state variable that determines whether -# Matplotlib is in "interactive mode." The default Boolean value is set -# by the :file:`matplotlibrc` file, and may be customized like any other -# configuration parameter (see :doc:`/tutorials/introductory/customizing`). It -# may also be set via :func:`matplotlib.interactive`, and its -# value may be queried via :func:`matplotlib.is_interactive`. Turning -# interactive mode on and off in the middle of a stream of plotting -# commands, whether in a script or in a shell, is rarely needed -# and potentially confusing. In the following, we will assume all -# plotting is done with interactive mode either on or off. -# -# .. note:: -# Major changes related to interactivity, and in particular the -# role and behavior of :func:`~matplotlib.pyplot.show`, were made in the -# transition to Matplotlib version 1.0, and bugs were fixed in -# 1.0.1. Here we describe the version 1.0.1 behavior for the -# primary interactive backends, with the partial exception of -# *macosx*. -# -# Interactive mode may also be turned on via :func:`matplotlib.pyplot.ion`, -# and turned off via :func:`matplotlib.pyplot.ioff`. -# -# .. note:: -# Interactive mode works with suitable backends in ipython and in -# the ordinary Python shell, but it does *not* work in the IDLE IDE. -# If the default backend does not support interactivity, an interactive -# backend can be explicitly activated using any of the methods discussed -# in `What is a backend?`_. -# -# -# Interactive example -# -------------------- -# -# From an ordinary Python prompt, or after invoking ipython with no options, -# try this:: -# -# import matplotlib.pyplot as plt -# plt.ion() -# plt.plot([1.6, 2.7]) -# -# This will pop up a plot window. Your terminal prompt will remain active, so -# that you can type additional commands such as:: -# -# plt.title("interactive test") -# plt.xlabel("index") -# -# On most interactive backends, the figure window will also be updated if you -# change it via the object-oriented interface. That is, get a reference to the -# `~matplotlib.axes.Axes` instance, and call a method of that instance:: -# -# ax = plt.gca() -# ax.plot([3.1, 2.2]) -# -# If you are using certain backends (like ``macosx``), or an older version -# of Matplotlib, you may not see the new line added to the plot immediately. -# In this case, you need to explicitly call :func:`~matplotlib.pyplot.draw` -# in order to update the plot:: -# -# plt.draw() -# -# -# Non-interactive example -# ----------------------- -# -# Start a new session as per the previous example, but now -# turn interactive mode off:: -# -# import matplotlib.pyplot as plt -# plt.ioff() -# plt.plot([1.6, 2.7]) -# -# Nothing happened--or at least nothing has shown up on the -# screen (unless you are using *macosx* backend, which is -# anomalous). To make the plot appear, you need to do this:: -# -# plt.show() -# -# Now you see the plot, but your terminal command line is -# unresponsive; `.pyplot.show()` *blocks* the input -# of additional commands until you manually close the plot -# window. -# -# Using a blocking function has benefits to users. Suppose a user -# needs a script that plots the contents of a file to the screen. -# The user may want to look at that plot, and then end the script. -# Without a blocking command such as ``show()``, the script would -# flash up the plot and then end immediately, leaving nothing on -# the screen. -# -# In addition, non-interactive mode delays all drawing until -# ``show()`` is called. This is more efficient than redrawing -# the plot each time a line in the script adds a new feature. -# -# Prior to version 1.0, ``show()`` generally could not be called -# more than once in a single script (although sometimes one -# could get away with it). For version 1.0.1 and above, this -# restriction is lifted, so one can write a script like this:: -# -# import numpy as np -# import matplotlib.pyplot as plt -# -# plt.ioff() -# for i in range(3): -# plt.plot(np.random.rand(10)) -# plt.show() -# -# This makes three plots, one at a time. That is, the second plot will show up -# once the first plot is closed. -# -# Summary -# ------- -# -# In interactive mode, pyplot functions automatically draw -# to the screen. -# -# When plotting interactively, if using -# object method calls in addition to pyplot functions, then -# call :func:`~matplotlib.pyplot.draw` whenever you want to -# refresh the plot. -# -# Use non-interactive mode in scripts in which you want to -# generate one or more figures and display them before ending -# or generating a new set of figures. In that case, use -# :func:`~matplotlib.pyplot.show` to display the figure(s) and -# to block execution until you have manually destroyed them. -# -# .. _performance: -# -# Performance -# =========== -# -# Whether exploring data in interactive mode or programmatically -# saving lots of plots, rendering performance can be a challenging -# bottleneck in your pipeline. Matplotlib provides multiple -# ways to greatly reduce rendering time at the cost of a slight -# change (to a settable tolerance) in your plot's appearance. -# The methods available to reduce rendering time depend on the -# type of plot that is being created. -# -# Line segment simplification -# --------------------------- -# -# For plots that have line segments (e.g. typical line plots, outlines -# of polygons, etc.), rendering performance can be controlled by -# :rc:`path.simplify` and :rc:`path.simplify_threshold`, which -# can be defined e.g. in the :file:`matplotlibrc` file (see -# :doc:`/tutorials/introductory/customizing` for more information about -# the :file:`matplotlibrc` file). :rc:`path.simplify` is a Boolean -# indicating whether or not line segments are simplified at all. -# :rc:`path.simplify_threshold` controls how much line segments are simplified; -# higher thresholds result in quicker rendering. -# -# The following script will first display the data without any -# simplification, and then display the same data with simplification. -# Try interacting with both of them:: -# -# import numpy as np -# import matplotlib.pyplot as plt -# import matplotlib as mpl -# -# # Setup, and create the data to plot -# y = np.random.rand(100000) -# y[50000:] *= 2 -# y[np.geomspace(10, 50000, 400).astype(int)] = -1 -# mpl.rcParams['path.simplify'] = True -# -# mpl.rcParams['path.simplify_threshold'] = 0.0 -# plt.plot(y) -# plt.show() -# -# mpl.rcParams['path.simplify_threshold'] = 1.0 -# plt.plot(y) -# plt.show() -# -# Matplotlib currently defaults to a conservative simplification -# threshold of ``1/9``. To change default settings to use a different -# value, change the :file:`matplotlibrc` file. Alternatively, users -# can create a new style for interactive plotting (with maximal -# simplification) and another style for publication quality plotting -# (with minimal simplification) and activate them as necessary. See -# :doc:`/tutorials/introductory/customizing` for instructions on -# how to perform these actions. -# -# -# The simplification works by iteratively merging line segments -# into a single vector until the next line segment's perpendicular -# distance to the vector (measured in display-coordinate space) -# is greater than the ``path.simplify_threshold`` parameter. -# -# .. note:: -# Changes related to how line segments are simplified were made -# in version 2.1. Rendering time will still be improved by these -# parameters prior to 2.1, but rendering time for some kinds of -# data will be vastly improved in versions 2.1 and greater. -# -# Marker simplification -# --------------------- -# -# Markers can also be simplified, albeit less robustly than -# line segments. Marker simplification is only available -# to :class:`~matplotlib.lines.Line2D` objects (through the -# ``markevery`` property). Wherever -# :class:`~matplotlib.lines.Line2D` construction parameters -# are passed through, such as -# :func:`matplotlib.pyplot.plot` and -# :meth:`matplotlib.axes.Axes.plot`, the ``markevery`` -# parameter can be used:: -# -# plt.plot(x, y, markevery=10) -# -# The ``markevery`` argument allows for naive subsampling, or an -# attempt at evenly spaced (along the *x* axis) sampling. See the -# :doc:`/gallery/lines_bars_and_markers/markevery_demo` -# for more information. -# -# Splitting lines into smaller chunks -# ----------------------------------- -# -# If you are using the Agg backend (see :ref:`what-is-a-backend`), -# then you can make use of :rc:`agg.path.chunksize` -# This allows users to specify a chunk size, and any lines with -# greater than that many vertices will be split into multiple -# 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 -# decrease rendering time. -# -# The following script will first display the data without any -# chunk size restriction, and then display the same data with -# a chunk size of 10,000. The difference can best be seen when -# the figures are large, try maximizing the GUI and then -# interacting with them:: -# -# import numpy as np -# import matplotlib.pyplot as plt -# import matplotlib as mpl -# mpl.rcParams['path.simplify_threshold'] = 1.0 -# -# # Setup, and create the data to plot -# y = np.random.rand(100000) -# y[50000:] *= 2 -# y[np.geomspace(10, 50000, 400).astype(int)] = -1 -# mpl.rcParams['path.simplify'] = True -# -# mpl.rcParams['agg.path.chunksize'] = 0 -# plt.plot(y) -# plt.show() -# -# mpl.rcParams['agg.path.chunksize'] = 10000 -# plt.plot(y) -# plt.show() -# -# Legends -# ------- -# -# The default legend behavior for axes attempts to find the location -# that covers the fewest data points (``loc='best'``). This can be a -# very expensive computation if there are lots of data points. In -# this case, you may want to provide a specific location. -# -# Using the *fast* style -# ---------------------- -# -# The *fast* style can be used to automatically set -# simplification and chunking parameters to reasonable -# settings to speed up plotting large amounts of data. -# The following code runs it:: -# -# import matplotlib.style as mplstyle -# mplstyle.use('fast') -# -# It is very lightweight, so it works well with other -# styles. Be sure the fast style is applied last -# so that other styles do not overwrite the settings:: -# -# mplstyle.use(['dark_background', 'ggplot', 'fast']) + From 8653dbfee8f0af8e76536232564f5f6923acd0bc Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Tue, 12 Oct 2021 08:40:06 +0200 Subject: [PATCH 2/7] DOC: move usage tutorial info to Users guide rst [skip actions] [skip azp] [skip appveyor] --- doc/users/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/users/index.rst b/doc/users/index.rst index 09ea86ef5eb8..ac5af88b418a 100644 --- a/doc/users/index.rst +++ b/doc/users/index.rst @@ -13,7 +13,6 @@ Usage guide getting_started.rst backends.rst performance.rst - ../gallery/usage.rst explain.rst ../faq/index.rst ../api/index.rst From c758196c348db75eebe6100b9a2ce8463d33814d Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 14 Oct 2021 09:45:31 +0200 Subject: [PATCH 3/7] DOC: move usage tutorial info to Users guide rst [skip actions] [skip azp] [skip appveyor] --- doc/users/getting_started.rst | 11 +++-------- lib/matplotlib/artist.py | 2 +- lib/matplotlib/collections.py | 2 +- lib/matplotlib/image.py | 5 ++--- lib/matplotlib/lines.py | 2 +- 5 files changed, 8 insertions(+), 14 deletions(-) diff --git a/doc/users/getting_started.rst b/doc/users/getting_started.rst index d48b6b454ba7..61eccf2a5781 100644 --- a/doc/users/getting_started.rst +++ b/doc/users/getting_started.rst @@ -22,14 +22,9 @@ Installation conda install matplotlib -Further details are available in the :doc:`Installation Guide `. - -Choosing a backend ------------------- - -Matplotlib needs a "backend" to render your figure, either in its own GUI window, -as part of a notebook, or saved as an image to disk. If you need more information on -choosing a backend, see :ref:`backends`. +Further details are available in the :doc:`Installation Guide `. If a +plot does not show up, we probably could not automatically find an appropriate backend; please +check :ref:`troubleshooting-faq`. Draw a first plot ----------------- diff --git a/lib/matplotlib/artist.py b/lib/matplotlib/artist.py index 179badd3598e..cc8f6f61c0ac 100644 --- a/lib/matplotlib/artist.py +++ b/lib/matplotlib/artist.py @@ -300,7 +300,7 @@ def stale(self, val): if val and self.stale_callback is not None: self.stale_callback(self, val) - def get_window_extent(self, renderer): + def get_window_extent(self, renderer=None): """ Get the axes bounding box in display space. diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 619c62b5ca14..cf765a267c11 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -303,7 +303,7 @@ def get_datalim(self, transData): return bbox return transforms.Bbox.null() - def get_window_extent(self, renderer): + def get_window_extent(self, renderer=None): # TODO: check to ensure that this does not fail for # cases other than scatter plot legend return self.get_datalim(transforms.IdentityTransform()) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 2d8cdf1691e4..e71659e80303 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1409,12 +1409,11 @@ def __init__(self, bbox, self.bbox = bbox def get_window_extent(self, renderer=None): - if renderer is None: - renderer = self.get_figure()._cachedRenderer - if isinstance(self.bbox, BboxBase): return self.bbox elif callable(self.bbox): + if renderer is None: + renderer = self.get_figure()._cachedRenderer return self.bbox(renderer) else: raise ValueError("Unknown type of bbox") diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index f1efd125a4ed..38284016f051 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -619,7 +619,7 @@ def set_picker(self, p): self.pickradius = p self._picker = p - def get_window_extent(self, renderer): + def get_window_extent(self, renderer=None): bbox = Bbox([[0, 0], [0, 0]]) trans_data_to_xy = self.get_transform().transform bbox.update_from_data_xy(trans_data_to_xy(self.get_xydata()), From a8d36204a1bb71a9f50ae7c52c3aad30b72409f8 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 14 Oct 2021 13:13:59 +0200 Subject: [PATCH 4/7] DOC: move usage tutorial info to Users guide rst [skip actions] [skip azp] [skip appveyor] --- doc/users/getting_started.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/users/getting_started.rst b/doc/users/getting_started.rst index 61eccf2a5781..3197a8a0f3a8 100644 --- a/doc/users/getting_started.rst +++ b/doc/users/getting_started.rst @@ -22,9 +22,7 @@ Installation conda install matplotlib -Further details are available in the :doc:`Installation Guide `. If a -plot does not show up, we probably could not automatically find an appropriate backend; please -check :ref:`troubleshooting-faq`. +Further details are available in the :doc:`Installation Guide `. Draw a first plot ----------------- @@ -45,6 +43,8 @@ Here is a minimal example plot you can try out: ax.plot(x, y) plt.show() +If a plot does not show up, we probably could not automatically find an appropriate backend; +please check :ref:`troubleshooting-faq`. Where to go next ---------------- From edb0ac6a096a26ddb48ab192f38531506e65c641 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 14 Oct 2021 13:32:26 +0200 Subject: [PATCH 5/7] DOC: move usage tutorial info to Users guide rst [skip actions] [skip azp] [skip appveyor] --- doc/users/getting_started.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/users/getting_started.rst b/doc/users/getting_started.rst index 3197a8a0f3a8..1cb7c97952da 100644 --- a/doc/users/getting_started.rst +++ b/doc/users/getting_started.rst @@ -43,8 +43,7 @@ Here is a minimal example plot you can try out: ax.plot(x, y) plt.show() -If a plot does not show up, we probably could not automatically find an appropriate backend; -please check :ref:`troubleshooting-faq`. +If a plot does not show up please check :ref:`troubleshooting-faq`. Where to go next ---------------- From bb7e24095ef25af3f6d4966df8a0de1d5ca9cf65 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 14 Oct 2021 22:17:10 +0200 Subject: [PATCH 6/7] DOC: move usage tutorial info to Users guide rst [skip actions] [skip azp] [skip appveyor] --- lib/matplotlib/artist.py | 2 +- lib/matplotlib/collections.py | 2 +- lib/matplotlib/image.py | 5 +++-- lib/matplotlib/lines.py | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/artist.py b/lib/matplotlib/artist.py index cc8f6f61c0ac..5f0234c5851c 100644 --- a/lib/matplotlib/artist.py +++ b/lib/matplotlib/artist.py @@ -300,7 +300,7 @@ def stale(self, val): if val and self.stale_callback is not None: self.stale_callback(self, val) - def get_window_extent(self, renderer=None): + def get_window_extent(self): """ Get the axes bounding box in display space. diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index cf765a267c11..0c2c2298df7c 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -303,7 +303,7 @@ def get_datalim(self, transData): return bbox return transforms.Bbox.null() - def get_window_extent(self, renderer=None): + def get_window_extent(self): # TODO: check to ensure that this does not fail for # cases other than scatter plot legend return self.get_datalim(transforms.IdentityTransform()) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index e71659e80303..2d8cdf1691e4 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -1409,11 +1409,12 @@ def __init__(self, bbox, self.bbox = bbox def get_window_extent(self, renderer=None): + if renderer is None: + renderer = self.get_figure()._cachedRenderer + if isinstance(self.bbox, BboxBase): return self.bbox elif callable(self.bbox): - if renderer is None: - renderer = self.get_figure()._cachedRenderer return self.bbox(renderer) else: raise ValueError("Unknown type of bbox") diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index 38284016f051..f1efd125a4ed 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -619,7 +619,7 @@ def set_picker(self, p): self.pickradius = p self._picker = p - def get_window_extent(self, renderer=None): + def get_window_extent(self, renderer): bbox = Bbox([[0, 0], [0, 0]]) trans_data_to_xy = self.get_transform().transform bbox.update_from_data_xy(trans_data_to_xy(self.get_xydata()), From 1c346b8885346e3d7ce00b4b6b955a6a7c2635c1 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 14 Oct 2021 22:18:27 +0200 Subject: [PATCH 7/7] DOC: move usage tutorial info to Users guide rst [skip actions] [skip azp] [skip appveyor] --- lib/matplotlib/artist.py | 2 +- lib/matplotlib/collections.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/artist.py b/lib/matplotlib/artist.py index 5f0234c5851c..179badd3598e 100644 --- a/lib/matplotlib/artist.py +++ b/lib/matplotlib/artist.py @@ -300,7 +300,7 @@ def stale(self, val): if val and self.stale_callback is not None: self.stale_callback(self, val) - def get_window_extent(self): + def get_window_extent(self, renderer): """ Get the axes bounding box in display space. diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 0c2c2298df7c..619c62b5ca14 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -303,7 +303,7 @@ def get_datalim(self, transData): return bbox return transforms.Bbox.null() - def get_window_extent(self): + def get_window_extent(self, renderer): # TODO: check to ensure that this does not fail for # cases other than scatter plot legend return self.get_datalim(transforms.IdentityTransform())