Neues in Matplotlib 3.6.0 (15. September 2022)#

Eine Liste aller Probleme und Pull-Anfragen seit der letzten Überarbeitung finden Sie in den GitHub-Statistiken für 3.10.3 (08. Mai 2025).

Erstellung / Verwaltung von Figuren und Achsen#

subplots, subplot_mosaic akzeptieren die Argumente height_ratios und width_ratios#

Die relativen Breiten und Höhen von Spalten und Zeilen in subplots und subplot_mosaic können durch Übergabe der Schlüsselwortargumente height_ratios und width_ratios an die Methoden gesteuert werden

fig = plt.figure()
axs = fig.subplots(3, 1, sharex=True, height_ratios=[3, 1, 1])

(Quellcode, 2x.png, png)

A figure with three subplots in three rows and one column. The height of the subplot in the first row is three times than the subplots in the 2nd and 3rd row.

Zuvor erforderte dies die Übergabe der Verhältnisse in den gridspec_kw-Argumenten

fig = plt.figure()
axs = fig.subplots(3, 1, sharex=True,
                   gridspec_kw=dict(height_ratios=[3, 1, 1]))

Constrained layout wird nicht länger als experimentell betrachtet#

Die Constrained-Layout-Engine und API wird nicht länger als experimentell betrachtet. Beliebige Änderungen am Verhalten und an der API sind ohne eine Deputationsperiode nicht mehr zulässig.

Neues Modul layout_engine#

Matplotlib liefert die Layout-Engines tight_layout und constrained_layout. Ein neues Modul layout_engine wird bereitgestellt, um nachgelagerten Bibliotheken die Erstellung eigener Layout-Engines zu ermöglichen. Figure-Objekte können nun eine Unterklasse von LayoutEngine als Argument für den layout-Parameter akzeptieren.

Kompaktes Layout für Achsen mit festem Seitenverhältnis#

Einfache Anordnungen von Achsen mit festem Seitenverhältnis können nun mit fig, axs = plt.subplots(2, 3, layout='compressed') zusammengefasst werden.

Mit layout='tight' oder 'constrained' können Achsen mit festem Seitenverhältnis große Lücken zwischen sich lassen

(Quellcode, 2x.png, png)

A figure labelled "fixed-aspect plots, layout=constrained". Figure has subplots displayed in 2 rows and 2 columns; Subplots have large gaps between each other.

Die Verwendung von layout='compressed' reduziert den Abstand zwischen den Achsen und fügt den zusätzlichen Platz den äußeren Rändern hinzu

(Quellcode, 2x.png, png)

Four identical two by two heatmaps, each cell a different color: purple, blue, yellow, green going clockwise from upper left corner. The four heatmaps are laid out in a two by two grid with minimum white space between the heatmaps.

Siehe Gitter von Achsen mit festem Seitenverhältnis: "compressed" Layout für weitere Details.

Layout-Engines können jetzt entfernt werden#

Die Layout-Engine einer Figur kann nun durch Aufruf von Figure.set_layout_engine mit 'none' entfernt werden. Dies kann nach der Layout-Berechnung nützlich sein, um Berechnungen zu reduzieren, z. B. für nachfolgende Animationsschleifen.

Eine andere Layout-Engine kann danach gesetzt werden, solange sie mit der vorherigen Layout-Engine kompatibel ist.

Axes.inset_axes Flexibilität#

matplotlib.axes.Axes.inset_axes akzeptiert nun die Schlüsselwortargumente projection, polar und axes_class, sodass Unterklassen von matplotlib.axes.Axes zurückgegeben werden können.

fig, ax = plt.subplots()

ax.plot([0, 2], [1, 2])

polar_ax = ax.inset_axes([0.75, 0.25, 0.2, 0.2], projection='polar')
polar_ax.plot([0, 2], [1, 2])

(Quellcode, 2x.png, png)

Plot of a straight line y=x, with a small inset axes in the lower right corner that shows a circle with radial grid lines and a line plotted in polar coordinates.

WebP ist jetzt ein unterstütztes Ausgabeformat#

Figuren können jetzt im WebP-Format gespeichert werden, indem die Dateiendung .webp verwendet oder format='webp' an savefig übergeben wird. Dies setzt die Unterstützung von Pillow für WebP voraus.

Garbage Collection wird beim Schließen von Figuren nicht mehr ausgeführt#

