8000 DOC: Start to document interactive figures by tacaswell · Pull Request #4779 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

DOC: Start to document interactive figures #4779

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 36 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cfa717a
DOC: Start to document interactive figures
tacaswell Jul 24, 2015
206f99c
DOC: improve text
tacaswell Jul 31, 2015
fa36c95
DOC: address comments
tacaswell Jan 7, 2017
8b28c01
DOC/WIP: updates to docs on how event loops work
tacaswell Jul 28, 2017
7189eed
DOC: add blocking_input docs
tacaswell Dec 28, 2017
98ae26c
WIP: Lots of text changes to interactive guide
tacaswell Dec 28, 2017
6263284
MNT: add warnings to Figure.show
tacaswell Dec 29, 2017
09deda3
DOC: re-arrange shell.rst and interactive.rst
tacaswell Jan 3, 2018
ec4230a
DOC/WIP: more edits and content
tacaswell Jul 10, 2018
d1a7a3e
WIP: more notes
tacaswell Mar 2, 2019
b49973a
DOC: merge the blocking API docs together
tacaswell Apr 28, 2020
bb8058a
DOC: remove rst files that have been merged into interactive.rst
tacaswell Apr 28, 2020
bc4ecd5
DOC: fix and sort intersphinx
tacaswell Apr 28, 2020
49f49fa
DOC: re-write pyplot.show docstring
tacaswell Apr 29, 2020
8000
295d71d
DOC: plt.pause is no longer experimental
tacaswell Apr 29, 2020
c3c5013
DOC: update pyplot documentation
tacaswell Apr 30, 2020
d9df057
DOC: Lots of editing to interactive figure documentation
tacaswell Apr 30, 2020
7b0b327
DOC: it's -> its
tacaswell Apr 30, 2020
5a426d6
DOC: spelling
tacaswell Apr 30, 2020
8ab0a65
DOC: edits from review
tacaswell May 1, 2020
d70d5ad
DOC: update skipped references
tacaswell May 1, 2020
757e040
DOC: correct many spelling / grammer / clarity issues
tacaswell May 3, 2020
b0690ff
DOC: remove badly named and superfluous heading
tacaswell May 7, 2020
cc3ac5b
DOC: address review comments
tacaswell May 7, 2020
afe9edd
DOC: edits from review
tacaswell May 7, 2020
e09cab9
DOC: more small edits
tacaswell May 7, 2020
04f2fc6
DOC: fix spyder spelling
tacaswell May 7, 2020
9d842bf
DOC: edits from review
tacaswell May 7, 2020
41e19a8
MNT: remove unused import
tacaswell May 7, 2020
eda2ed3
DOC: edits from review
tacaswell May 9, 2020
7cf68e8
DOC: remove non-existent function call
tacaswell May 9, 2020
bfa3589
DOC: edits and duplicate removal
tacaswell May 9, 2020
6edcb47
DOC: windows not widows
tacaswell May 9, 2020
9b492bd
DOC: Revert all changes to blocking_input_api.rst
tacaswell May 9, 2020
6d4747f
DOC: reduce jargon and correct grammar
tacaswell May 20, 2020
f05ea3d
DOC: grammar / wording corrections from review
tacaswell May 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
10000
Diff view
Prev Previous commit
Next Next commit
DOC: edits from review
  • Loading branch information
tacaswell committed May 1, 2020
commit 8ab0a651d14690823c3a93a90ea88f349845a9e3
43 changes: 18 additions & 25 deletions doc/users/interactive.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
.. toctree::


When working with data it is often invaluable to be able to
interact with your plots In many cases the built in pan/zoom
and mouse-location tools are sufficient, but if they are not
you can make use of the Matplotlib event system to build a customized
data exploration tool.
When working with data it is often invaluable to be able to interact
with your plots In many cases the built in pan/zoom and mouse-location
tools are sufficient, but you can also use the Matplotlib event system
to build a customized data exploration tools.

