<spanid="interactive-figures-and-eventloops"></span><h1>Interactive Figures and Asynchronous Programming<aclass="headerlink" href="#interactive-figures-and-asynchronous-programming" title="Permalink to this headline">¶</a></h1>
<p>Matplotlib supports rich interactive figures by embedding figures into
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.</p>
<p>This guide is meant to be an introduction to the low-level details of
how Matplotlib integration with a GUI event loop works. For a more
practical introduction to the Matplotlib event API see <aclass="reference internal" href="event_handling.html#event-handling-tutorial"><spanclass="std std-ref">event
handling system</span></a>, <aclass="reference external" href="https://github.com/matplotlib/interactive_tutorial">Interactive Tutorial</a>, and
<aclass="reference external" href="http://www.amazon.com/Interactive-Applications-using-Matplotlib-Benjamin/dp/1783988843">Interactive Applications using Matplotlib</a>.</p>
<divclass="section" id="event-loops">
<h2>Event Loops<aclass="headerlink" href="#event-loops" title="Permalink to this headline">¶</a></h2>
<p>Fundamentally, all user interaction (and networking) is implemented as
an infinite loop waiting for events from the user (via the OS) and
then doing something about it. For example, a minimal Read Evaluate
<p>This is missing many niceties (for example, it exits on the first
exception!), but is representative of the event loops that underlie
all terminals, GUIs, and servers <aclass="footnote-reference" href="#f1" id="id1">[1]</a>. In general the <em>Read</em> step
is waiting on some sort of I/O -- be it user input or the network --
while the <em>Evaluate</em> and <em>Print</em> are responsible for interpreting the
input and then <strong>doing</strong> something about it.</p>
<p>In practice we interact with a framework that provides a mechanism to
register callbacks to be run in response to specific events rather
than directly implement the I/O loop <aclass="footnote-reference" href="#f2" id="id2">[2]</a>. 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 nitty-gritty <aclass="footnote-reference" href="#f3" id="id3">[3]</a> 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 <codeclass="docutils literal notranslate"><spanclass="pre">_exec</span></code>,
<codeclass="docutils literal notranslate"><spanclass="pre">run</span></code>, or <codeclass="docutils literal notranslate"><spanclass="pre">start</span></code>.</p>
<p>All GUI frameworks (Qt, Wx, Gtk, tk, OSX, or web) have some method of
capturing user interactions and passing them back to the application
(for example <codeclass="docutils literal notranslate"><spanclass="pre">Signal</span></code> / <codeclass="docutils literal notranslate"><spanclass="pre">Slot</span></code> framework in Qt) but the exact
details depend on the toolkit. Matplotlib has a <aclass="reference internal" href="../tutorials/introductory/usage.html#what-is-a-backend"><spanclass="std std-ref">backend</span></a> for each GUI toolkit we support which uses the
toolkit API to bridge the toolkit UI events into Matplotlib's <aclass="reference internal" href="event_handling.html#event-handling-tutorial"><spanclass="std std-ref">event
handling system</span></a>. You can then use
<aclass="reference internal" href="../api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.mpl_connect" title="matplotlib.backend_bases.FigureCanvasBase.mpl_connect"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">FigureCanvasBase.mpl_connect</span></code></a> to connect your function to
Matplotlib's event handling system. This allows you to directly
interact with your data and write GUI toolkit agnostic user
<spanid="cp-integration"></span><h2>Command Prompt Integration<aclass="headerlink" href="#command-prompt-integration" title="Permalink to this headline">¶</a></h2>
<p>So far, so good. We have the REPL (like the IPython terminal) that
lets us interactively send code to the interpreter and get results
back. We also have the GUI toolkit that runs an event loop waiting
for user input and lets us 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 <em>they</em>
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' :</p>
<olclass="arabic simple">
<li>let the GUI main loop block the python process when you want
interactive windows</li>
<li>let the CLI main loop block the python process and intermittently
run the GUI loop</li>
<li>fully embed python in the GUI (but this is basically writing a full
application)</li>
</ol>
<divclass="section" id="blocking-the-prompt">
<spanid="cp-block-the-prompt"></span><h3>Blocking the Prompt<aclass="headerlink" href="#blocking-the-prompt" title="Permalink to this headline">¶</a></h3>
<p>If you are not using <aclass="reference internal" href="../api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot" title="matplotlib.pyplot"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">pyplot</span></code></a> you can start and stop the event loops
via <aclass="reference internal" href="../api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.start_event_loop" title="matplotlib.backend_bases.FigureCanvasBase.start_event_loop"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">FigureCanvasBase.start_event_loop</span></code></a> and
<aclass="reference internal" href="../api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.stop_event_loop" title="matplotlib.backend_bases.FigureCanvasBase.stop_event_loop"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">FigureCanvasBase.stop_event_loop</span></code></a>. However, in most contexts where
you would not be using <aclass="reference internal" href="../api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot" title="matplotlib.pyplot"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">pyplot</span></code></a> you are embedding Matplotlib in a
large GUI application and the GUI event loop should already be running
for the application.</p>
<p>Away from the prompt, this technique can be very useful if you want to
write a script that pauses for user interaction, or displays a figure
between polling for additional data. See <aclass="reference internal" href="#interactive-scripts"><spanclass="std std-ref">Scripts and functions</span></a>
for more details.</p>
</div>
<divclass="section" id="input-hook-integration">
<h3>Input Hook integration<aclass="headerlink" href="#input-hook-integration" title="Permalink to this headline">¶</a></h3>
<p>While running the GUI event loop in a blocking mode or explicitly
handling UI events is useful, we can do better! We really want to be
able to have a usable prompt <strong>and</strong> interactive figure windows.</p>
<p>We can do this using the 'input hook' feature of the interactive
prompt. This hook is called by the prompt as it waits for the user
to type (even for a fast typist the prompt is mostly waiting for the
human to think and move their fingers). Although the details vary
between prompts the logic is roughly</p>
<olclass="arabic simple">
<li>start to wait for keyboard input</li>
<li>start the GUI event loop</li>
<li>as soon as the user hits a key, exit the GUI event loop and handle the key</li>
<li>repeat</li>
</ol>
<p>This gives us the illusion of simultaneously having interactive GUI
windows and an interactive prompt. Most of the time the GUI event
loop is running, but as soon as the user starts typing the prompt
takes over again.</p>
<p>This time-share technique only allows the event loop to run while
python is otherwise idle and waiting for user input. If you want the
GUI to be responsive during long running code it is necessary to
periodically flush the GUI event queue as described <aclass="reference internal" href="#spin-event-loop"><spanclass="std std-ref">above</span></a>. In this case it is your code, not the REPL, which
is blocking the process so you need to handle the "time-share" manually.
Conversely, a very slow figure draw will block the prompt until it
finishes drawing.</p>
</div>
</div>
<divclass="section" id="full-embedding">
<h2>Full embedding<aclass="headerlink" href="#full-embedding" title="Permalink to this headline">¶</a></h2>
<p>It is also possible to go the other direction and fully embed figures
(and a <aclass="reference external" href="https://docs.python.org/3/extending/embedding.html">Python interpreter</a>) in a rich
native application. Matplotlib provides classes for each toolkit
which can be directly embedded in GUI applications (this is how the
built-in windows are implemented!). See <aclass="reference internal" href="../gallery/index.html#user-interfaces"><spanclass="std std-ref">Embedding Matplotlib in graphical user interfaces</span></a> for
more details.</p>
</div>
<divclass="section" id="scripts-and-functions">
<spanid="interactive-scripts"></span><h2>Scripts and functions<aclass="headerlink" href="#scripts-and-functions" title="Permalink to this headline">¶</a></h2>
<td>Run the GUI event loop for <em>interval</em> seconds.</td>
</tr>
</tbody>
</table>
<p>There are several use-cases for using interactive figures in scripts:</p>
<ulclass="simple">
<li>capture user input to steer the script</li>
<li>progress updates as a long running script progresses</li>
<li>streaming updates from a data source</li>
</ul>
<divclass="section" id="blocking-functions">
<h3>Blocking functions<aclass="headerlink" href="#blocking-functions" title="Permalink to this headline">¶</a></h3>
<p>If you only need to collect points in an Axes you can use
<aclass="reference internal" href="../api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure.ginput" title="matplotlib.figure.Figure.ginput"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">figure.Figure.ginput</span></code></a> or more generally the tools from
<aclass="reference internal" href="../api/blocking_input_api.html#module-matplotlib.blocking_input" title="matplotlib.blocking_input"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">blocking_input</span></code></a> 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 <aclass="reference internal" href="../api/widgets_api.html#module-matplotlib.widgets" title="matplotlib.widgets"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">widgets</span></code></a> you will need to manually run the GUI
event loop using the methods described <aclass="reference internal" href="#cp-block-the-prompt"><spanclass="std std-ref">above</span></a>.</p>
<p>You can also use the methods described in <aclass="reference internal" href="#cp-block-the-prompt"><spanclass="std std-ref">Blocking the Prompt</span></a>
to suspend run the GUI event loop. Once the loop exits your code will
resume. In general, any place you would use <aclass="reference external" href="https://docs.python.org/3/library/time.html#time.sleep" title="(in Python v3.9)"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">time.sleep</span></code></a> you can use
<aclass="reference internal" href="../api/_as_gen/matplotlib.pyplot.pause.html#matplotlib.pyplot.pause" title="matplotlib.pyplot.pause"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">pyplot.pause</span></code></a> instead with the added benefit of interactive figures.</p>
<p>For example, if you want to poll for data you could use something like</p>
<spanid="spin-event-loop"></span><h3>Explicitly spinning the Event Loop<aclass="headerlink" href="#explicitly-spinning-the-event-loop" title="Permalink to this headline">¶</a></h3>
<td>Request a widget redraw once control returns to the GUI event loop.</td>
</tr>
</tbody>
</table>
<p>If you have open windows that have pending UI
events (mouse clicks, button presses, or draws) you can explicitly
process those events by calling <aclass="reference internal" href="../api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.flush_events" title="matplotlib.backend_bases.FigureCanvasBase.flush_events"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">FigureCanvasBase.flush_events</span></code></a>.
This will run the GUI event loop until all UI events currently waiting
have been processed. The exact behavior is backend-dependent but
typically events on all figure are processed and only events waiting
to be processed (not those added during processing) will be handled.</p>
<spanclass="n">time</span><spanclass="o">.</span><spanclass="n">sleep</span><spanclass="p">(</span><spanclass="o">.</span><spanclass="mi">1</span><spanclass="p">)</span><spanclass="c1"># to simulate some work</span>
<p>While this will feel a bit laggy (as we are only processing user input
every 100ms whereas 20-30ms is what feels "responsive") it will
respond.</p>
<p>If you make changes to the plot and want it re-rendered you will need
to call <aclass="reference internal" href="../api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.draw_idle" title="matplotlib.backend_bases.FigureCanvasBase.draw_idle"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">draw_idle</span></code></a> to request that the canvas be
re-drawn. This method can be thought of <em>draw_soon</em> in analogy to
<spanclass="n">time</span><spanclass="o">.</span><spanclass="n">sleep</span><spanclass="p">(</span><spanclass="o">.</span><spanclass="mi">1</span><spanclass="p">)</span><spanclass="c1"># to simulate some work</span>
<p>The more frequently you call <aclass="reference internal" href="../api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.flush_events" title="matplotlib.backend_bases.FigureCanvasBase.flush_events"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">FigureCanvasBase.flush_events</span></code></a> the more
responsive your figure will feel but at the cost of spending more
resources on the visualization and less on your computation.</p>
</div>
</div>
<divclass="section" id="stale-artists">
<spanid="id4"></span><h2>Stale Artists<aclass="headerlink" href="#stale-artists" title="Permalink to this headline">¶</a></h2>
<p>Artists (as of Matplotlib 1.5) have a <strong>stale</strong> attribute which is
<aclass="reference external" href="https://docs.python.org/3/library/constants.html#True" title="(in Python v3.9)"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">True</span></code></a> if the internal state of the artist has changed since the last
time it was rendered. By default the stale state is propagated up to
the Artists parents in the draw tree, e.g., if the color of a <aclass="reference internal" href="../api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D" title="matplotlib.lines.Line2D"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">Line2D</span></code></a>
instance is changed, the <aclass="reference internal" href="../api/axes_api.html#matplotlib.axes.Axes" title="matplotlib.axes.Axes"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">axes.Axes</span></code></a> and <aclass="reference internal" href="../api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure" title="matplotlib.figure.Figure"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">figure.Figure</span></code></a> that
contain it will also be marked as "stale". Thus, <codeclass="docutils literal notranslate"><spanclass="pre">fig.stale</span></code> will
report if any artist in the figure has been modified and is out of sync
with what is displayed on the screen. This is intended to be used to
determine if <codeclass="docutils literal notranslate"><spanclass="pre">draw_idle</span></code> should be called to schedule a re-rendering
of the figure.</p>
<p>Each artist has a <codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">Artist.stale_callback</span></code> attribute which holds a callback
<p>which by default is set to a function that forwards the stale state to
the artist's parent. If you wish to suppress a given artist from propagating
set this attribute to None.</p>
<p><aclass="reference internal" href="../api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure" title="matplotlib.figure.Figure"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">figure.Figure</span></code></a> instances do not have a containing artist and their
default callback is <aclass="reference external" href="https://docs.python.org/3/library/constants.html#None" title="(in Python v3.9)"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">None</span></code></a>. If you call <aclass="reference internal" href="../api/_as_gen/matplotlib.pyplot.ion.html#matplotlib.pyplot.ion" title="matplotlib.pyplot.ion"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">pyplot.ion</span></code></a> and are not in
<codeclass="docutils literal notranslate"><spanclass="pre">IPython</span></code> we will install a callback to invoke
<aclass="reference internal" href="../api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure" title="matplotlib.figure.Figure"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">figure.Figure</span></code></a> becomes stale. In <codeclass="docutils literal notranslate"><spanclass="pre">IPython</span></code> we use the
<codeclass="docutils literal notranslate"><spanclass="pre">'post_execute'</span></code> hook to invoke
<aclass="reference internal" href="../api/backend_bases_api.html#matplotlib.backend_bases.FigureCanvasBase.draw_idle" title="matplotlib.backend_bases.FigureCanvasBase.draw_idle"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">draw_idle</span></code></a> on any stale figures
after having executed the user's input, but before returning the prompt
to the user. If you are not using <aclass="reference internal" href="../api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot" title="matplotlib.pyplot"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">pyplot</span></code></a> you can use the callback
<codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">Figure.stale_callback</span></code> attribute to be notified when a figure has
become stale.</p>
</div>
<divclass="section" id="draw-idle">
<spanid="id5"></span><h2>Draw Idle<aclass="headerlink" href="#draw-idle" title="Permalink to this headline">¶</a></h2>
<h2>Threading<aclass="headerlink" href="#threading" title="Permalink to this headline">¶</a></h2>
<p>Most GUI frameworks require that all updates to the screen, and hence
their main event loop, run on the main thread. This makes pushing
periodic updates of a plot to a background thread impossible.
Although it seems backwards, it is typically easier to push your
computations to a background thread and periodically update
the figure on the main thread.</p>
<p>In general Matplotlib is not thread safe. If you are going to update
<aclass="reference internal" href="../api/artist_api.html#matplotlib.artist.Artist" title="matplotlib.artist.Artist"><codeclass="xref py py-obj docutils literal notranslate"><spanclass="pre">Artist</span></code></a> objects in one thread and draw from another you should make
sure that you are locking in the critical sections.</p>
<h2>Eventloop integration mechanism<aclass="headerlink" href="#eventloop-integration-mechanism" title="Permalink to this headline">¶</a></h2>
<divclass="section" id="cpython-readline">
<h3>CPython / readline<aclass="headerlink" href="#cpython-readline" title="Permalink to this headline">¶</a></h3>
<p>The Python C API provides a hook, <aclass="reference external" href="https://docs.python.org/3/c-api/veryhigh.html#c.PyOS_InputHook" title="(in Python v3.9)"><codeclass="xref c c-data docutils literal notranslate"><spanclass="pre">PyOS_InputHook</span></code></a>, to register a
function to be run "The function will be called when Python's
interpreter prompt is about to become idle and wait for user input
from the terminal.". This hook can be used to integrate a second
event loop (the GUI event loop) with the python input prompt loop.
The hook functions typically exhaust all pending events on the GUI
event queue, run the main loop for a short fixed amount of time, or
run the event loop until a key is pressed on stdin.</p>
<p>Matplotlib does not currently do any management of <aclass="reference external" href="https://docs.python.org/3/c-api/veryhigh.html#c.PyOS_InputHook" title="(in Python v3.9)"><codeclass="xref c c-data docutils literal notranslate"><spanclass="pre">PyOS_InputHook</span></code></a> due
to the wide range of ways that Matplotlib is used. This management is left to
downstream libraries -- either user code or the shell. Interactive figures,
even with matplotlib in 'interactive mode', may not work in the vanilla python
repl if an appropriate <aclass="reference external" href="https://docs.python.org/3/c-api/veryhigh.html#c.PyOS_InputHook" title="(in Python v3.9)"><codeclass="xref c c-data docutils literal notranslate"><spanclass="pre">PyOS_InputHook</span></code></a> is not registered.</p>
<p>Input hooks, and helpers to install them, are usually included with
the python bindings for GUI toolkits and may be registered on import.
IPython also ships input hook functions for all of the GUI frameworks
Matplotlib supports which can be installed via <codeclass="docutils literal notranslate"><spanclass="pre">%matplotlib</span></code>. This
is the recommended method of integrating Matplotlib and a prompt.</p>
</div>
<divclass="section" id="ipython-prompt-toolkit">
<h3>IPython / prompt toolkit<aclass="headerlink" href="#ipython-prompt-toolkit" title="Permalink to this headline">¶</a></h3>
<p>With IPython >= 5.0 IPython has changed from using cpython's readline
based prompt to a <codeclass="docutils literal notranslate"><spanclass="pre">prompt_toolkit</span></code> based prompt. <codeclass="docutils literal notranslate"><spanclass="pre">prompt_toolkit</span></code>
has the same conceptual input hook, which is fed into <codeclass="docutils literal notranslate"><spanclass="pre">prompt_toolkit</span></code> via the
<tr><tdclass="label"><aclass="fn-backref" href="#id2">[2]</a></td><td>Or you can <aclass="reference external" href="https://www.youtube.com/watch?v=ZzfHjytDceU">write your own</a> if you must.</td></tr>