Matplotlib weist eine große Anzahl von zirkulären Referenzen auf (zwischen Figure und Manager, zwischen Axes und Figure, Axes und Artist, Figure und Canvas usw.), sodass, wenn der Benutzer seine letzte Referenz auf eine Figure fallen lässt (und sie aus dem Pyplot-Zustand löscht), die Objekte nicht sofort gelöscht werden.

Um dies zu berücksichtigen, hatten wir lange Zeit (seit vor 2004) eine gc.collect (nur der beiden niedrigsten Generationen) im Schließcode, um uns umgehend aufzuräumen. Dies tat jedoch weder das, was wir wollten (da die meisten unserer Objekte überleben würden), noch hat es uns durch das Leeren der ersten Generation anfällig für unbegrenzte Speichernutzung gemacht.

In Fällen mit einer sehr engen Schleife zwischen dem Erstellen und Zerstören der Figur (z. B. plt.figure(); plt.close()) wird die erste Generation nie groß genug, damit Python die Sammlung der höheren Generationen ausführt. Dies führt zu unbegrenzter Speichernutzung, da die langlebigen Objekte nie erneut für Referenzzyklen geprüft werden und daher nie gelöscht werden.

Wir führen nun keine Garbage Collection mehr durch, wenn eine Figur geschlossen wird, und verlassen uns darauf, dass Python die Garbage Collection periodisch automatisch ausführt. Wenn Sie strenge Speicheranforderungen haben, können Sie gc.collect selbst aufrufen, dies kann jedoch Leistungseinbußen in einer engen Rechenschleife haben.

Plotting-Methoden#

Gestreifte Linien (experimentell)#

Der neue Parameter gapcolor für plot ermöglicht die Erstellung von gestreiften Linien.

x = np.linspace(1., 3., 10)
y = x**3

fig, ax = plt.subplots()
ax.plot(x, y, linestyle='--', color='orange', gapcolor='blue',
        linewidth=3, label='a striped line')
ax.legend()

(Quellcode, 2x.png, png)

Plot of x**3 where the line is an orange-blue striped line, achieved using the keywords linestyle='--', color='orange', gapcolor='blue'

Benutzerdefinierte Kappenbreiten in Box- und Whisker-Plots in bxp und boxplot#

Der neue Parameter capwidths für bxp und boxplot ermöglicht die Steuerung der Breiten der Kappen in Box- und Whisker-Plots.

x = np.linspace(-7, 7, 140)
x = np.hstack([-25, x, 25])
capwidths = [0.01, 0.2]

fig, ax = plt.subplots()
ax.boxplot([x, x], notch=True, capwidths=capwidths)
ax.set_title(f'{capwidths=}')

(Quellcode, 2x.png, png)

A box plot with capwidths 0.01 and 0.2

Einfacheres Beschriften von Balken in Balkendiagrammen#

Das label-Argument von bar und barh kann nun eine Liste von Labels für die Balken empfangen. Die Liste muss die gleiche Länge wie x haben und beschriftet die einzelnen Balken. Wiederholte Labels werden nicht dedupliziert und führen zu wiederholten Label-Einträgen. Dies ist daher am besten geeignet, wenn sich Balken auch stilistisch unterscheiden (z. B. durch Übergabe einer Liste an color, wie unten gezeigt).

x = ["a", "b", "c"]
y = [10, 20, 15]
color = ['C0', 'C1', 'C2']

fig, ax = plt.subplots()
ax.bar(x, y, color=color, label=x)
ax.legend()

(Quellcode, 2x.png, png)

Bar chart: blue bar height 10, orange bar height 20, green bar height 15 legend with blue box labeled a, orange box labeled b, and green box labeled c

Neuer Format-String für Farbleisten-Ticks#

Das format-Argument von colorbar (und andere Farbleisten-Methoden) akzeptiert nun Format-Strings im {}-Stil.

fig, ax = plt.subplots()
im = ax.imshow(z)
fig.colorbar(im, format='{x:.2e}')  # Instead of '%.2e'

Linienstile für negative Konturen können individuell gesetzt werden#

Der Linienstil negativer Konturen kann durch Übergabe des Arguments negative_linestyles an Axes.contour gesetzt werden. Zuvor konnte dieser Stil nur global über rcParams["contour.negative_linestyle"] (Standard: 'dashed') gesetzt werden.

delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2

fig, axs = plt.subplots(1, 2)

CS = axs[0].contour(X, Y, Z, 6, colors='k')
axs[0].clabel(CS, fontsize=9, inline=True)
axs[0].set_title('Default negative contours')

CS = axs[1].contour(X, Y, Z, 6, colors='k', negative_linestyles='dotted')
axs[1].clabel(CS, fontsize=9, inline=True)
axs[1].set_title('Dotted negative contours')

(Quellcode, 2x.png, png)

Two contour plots, each showing two positive and two negative contours. The positive contours are shown in solid black lines in both plots. In one plot the negative contours are shown in dashed lines, which is the current styling. In the other plot they're shown in dotted lines, which is one of the new options.

Verbesserte Quad-Konturberechnungen über ContourPy#

Die Konturierungsfunktionen contour und contourf haben ein neues Schlüsselwortargument algorithm, um den Algorithmus zur Berechnung der Konturen zu steuern. Es stehen vier Algorithmen zur Auswahl, und der Standard ist algorithm='mpl2014', der gleiche Algorithmus, den Matplotlib seit 2014 verwendet.

Zuvor lieferte Matplotlib eigenen C++-Code für die Berechnung der Konturen von Quad-Gittern. Jetzt wird stattdessen die externe Bibliothek ContourPy verwendet.

Andere mögliche Werte für das Schlüsselwortargument algorithm sind derzeit 'mpl2005', 'serial' und 'threaded'; weitere Einzelheiten finden Sie in der ContourPy-Dokumentation.

Hinweis

Konturlinien und Polygone, die von algorithm='mpl2014' erzeugt werden, sind bis auf Fließkomma-Toleranzen gleich wie die vor dieser Änderung erzeugten. Die Ausnahme bilden doppelte Punkte, d. h. Konturen, die benachbarte (x, y)-Punkte enthalten, die identisch sind; zuvor wurden die doppelten Punkte entfernt, jetzt werden sie beibehalten. Konturen, die davon betroffen sind, erzeugen das gleiche visuelle Ergebnis, aber es gibt eine größere Anzahl von Punkten in den Konturen.

Die Positionen von Kontur-Labels, die mit clabel erhalten werden, können ebenfalls abweichen.

errorbar unterstützt markerfacecoloralt#

Der Parameter markerfacecoloralt wird jetzt vom Linienplotter aus Axes.errorbar an den Linienplotter weitergegeben. Die Dokumentation listet nun genau auf, welche Eigenschaften an Line2D übergeben werden, anstatt zu behaupten, dass alle Schlüsselwortargumente weitergegeben werden.

x = np.arange(0.1, 4, 0.5)
y = np.exp(-x)

fig, ax = plt.subplots()
ax.errorbar(x, y, xerr=0.2, yerr=0.4,
            linestyle=':', color='darkgrey',
            marker='o', markersize=20, fillstyle='left',
            markerfacecolor='tab:blue', markerfacecoloralt='tab:orange',
            markeredgecolor='tab:brown', markeredgewidth=2)

(Quellcode, 2x.png, png)

Graph with error bar showing ±0.2 error on the x-axis, and ±0.4 error on the y-axis. Error bar marker is a circle radius 20. Error bar face color is blue.

streamplot kann Stromlinienbrüche deaktivieren#

Es ist nun möglich, anzugeben, dass Stromlinienplots kontinuierliche, ungebrochene Stromlinien haben sollen. Zuvor brachen Stromlinien ab, um die Anzahl der Linien innerhalb einer einzelnen Gitterzelle zu begrenzen. Sehen Sie den Unterschied zwischen den untenstehenden Plots

(Quellcode, 2x.png, png)

A figure with two streamplots. First streamplot has broken streamlines. Second streamplot has continuous streamlines.

Neue Achsenskala asinh (experimentell)#

Die neue asinh-Achsenskala bietet eine Alternative zu symlog, die nahtlos zwischen den quasi-linearen und asymptotisch logarithmischen Bereichen der Skala wechselt. Dies basiert auf einer Arcsinh-Transformation, die das Plotten sowohl positiver als auch negativer Werte über viele Größenordnungen hinweg ermöglicht.

(Quellcode, 2x.png, png)

Figure with 2 subplots. Subplot on the left uses symlog scale on the y axis. The transition at -2 is not smooth. Subplot on the right use asinh scale. The transition at -2 is smooth.

