Umfassendes Beispiel#
# Enabling the `widget` backend.
# This requires jupyter-matplotlib a.k.a. ipympl.
# ipympl can be install via pip or conda.
%matplotlib widget
import matplotlib.pyplot as plt
import numpy as np
# Testing matplotlib interactions with a simple plot
fig = plt.figure()
plt.plot(np.sin(np.linspace(0, 20, 100)));
# Always hide the toolbar
fig.canvas.toolbar_visible = False
# Put it back to its default
fig.canvas.toolbar_visible = 'fade-in-fade-out'
# Change the toolbar position
fig.canvas.toolbar_position = 'top'
# Hide the Figure name at the top of the figure
fig.canvas.header_visible = False
# Hide the footer
fig.canvas.footer_visible = False
# Disable the resizing feature
fig.canvas.resizable = False
# If true then scrolling while the mouse is over the canvas will not move the entire notebook
fig.canvas.capture_scroll = True
Sie können auch display für fig.canvas aufrufen, um das interaktive Diagramm überall im Notebook anzuzeigen.
fig.canvas.toolbar_visible = True
display(fig.canvas)
Oder Sie können display(fig) verwenden, um das aktuelle Diagramm als PNG einzubetten.
display(fig)
3D-Darstellung#
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Grab some test data.
X, Y, Z = axes3d.get_test_data(0.05)
# Plot a basic wireframe.
ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
plt.show()
Subplots#
# A more complex example from the matplotlib gallery
np.random.seed(0)
n_bins = 10
x = np.random.randn(1000, 3)
fig, axes = plt.subplots(nrows=2, ncols=2)
ax0, ax1, ax2, ax3 = axes.flatten()
colors = ['red', 'tan', 'lime']
ax0.hist(x, n_bins, density=1, histtype='bar', color=colors, label=colors)
ax0.legend(prop={'size': 10})
ax0.set_title('bars with legend')
ax1.hist(x, n_bins, density=1, histtype='bar', stacked=True)
ax1.set_title('stacked bar')
ax2.hist(x, n_bins, histtype='step', stacked=True, fill=False)
ax2.set_title('stack step (unfilled)')
# Make a multiple-histogram of data-sets with different length.
x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]
ax3.hist(x_multi, n_bins, histtype='bar')
ax3.set_title('different sample sizes')
fig.tight_layout()
plt.show()
fig.canvas.toolbar_position = 'right'
fig.canvas.toolbar_visible = False
Interaktionen mit anderen Widgets und Layouting#
Wenn Sie die Grafik in ein Layout anderer Widgets einbetten möchten, sollten Sie plt.ioff() aufrufen, bevor Sie die Grafik erstellen, da plt.figure() andernfalls automatisch und außerhalb Ihres Layouts eine Anzeige der Leinwand auslöst.
Ohne Verwendung von ioff#
Hier wird die Grafik zweimal angezeigt. Der Button tut nichts, er wurde nur als Beispiel für das Layouting platziert.
import ipywidgets as widgets
# ensure we are interactive mode
# this is default but if this notebook is executed out of order it may have been turned off
plt.ion()
fig = plt.figure()
ax = fig.gca()
ax.imshow(Z)
widgets.AppLayout(
center=fig.canvas,
footer=widgets.Button(icon='check'),
pane_heights=[0, 6, 1]
)
Behebung der doppelten Anzeige mit ioff#
Wenn wir sicherstellen, dass der interaktive Modus beim Erstellen der Grafik deaktiviert ist, wird die Grafik nur dort angezeigt, wo wir sie haben möchten.
Dazu können Sie plt.ioff() als Kontextmanager verwenden.
with plt.ioff():
fig = plt.figure()
ax = fig.gca()
ax.imshow(Z)
widgets.AppLayout(
center=fig.canvas,
footer=widgets.Button(icon='check'),
pane_heights=[0, 6, 1]
)
Interaktion mit anderen Widgets#
Ändern eines Liniendiagramms mit einem Schieberegler#
# When using the `widget` backend from ipympl,
# fig.canvas is a proper Jupyter interactive widget, which can be embedded in
# an ipywidgets layout. See https://ipywidgets.readthedocs.io/en/stable/examples/Layout%20Templates.html
# One can bound figure attributes to other widget values.
from ipywidgets import AppLayout, FloatSlider
plt.ioff()
slider = FloatSlider(
orientation='horizontal',
description='Factor:',
value=1.0,
min=0.02,
max=2.0
)
slider.layout.margin = '0px 30% 0px 30%'
slider.layout.width = '40%'
fig = plt.figure()
fig.canvas.header_visible = False
fig.canvas.layout.min_height = '400px'
plt.title('Plotting: y=sin({} * x)'.format(slider.value))
x = np.linspace(0, 20, 500)
lines = plt.plot(x, np.sin(slider.value * x))
def update_lines(change):
plt.title('Plotting: y=sin({} * x)'.format(change.new))
lines[0].set_data(x, np.sin(change.new * x))
fig.canvas.draw()
fig.canvas.flush_events()
slider.observe(update_lines, names='value')
AppLayout(
center=fig.canvas,
footer=slider,
pane_heights=[0, 6, 1]
)
Aktualisieren von Bilddaten auf performante Weise#
Zwei nützliche Tricks zur Leistungssteigerung bei der Aktualisierung eines mit Matplotlib angezeigten Bildes sind:
Verwenden Sie die Methode
set_dataanstelle des Aufrufs von imshowVorberechnen und dann Indizieren des Arrays
# precomputing all images
x = np.linspace(0,np.pi,200)
y = np.linspace(0,10,200)
X,Y = np.meshgrid(x,y)
parameter = np.linspace(-5,5)
example_image_stack = np.sin(X)[None,:,:]+np.exp(np.cos(Y[None,:,:]*parameter[:,None,None]))
with plt.ioff():
fig = plt.figure()
im = plt.imshow(example_image_stack[0])
def update(change):
im.set_data(example_image_stack[change['new']])
fig.canvas.draw_idle()
slider = widgets.IntSlider(value=0, min=0, max=len(parameter)-1)
slider.observe(update, names='value')
widgets.VBox([slider, fig.canvas])
Debuggen von Widget-Updates und Matplotlib-Callbacks#
Wenn in der update-Funktion ein Fehler auftritt, wird dieser nicht immer im Notebook angezeigt, was das Debugging erschweren kann. Dieses Problem besteht auch für Matplotlib-Callbacks bei Benutzerereignissen wie Mausbewegungen, siehe z. B. Issue. Es gibt zwei Möglichkeiten, die Ausgabe zu sehen:
In JupyterLab wird die Ausgabe in der Log-Konsole angezeigt (Ansicht > Log-Konsole anzeigen)
Verwendung von
ipywidgets.Output
Hier ist ein Beispiel für die Verwendung eines Output-Widgets, um Fehler in der Update-Funktion des vorherigen Beispiels abzufangen. Um Fehler zu provozieren, haben wir die Grenzen des Schiebereglers geändert, damit Fehler außerhalb des Bereichs auftreten.
Von: slider = widgets.IntSlider(value=0, min=0, max=len(parameter)-1)
Zu: slider = widgets.IntSlider(value=0, min=0, max=len(parameter)+10)
Wenn Sie den Schieberegler ganz nach rechts schieben, sollten Sie Fehler im Output-Widget sehen.
with plt.ioff():
fig = plt.figure()
im = plt.imshow(example_image_stack[0])
out = widgets.Output()
@out.capture()
def update(change):
with out:
if change['name'] == 'value':
im.set_data(example_image_stack[change['new']])
fig.canvas.draw_idle
slider = widgets.IntSlider(value=0, min=0, max=len(parameter)+10)
slider.observe(update)
display(widgets.VBox([slider, fig.canvas]))
display(out)