Matplotlib ships with :ref:`backends <what-is-a-backend>` binding to
several GUI toolkits (Qt, Tk, Wx, Gtk, OSX, js) and third party
Expand Down Expand Up @@ -59,7 +58,9 @@ loop is properly integrated with the command line (see
:ref:`interactive mode <controlling-interactive>` use the
``%matplotlib`` magic

.. sourcecode:: ipython
.. highlight:: ipython

::

user@machine:~ $ ipython
Python 3.8.2 (default, Apr 8 2020, 14:31:25)
Expand All @@ -75,33 +76,33 @@ loop is properly integrated with the command line (see

Calling

.. sourcecode:: ipython
::

In [3]: fig, ax = plt.subplots()

will pop open a window for you and

.. sourcecode:: ipython
::

In [4]: ln, = ax.plot(range(5))

will show your data in the window. If you
want to change anything about the line, ex the color
will show your data in the window. If you change something about the
line, for example the color

.. sourcecode:: ipython
::

In [5]: ln.set_color('orange')

will be reflected immediately. If you wish to disable this behavior
you can use
it will be reflected immediately. If you wish to disable this behavior
use

.. sourcecode:: ipython
::

In [6]: plt.ioff()

and

.. sourcecode:: ipython
::

In [7]: plt.ion()

Expand All @@ -112,7 +113,7 @@ sufficient to import `matplotlib.pyplot` and call `.pyplot.ion`, but
using the magic is guaranteed to work regardless of versions.



.. highlight:: python

.. _controlling-interactive:

Expand Down Expand Up @@ -228,7 +229,7 @@ If you can not or do not want to use IPython, interactive mode works
in the vanilla python prompt


.. sourcecode:: python
.. sourcecode:: pycon

>>> import matplotlib.pyplot as plt
>>> plt.ion()
Expand All @@ -253,14 +254,6 @@ Jupyter Notebooks / Lab
not be panned / zoomed, take user input, or be updated from other
cells.

Jupyter uses a different architecture than a traditional interactive
terminal. Rather than the user interface running in the same process
as your interpreter, the user interacts with a javascript front end
running in a browser which communicates with a server which in turn
communicates with a kernel that executes your Python. This means
for interactive figures our UI needs to also be written in javascript
and run inside of the jupyter front end.

To get interactive figures in the 'classic' notebook or jupyter lab
use the `ipympl <https://github.com/matplotlib/ipympl>`__ backend
(must be installed separately) which uses the **ipywidget** framework.
Expand Down
100 changes: 61 additions & 39 deletions doc/users/interactive_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
==================================================

Matplotlib supports rich interactive figures by embedding figures into
a GUI window. The basic interactions of panning and zooming in as
Axis to inspect your data is 'baked in' to Matplotlib. This is
a GUI window. The basic interactions of panning and zooming in an
Axes to inspect your data is 'baked in' to Matplotlib. This is
supported by a full mouse and keyboard event handling system that
you can use to build sophisticated interactive graphs.

Expand Down Expand Up @@ -50,7 +50,7 @@ than directly implement the I/O loop [#f2]_. For example "when the
user clicks on this button, please run this function" or "when the
user hits the 'z' key, please run this other function". This allows
users to write reactive, event-driven, programs without having to
delve into the nity-gritty [#f3]_ details of I/O. The core event loop
delve into the nitty-gritty [#f3]_ details of I/O. The core event loop
is sometimes referred to as "the main loop" and is typically started,
depending on the library, by methods with names like ``_exec``,
``run``, or ``start``.
Expand All @@ -75,13 +75,13 @@ interfaces.
Command Prompt Integration
==========================

So far, so good. We have the REPL (like the IPthon terminal) that
So far, so good. We have the REPL (like the IPython terminal) that
lets us interactively send things code to the interpreter and get
results back. We also have the GUI toolkit that run an event loop
waiting for user input and let up register functions to be run when
that happens. However, if we want to do both we have a problem: the
prompt and the GUI event loop are both infinite loops that each think
*they* are in charge! In order for both the prompt and the GUI widows
*they* are in charge! In order for both the prompt and the GUI windows
to be responsive we need a method to allow the loops to 'timeshare' :

1. let the GUI main loop block the python process when you want
Expand Down Expand Up @@ -110,17 +110,21 @@ Blocking the Prompt
The simplest "integration" is to start the GUI event loop in
'blocking' mode and take over the CLI. While the GUI event loop is
running you can not enter new commands into the prompt (your terminal
may echo the charters typed into standard in, but they will not be
may echo the characters typed into the terminal, but they will not be
sent to the Python interpreter because it is busy running the GUI
event loop), but the figure windows will be responsive. Once the
event loop is stopped (leaving any still open figure windows
non-responsive) you will be able to use the prompt again. Re-starting
the event loop will make any open figure responsive again (and will
process and queued up user interaction).
process any queued up user interaction).

To start the event loop until all open figures are closed use
`.pyplot.show` as ``pyplot.show(block=True)``. To start the event
loop for a fixed amount of time (in seconds) use `.pyplot.pause`.
`.pyplot.show` as ::

pyplot.show(block=True)

To start the event loop for a fixed amount of time (in seconds) use
`.pyplot.pause`.

If you are not using `.pyplot` you can start and stop the event loops
via `.FigureCanvasBase.start_event_loop` and
Expand All @@ -130,25 +134,9 @@ large GUI application and the GUI event loop should already be running
for the application.

Away from the prompt, this technique can be very useful if you want to
write a script that pauses for user interaction, see
:ref:`interactive_scripts`.

.. _spin_event_loop:

Explicitly spinning the Event Loop
----------------------------------

.. autosummary::
:template: autosummary.rst
:nosignatures:

backend_bases.FigureCanvasBase.flush_events
backend_bases.FigureCanvasBase.draw_idle



This is particularly useful if you want to provide updates to a plot
during a long computation.
write a script that pauses for user interaction, or displays a figure
between polling for additional data. See :ref:`interactive_scripts`
for more details.


Input Hook integration
Expand Down Expand Up @@ -197,8 +185,8 @@ more details.

.. _interactive_scripts :

Scripts
=======
Scripts and functions
=====================


.. autosummary::
Expand All @@ -211,21 +199,58 @@ Scripts
figure.Figure.ginput
pyplot.ginput

pyplot.show
pyplot.pause

There are several use-cases for using interactive figures in scripts:

- progress updates as a long running script progresses
- capture user input to steer the script
- progress updates as a long running script progresses
- streaming updates from a data source

Blocking functions
------------------

In the first if you only need to collect points in an Axes you can use
If you only need to collect points in an Axes you can use
`.figure.Figure.ginput` or more generally the tools from
`.blocking_input` the tools will take care of starting and stopping
the event loop for you. However if you have written some custom event
handling or are using `.widgets` you will need to manually run the GUI
event loop using the methods described :ref:`above <cp_block_the_prompt>`.

In the second caes, if you have open windows that have pending UI
You can also use the methods described in :ref:`cp_block_the_prompt`
to suspend run the GUI event loop. Once the loop exits your code will
resume. In general, anyplace you would use `time.sleep` you can use
`.pyplot.pause` instead with the added benefit of interactive figures.

For example, if you want to poll for data you could use something like ::

fig, ax = plt.subplots()
ln, = ax.plot([], [])

while True:
x, y = get_new_data()
ln.set_data(x, y)
fig.canvas.draw_idle()
plt.pause(1)

which would poll for new data and update the figure at 1Hz.

.. _spin_event_loop:

Explicitly spinning the Event Loop
----------------------------------

.. autosummary::
:template: autosummary.rst
:nosignatures:

backend_bases.FigureCanvasBase.flush_events
backend_bases.FigureCanvasBase.draw_idle



If you have open windows that have pending UI
events (mouse clicks, button presses, or draws) you can explicitly
process those events by calling `.FigureCanvasBase.flush_events`.
This will run the GUI event loop until all UI events currently waiting
Expand All @@ -243,7 +268,7 @@ For example ::
fig, ax = plt.subplots()
fig.canvas.show()
th = np.linspace(0, 2*np.pi, 512)
ax.set_Lima(-1.5, 1.5)
ax.set_ylim(-1.5, 1.5)

ln, = ax.plot(th, np.sin(th))

Expand Down Expand Up @@ -281,9 +306,6 @@ The more frequently you call `.FigureCanvasBase.flush_events` the more
responsive your figure will feel but at the cost of spending more
resource on the visualization and less on your computation.

The third case you will have to integrate updating the ``Aritist``
instances, calling ``draw_idle``, and flushing the GUI event loop with your
data I/O.

.. _stale_artists:

Expand Down Expand Up @@ -312,7 +334,7 @@ the artists parent. If you wish to suppress a given artist from propagating
set this attribute to None.

`.figure.Figure` instances do not have a containing artist and their
default callback is `None`. If you call ``.pyplot.ion` and are not in
default callback is `None`. If you call `.pyplot.ion` and are not in
``IPython`` we will install callback to invoke
`~.backend_bases.FigureCanvasBase.draw_idle` when ever the
`.figure.Figure` becomes stale. In ``IPython`` we use the
Expand Down Expand Up @@ -405,7 +427,7 @@ IPython / prompt toolkit

With IPython >= 5.0 IPython has changed from using cpython's readline
based prompt to a ``prompt_toolkit`` based prompt. ``prompt_toolkit``
has the same conceptual input hook, which is feed into pt via the
has the same conceptual input hook, which is feed into prompt_toolkit via the
:meth:`IPython.terminal.interactiveshell.TerminalInteractiveShell.inputhook`
method. The source for the prompt_toolkit input hooks lives at
:mod:`IPython.terminal.pt_inputhooks`
Expand Down
0