stairs(..., fill=True) verbirgt Kanten durch Setzen der Liniendicke#

stairs(..., fill=True) versteckte zuvor Patch-Kanten, indem edgecolor="none" gesetzt wurde. Folglich würde das spätere Aufrufen von set_color() auf dem Patch dazu führen, dass der Patch größer erscheint.

Nun wird durch die Verwendung von linewidth=0 diese scheinbare Größenänderung verhindert. Ebenso verhält sich stairs(..., fill=True, linewidth=3) transparenter.

Behebt den Dash-Offset der Patch-Klasse#

Zuvor wurde beim Setzen des Linienstils auf ein Patch-Objekt unter Verwendung eines Dash-Tupels der Offset ignoriert. Jetzt wird der Offset wie erwartet auf den Patch angewendet und kann wie bei Line2D-Objekten verwendet werden.

Drehpunkt für Rechteck-Patches#

Der Drehpunkt des Rectangle kann nun mit dem Argument rotation_point auf 'xy', 'center' oder ein 2er-Tupel von Zahlen gesetzt werden.

(Quellcode, 2x.png, png)

Blue square that isn't rotated. Green square rotated 45 degrees relative to center. Orange square rotated 45 degrees relative to lower right corner. Red square rotated 45 degrees relative to point in upper right quadrant.

Farben und Colormaps#

Registrierung von Farbsequenzen#

Das Registrierungssystem für Farbsequenzen, ColorSequenceRegistry, enthält Sequenzen (d. h. einfache Listen) von Farben, die Matplotlib namentlich bekannt sind. Dies wird normalerweise nicht direkt verwendet, sondern über die universelle Instanz unter matplotlib.color_sequences.

Colormap-Methode zur Erstellung einer anderen Lookup-Tabellengröße#

Die neue Methode Colormap.resampled erstellt eine neue Colormap-Instanz mit der angegebenen Lookup-Tabellengröße. Dies ersetzt die Manipulation der Lookup-Tabellengröße über get_cmap.

Verwenden Sie

get_cmap(name).resampled(N)

statt

get_cmap(name, lut=N)

Normen mit Strings setzen#

Normen können jetzt (z. B. auf Bildern) anhand des String-Namens der entsprechenden Skala gesetzt werden, z. B. imshow(array, norm="log"). Beachten Sie, dass in diesem Fall auch vmin und vmax übergeben werden dürfen, da im Hintergrund eine neue Norm-Instanz erstellt wird.

Titel, Ticks und Beschriftungen#

plt.xticks und plt.yticks unterstützen das Schlüsselwortargument minor#

Es ist nun möglich, Minor-Ticks mit pyplot.xticks und pyplot.yticks durch Setzen von minor=True zu setzen oder abzurufen.

plt.figure()
plt.plot([1, 2, 3, 3.5], [2, 1, 0, -0.5])
plt.xticks([1, 2, 3], ["One", "Zwei", "Trois"])
plt.xticks([np.sqrt(2), 2.5, np.pi],
           [r"$\sqrt{2}$", r"$\frac{5}{2}$", r"$\pi$"], minor=True)

(Quellcode, 2x.png, png)

Plot showing a line from 1,2 to 3.5,-0.5. X axis showing the 1, 2 and 3 minor ticks on the x axis as One, Zwei, Trois.

Legenden#

Legende kann die Ausrichtung von Titel und Handles steuern#

Legend unterstützt nun die Steuerung der Ausrichtung von Titel und Handles über das Schlüsselwortargument alignment. Sie können auch Legend.set_alignment verwenden, um die Ausrichtung auf vorhandenen Legenden zu steuern.

fig, axs = plt.subplots(3, 1)
for i, alignment in enumerate(['left', 'center', 'right']):
    axs[i].plot(range(10), label='test')
    axs[i].legend(title=f'{alignment=}', alignment=alignment)

(Quellcode, 2x.png, png)

Figure with 3 subplots. All the subplots are titled test. The three subplots have legends titled alignment='left', alignment='center', alignment='right'. The legend texts are respectively aligned left, center and right.

Das Schlüsselwortargument ncol für legend wurde in ncols umbenannt#

Das Schlüsselwortargument ncol für legend zur Steuerung der Anzahl der Spalten wurde in ncols umbenannt, um die Konsistenz mit den Schlüsselwörtern ncols und nrows von subplots und GridSpec zu gewährleisten. ncol wird weiterhin aus Gründen der Abwärtskompatibilität unterstützt, wird aber nicht mehr empfohlen.

Marker#

marker kann nun auf den String "none" gesetzt werden#

Der String "none" bedeutet kein-Marker, konsistent mit anderen APIs, die die Kleinbuchstabenversion unterstützen. Die Verwendung von "none" wird gegenüber der Verwendung von "None" empfohlen, um Verwechslungen mit dem None-Objekt zu vermeiden.

Anpassung von MarkerStyle Join- und Cap-Stil#

Neue MarkerStyle-Parameter ermöglichen die Steuerung des Join- und Cap-Stils sowie die Übergabe einer Transformation durch den Benutzer, die auf den Marker angewendet werden soll (z. B. eine Drehung).

from matplotlib.markers import CapStyle, JoinStyle, MarkerStyle
from matplotlib.transforms import Affine2D

fig, axs = plt.subplots(3, 1, layout='constrained')
for ax in axs:
    ax.axis('off')
    ax.set_xlim(-0.5, 2.5)

axs[0].set_title('Cap styles', fontsize=14)
for col, cap in enumerate(CapStyle):
    axs[0].plot(col, 0, markersize=32, markeredgewidth=8,
                marker=MarkerStyle('1', capstyle=cap))
    # Show the marker edge for comparison with the cap.
    axs[0].plot(col, 0, markersize=32, markeredgewidth=1,
                markerfacecolor='none', markeredgecolor='lightgrey',
                marker=MarkerStyle('1'))
    axs[0].annotate(cap.name, (col, 0),
                    xytext=(20, -5), textcoords='offset points')

axs[1].set_title('Join styles', fontsize=14)
for col, join in enumerate(JoinStyle):
    axs[1].plot(col, 0, markersize=32, markeredgewidth=8,
                marker=MarkerStyle('*', joinstyle=join))
    # Show the marker edge for comparison with the join.
    axs[1].plot(col, 0, markersize=32, markeredgewidth=1,
                markerfacecolor='none', markeredgecolor='lightgrey',
                marker=MarkerStyle('*'))
    axs[1].annotate(join.name, (col, 0),
                    xytext=(20, -5), textcoords='offset points')

axs[2].set_title('Arbitrary transforms', fontsize=14)
for col, (size, rot) in enumerate(zip([2, 5, 7], [0, 45, 90])):
    t = Affine2D().rotate_deg(rot).scale(size)
    axs[2].plot(col, 0, marker=MarkerStyle('*', transform=t))

(Quellcode, 2x.png, png)

Three rows of markers, columns are blue, green, and purple. First row is y-shaped markers with different capstyles: butt, end is squared off at endpoint; projecting, end is squared off at short distance from endpoint; round, end is rounded. Second row is star-shaped markers with different join styles: miter, star points are sharp triangles; round, star points are rounded; bevel, star points are beveled. Last row shows stars rotated at different angles: small star rotated 0 degrees - top point vertical; medium star rotated 45 degrees - top point tilted right; large star rotated 90 degrees - top point tilted left.

Schriften und Text#

Schriftart-Fallback#

Es ist nun möglich, eine Liste von Schriftfamilien anzugeben, und Matplotlib wird versuchen, diese in der angegebenen Reihenfolge zu verwenden, um ein benötigtes Glyphe zu finden.

plt.rcParams["font.size"] = 20
fig = plt.figure(figsize=(4.75, 1.85))

text = "There are 几个汉字 in between!"
fig.text(0.05, 0.65, text, family=["Noto Sans CJK JP", "Noto Sans TC"])
fig.text(0.05, 0.45, text, family=["DejaVu Sans", "Noto Sans CJK JP", "Noto Sans TC"])

(Quellcode, 2x.png, png)

The phrase "There are 几个汉字 in between!" rendered in various fonts.

Demonstration von gemischtem englischem und chinesischem Text mit Schriftart-Fallback.

Dies funktioniert derzeit mit den Backends Agg (und allen GUI-Einbettungen), svg, pdf, ps und inline.

Liste verfügbarer Schriftartnamen#

Die Liste der verfügbaren Schriftarten ist nun leicht zugänglich. Um eine Liste der verfügbaren Schriftartnamen in Matplotlib zu erhalten, verwenden Sie

from matplotlib import font_manager
font_manager.get_font_names()

math_to_image verfügt nun über ein color-Schlüsselwortargument#

Um externe Bibliotheken, die auf der MathText-Rendering von Matplotlib basieren, zur Erzeugung von Gleichungsbildern einfach zu unterstützen, wurde der math_to_image ein color-Schlüsselwortargument hinzugefügt.

from matplotlib import mathtext
mathtext.math_to_image('$x^2$', 'filename.png', color='Maroon')

Verbesserungen an rcParams#

Festlegen der Schriftgröße und -stärke von Abbildungsbeschriftungen global und getrennt vom Titel#

Für Abbildungsbeschriftungen, Figure.supxlabel und Figure.supylabel, können die Größe und Stärke separat vom Abbildungstitel über rcParams["figure.labelsize"] (Standard: 'large') und rcParams["figure.labelweight"] (Standard: 'normal') eingestellt werden.

# Original (previously combined with below) rcParams:
plt.rcParams['figure.titlesize'] = 64
plt.rcParams['figure.titleweight'] = 'bold'

# New rcParams:
plt.rcParams['figure.labelsize'] = 32
plt.rcParams['figure.labelweight'] = 'bold'

fig, axs = plt.subplots(2, 2, layout='constrained')
for ax in axs.flat:
    ax.set(xlabel='xlabel', ylabel='ylabel')

fig.suptitle('suptitle')
fig.supxlabel('supxlabel')
fig.supylabel('supylabel')

(Quellcode, 2x.png, png)

A figure with 4 plots organised in 2 rows and 2 columns. The title of the figure is suptitle in bold and 64 points. The x axis is labelled supxlabel, and y axis is labelled subylabel. Both labels are 32 points and bold.

Beachten Sie, dass Sie bei Änderung von rcParams["figure.titlesize"] (Standard: 'large') oder rcParams["figure.titleweight"] (Standard: 'normal') nun auch die neu eingeführten Parameter ändern müssen, um ein Ergebnis zu erzielen, das mit dem bisherigen Verhalten konsistent ist.

Mathtext-Parsing kann global deaktiviert werden#

Die Einstellung rcParams["text.parse_math"] (Standard: True) kann verwendet werden, um das Parsen von Mathtext in allen Text-Objekten zu deaktivieren (insbesondere in der Methode Axes.text).

Doppelt zitierte Zeichenketten in matplotlibrc#

Sie können nun doppelte Anführungszeichen um Zeichenketten verwenden. Dies ermöglicht die Verwendung des Zeichens '#' in Zeichenketten. Ohne Anführungszeichen wird '#' als Kommentarbeginn interpretiert. Insbesondere können Sie nun Hex-Farben definieren

grid.color: "#b0b0b0"

3D-Achsen-Verbesserungen#

Standardisierte Ansichten für primäre Ebenen-Betrachtungswinkel#

Beim Betrachten eines 3D-Plots in einer der primären Betrachtungsebenen (d. h. senkrecht zu den XY-, XZ- oder YZ-Ebenen) werden die Achsen an einer Standardposition angezeigt. Weitere Informationen zu 3D-Ansichten finden Sie unter mplot3d Ansichtswinkel und Primäre 3D-Betrachtungsebenen.

Benutzerdefinierte Brennweite für 3D-Kamera#

Die 3D-Achsen können nun reale Kameras besser nachahmen, indem die Brennweite der virtuellen Kamera angegeben wird. Die Standardbrennweite von 1 entspricht einem Sichtfeld (FOV) von 90° und ist abwärtskompatibel mit bestehenden 3D-Plots. Eine erhöhte Brennweite zwischen 1 und unendlich "flacht" das Bild ab, während eine verringerte Brennweite zwischen 1 und 0 die Perspektive übertreibt und dem Bild mehr Tiefenwirkung verleiht.

Die Brennweite kann aus einem gewünschten FOV über die Gleichung berechnet werden

from mpl_toolkits.mplot3d import axes3d

X, Y, Z = axes3d.get_test_data(0.05)

fig, axs = plt.subplots(1, 3, figsize=(7, 4),
                        subplot_kw={'projection': '3d'})

for ax, focal_length in zip(axs, [0.2, 1, np.inf]):
    ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
    ax.set_proj_type('persp', focal_length=focal_length)
    ax.set_title(f"{focal_length=}")

(Quellcode, 2x.png, png)

A figure showing 3 basic 3D Wireframe plots. From left to right, the plots use focal length of 0.2, 1 and infinity. Focal length between 0.2 and 1 produce plot with depth while focal length between 1 and infinity show relatively flattened image.

3D-Plots erhielten einen 3. "Roll"-Betrachtungswinkel#

3D-Plots können nun mit einem zusätzlichen Rollwinkel aus jeder Ausrichtung betrachtet werden, der den Plot um die Blickachse dreht. Die interaktive Drehung mit der Maus steuert weiterhin nur die Elevation und den Azimut, was bedeutet, dass dieses Feature für Benutzer relevant ist, die komplexere Kammerawinkel programmatisch erstellen. Der Standard-Rollwinkel von 0 ist abwärtskompatibel mit bestehenden 3D-Plots.

from mpl_toolkits.mplot3d import axes3d

X, Y, Z = axes3d.get_test_data(0.05)

fig, ax = plt.subplots(subplot_kw={'projection': '3d'})

ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
ax.view_init(elev=0, azim=0, roll=30)
ax.set_title('elev=0, azim=0, roll=30')

(Quellcode, 2x.png, png)

View of a wireframe of a 3D contour that is somewhat a thickened s shape. Elevation and azimuth are 0 degrees so the shape is viewed straight on, but tilted because the roll is 30 degrees.

Gleiches Seitenverhältnis für 3D-Plots#

Benutzer können das Seitenverhältnis für die X-, Y- und Z-Achsen eines 3D-Plots auf 'equal', 'equalxy', 'equalxz' oder 'equalyz' statt auf den Standardwert 'auto' setzen.

from itertools import combinations, product

aspects = [
    ['auto', 'equal', '.'],
    ['equalxy', 'equalyz', 'equalxz'],
]
fig, axs = plt.subplot_mosaic(aspects, figsize=(7, 6),
                              subplot_kw={'projection': '3d'})

# Draw rectangular cuboid with side lengths [1, 1, 5]
r = [0, 1]
scale = np.array([1, 1, 5])
pts = combinations(np.array(list(product(r, r, r))), 2)
for start, end in pts:
    if np.sum(np.abs(start - end)) == r[1] - r[0]:
        for ax in axs.values():
            ax.plot3D(*zip(start*scale, end*scale), color='C0')

# Set the aspect ratios
for aspect, ax in axs.items():
    ax.set_box_aspect((3, 4, 5))
    ax.set_aspect(aspect)
    ax.set_title(f'set_aspect({aspect!r})')

(Quellcode, 2x.png, png)

Five plots, each showing a different aspect option for a rectangle that has height 4, depth 1, and width 1. auto: none of the dimensions have equal aspect, depth and width form a rectangular and height appears shrunken in proportion. equal: all the dimensions have equal aspect. equalxy: width and depth equal, height not so looks shrunken in proportion. equalyz: depth and height equal, width not so elongated. equalxz: width and height equal, depth not so elongated.

Verbesserungen an interaktiven Werkzeugen#

Drehung, Korrektur des Seitenverhältnisses und Zustand hinzufügen/entfernen#

Der RectangleSelector und der EllipseSelector können nun interaktiv zwischen -45° und 45° gedreht werden. Die Bereichsgrenzen werden derzeit durch die Implementierung bestimmt. Die Drehung wird durch Drücken der r-Taste (r ist die Standardtaste, die in state_modifier_keys auf 'rotate' abgebildet ist) oder durch Aufruf von selector.add_state('rotate') aktiviert oder deaktiviert.

Das Seitenverhältnis der Achsen kann nun berücksichtigt werden, wenn der "square"-Zustand verwendet wird. Dies wird aktiviert, indem beim Initialisieren des Selektors use_data_coordinates='True' angegeben wird.

Zusätzlich zur interaktiven Änderung des Selektorzustands mithilfe der in state_modifier_keys definierten Modifikatortasten kann der Selektorzustand nun programmatisch über die Methoden add_state und remove_state geändert werden.

from matplotlib.widgets import RectangleSelector

values = np.arange(0, 100)

fig = plt.figure()
ax = fig.add_subplot()
ax.plot(values, values)

selector = RectangleSelector(ax, print, interactive=True,
                             drag_from_anywhere=True,
                             use_data_coordinates=True)
selector.add_state('rotate')  # alternatively press 'r' key
# rotate the selector interactively

selector.remove_state('rotate')  # alternatively press 'r' key

selector.add_state('square')

MultiCursor unterstützt nun Achsen, die sich über mehrere Abbildungen erstrecken#

Zuvor funktionierte MultiCursor nur, wenn alle Ziel-Achsen zur selben Abbildung gehörten.

Als Konsequenz dieser Änderung ist das erste Argument des Konstruktors MultiCursor ungenutzt geworden (es war zuvor die gemeinsame Zeichenfläche aller Achsen, aber die Zeichenflächen werden nun direkt aus der Liste der Achsen abgeleitet).

Begrenzungsrahmen von PolygonSelector#

PolygonSelector verfügt nun über ein Argument draw_bounding_box, das beim Setzen auf True einen Begrenzungsrahmen um das Polygon zeichnet, sobald es vollständig ist. Der Begrenzungsrahmen kann in der Größe verändert und verschoben werden, was eine einfache Größenänderung der Punkte des Polygons ermöglicht.

Festlegen von PolygonSelector-Eckpunkten#

Die Eckpunkte eines PolygonSelector können nun programmatisch über die Eigenschaft PolygonSelector.verts gesetzt werden. Das Setzen der Eckpunkte auf diese Weise setzt den Selektor zurück und erstellt einen neuen vollständigen Selektor mit den angegebenen Eckpunkten.

SpanSelector-Widget kann nun an bestimmte Werte gesnappt werden#

Das SpanSelector-Widget kann nun an Werte gesnappt werden, die durch das Argument snap_values angegeben sind.

Mehr Symbolleistensymbole sind für dunkle Themes gestaltet#

Auf den macOS- und Tk-Backends werden Symbolleistensymbole nun invertiert, wenn ein dunkles Theme verwendet wird.

Plattformspezifische Änderungen#

Wx-Backend verwendet Standard-Symbolleiste#

Anstelle eines benutzerdefinierten Sizers wird die Symbolleiste auf Wx-Fenstern als Standard-Symbolleiste gesetzt.

Verbesserungen am macosx-Backend#

Modifikatortasten werden konsistenter behandelt#

Das macosx-Backend behandelt Modifikatortasten nun konsistenter mit anderen Backends. Weitere Informationen finden Sie in der Tabelle unter Ereignisverbindungen.

savefig.directory rcParam-Unterstützung#

Das macosx-Backend befolgt nun die Einstellung rcParams["savefig.directory"] (Standard: '~'). Wenn sie auf eine nicht leere Zeichenkette gesetzt wird, wird der Speicherdialog standardmäßig auf dieses Verzeichnis gesetzt und nachfolgende Speicherverzeichnisse werden bei Änderungen beibehalten.

figure.raise_window rcParam-Unterstützung#

Das macosx-Backend befolgt nun die Einstellung rcParams["figure.raise_window"] (Standard: True). Wenn sie auf False gesetzt ist, werden Abbildungsfenster bei Aktualisierung nicht mehr nach oben gebracht.

Unterstützung für Umschalten des Vollbildmodus#

Wie bei anderen Backends wird nun auch im macosx-Backend die Umschaltung der Vollbildansicht unterstützt. Standardmäßig kann diese Ansicht durch Drücken der Taste f umgeschaltet werden.

Verbesserte Animation und Blitting-Unterstützung#

Das macosx-Backend wurde verbessert, um Blitting, Animations-Frames mit neuen Künstlern zu beheben und unnötige Zeichenaufrufe zu reduzieren.

macOS-Anwendungssymbol auf Qt-Backend angewendet#

Bei Verwendung der Qt-basierten Backends auf macOS wird nun das Anwendungssymbol gesetzt, wie es auch auf anderen Backends/Plattformen geschieht.

Neue Mindest-macOS-Version#

Das macosx-Backend erfordert nun macOS >= 10.12.

Windows auf ARM-Unterstützung#

Es wurde eine vorläufige Unterstützung für das Ziel Windows auf ARM64 hinzugefügt. Diese Unterstützung erfordert FreeType 2.11 oder höher.

Es sind noch keine Binärpakete verfügbar, aber es kann aus dem Quellcode kompiliert werden.