Das axisartist-Toolkit#

Warnung

axisartist verwendet eine benutzerdefinierte Axes-Klasse (abgeleitet von Matplotlibs ursprünglicher Axes-Klasse). Als Nebeneffekt funktionieren einige Befehle (hauptsächlich tick-bezogene) nicht.

Das axisartist enthält eine benutzerdefinierte Axes-Klasse, die zur Unterstützung von gekrümmten Gittern (z. B. dem Weltkoordinatensystem in der Astronomie) gedacht ist. Im Gegensatz zu Matplotlibs ursprünglicher Axes-Klasse, die Axes.xaxis und Axes.yaxis zum Zeichnen von Ticks, Ticklines usw. verwendet, nutzt axisartist einen speziellen Künstler (AxisArtist), der Ticks, Ticklines usw. für gekrümmte Koordinatensysteme handhaben kann.

../../../_images/sphx_glr_demo_floating_axis_001.png

Da es spezielle Künstler verwendet, funktionieren einige Matplotlib-Befehle, die auf Axes.xaxis und Axes.yaxis angewendet werden, möglicherweise nicht.

axisartist#

Das Modul axisartist bietet eine benutzerdefinierte (und sehr experimentelle) Axes-Klasse, bei der jede Achse (links, rechts, oben und unten) einen separaten zugeordneten Künstler hat, der für das Zeichnen der Achsenlinie, Ticks, Ticklabels und Labels verantwortlich ist. Sie können auch Ihre eigene Achse erstellen, die durch eine feste Position im Achsenkoordinatensystem oder eine feste Position im Datenkoordinatensystem (d. h. die Achse schwimmt beim Ändern der Ansichtsgrenzen herum) verlaufen kann.

Die Achsenklasse hat standardmäßig ihre xaxis und yaxis unsichtbar und verfügt über 4 zusätzliche Künstler, die für das Zeichnen der 4 Achsenrahmen in "links", "rechts", "unten" und "oben" verantwortlich sind. Sie werden als ax.axis["left"], ax.axis["right"] usw. aufgerufen, d. h. ax.axis ist ein Wörterbuch, das Künstler enthält (beachten Sie, dass ax.axis immer noch eine aufrufbare Methode ist und sich wie eine ursprüngliche Axes.axis-Methode in Matplotlib verhält).

Zum Erstellen einer Achse,

import mpl_toolkits.axisartist as AA
fig = plt.figure()
fig.add_axes([0.1, 0.1, 0.8, 0.8], axes_class=AA.Axes)

oder zum Erstellen eines Subplots

fig.add_subplot(111, axes_class=AA.Axes)
# Given that 111 is the default, one can also do
fig.add_subplot(axes_class=AA.Axes)

Zum Beispiel können Sie die rechten und oberen Spines ausblenden mit

ax.axis["right"].set_visible(False)
ax.axis["top"].set_visible(False)
../../../_images/sphx_glr_simple_axisline3_001.png

Es ist auch möglich, eine horizontale Achse hinzuzufügen. Zum Beispiel könnten Sie eine horizontale Achse bei y=0 (in Datenkoordinaten) haben.

ax.axis["y=0"] = ax.new_floating_axis(nth_coord=0, value=0)
../../../_images/sphx_glr_simple_axisartist1_001.png

Oder eine feste Achse mit einem gewissen Versatz

# make new (right-side) yaxis, but with some offset
ax.axis["right2"] = ax.new_fixed_axis(loc="right", offset=(20, 0))

axisartist mit ParasiteAxes#

Die meisten Befehle im axes_grid1-Toolkit können ein Schlüsselwortargument axes_class entgegennehmen, und die Befehle erstellen eine Achse der angegebenen Klasse. Zum Beispiel, um einen Host-Subplot mit axisartist.Axes zu erstellen,

import mpl_toolkits.axisartist as AA
from mpl_toolkits.axes_grid1 import host_subplot

host = host_subplot(111, axes_class=AA.Axes)

Hier ist ein Beispiel, das ParasiteAxes verwendet.

../../../_images/sphx_glr_demo_parasite_axes2_001.png

Gekrümmtes Gitter#

Die Motivation hinter dem AxisArtist-Modul ist die Unterstützung eines gekrümmten Gitters und von Ticks.

../../../_images/sphx_glr_demo_curvelinear_grid_001.png

Schwebende Achsen#

AxisArtist unterstützt auch eine schwebende Achse, deren äußere Achsen als schwebende Achsen definiert sind.

../../../_images/sphx_glr_demo_floating_axes_001.png

axisartist-Namensraum#

Der axisartist-Namensraum enthält eine abgeleitete Axes-Implementierung. Der größte Unterschied besteht darin, dass die Künstler, die für das Zeichnen der Achsenlinie, der Ticks, der Ticklabels und der Achsenbeschriftungen verantwortlich sind, von der Matplotlib Axis-Klasse getrennt sind, was weit mehr ist als bei den Künstlern im ursprünglichen Matplotlib. Diese Änderung wurde stark motiviert, um gekrümmte Gitter zu unterstützen. Hier sind einige Dinge, die mpl_toolkits.axisartist.Axes von der ursprünglichen Axes von Matplotlib unterscheiden.

  • Achsensymbole (Achsenlinie (Spine), Ticks, Ticklabel und Achsenbeschriftungen) werden von einer AxisArtist-Instanz gezeichnet. Im Gegensatz zu Axis werden die linke, rechte, obere und untere Achse von separaten Künstlern gezeichnet. Und jeder von ihnen kann eine andere Tick-Position und andere Tick-Labels haben.

  • Gitterlinien werden von einer Gridlines-Instanz gezeichnet. Die Änderung wurde dadurch motiviert, dass in einem gekrümmten Koordinatensystem eine Gitterlinie möglicherweise keine Achsenlinien kreuzt (d. h. keine zugehörigen Ticks hat). In der ursprünglichen Axes-Klasse sind Gitterlinien an Ticks gebunden.

  • Ticklines können bei Bedarf gedreht werden (d. h. entlang der Gitterlinien)

Zusammenfassend lässt sich sagen, dass all diese Änderungen dazu dienten,

  • ein gekrümmtes Gitter zu unterstützen.

  • eine schwebende Achse zu unterstützen.

../../../_images/sphx_glr_demo_floating_axis_001.png

Die Klasse mpl_toolkits.axisartist.Axes definiert ein Attribut axis, das ein Wörterbuch von AxisArtist-Instanzen ist. Standardmäßig enthält das Wörterbuch 4 AxisArtist-Instanzen, die für das Zeichnen der linken, rechten, unteren und oberen Achse verantwortlich sind.

Die Attribute xaxis und yaxis sind weiterhin verfügbar, aber sie sind auf unsichtbar gesetzt. Da für die Darstellung der Achse separate Künstler verwendet werden, haben einige achsenbezogene Methoden in Matplotlib möglicherweise keine Auswirkungen. Zusätzlich zu den AxisArtist-Instanzen hat die mpl_toolkits.axisartist.Axes das Attribut gridlines (Gridlines), das offensichtlich Gitterlinien zeichnet.

Sowohl in AxisArtist als auch in Gridlines wird die Berechnung der Tick- und Gitterposition an eine Instanz der GridHelper-Klasse delegiert. Die Klasse mpl_toolkits.axisartist.Axes verwendet GridHelperRectlinear als Gitterhelfer. Die Klasse GridHelperRectlinear ist ein Wrapper um die xaxis und yaxis der ursprünglichen Axes von Matplotlib und war dazu gedacht, so zu funktionieren, wie die ursprünglichen Achsen von Matplotlib funktionieren. Zum Beispiel sollten Tick-Positionsänderungen mit der set_ticks-Methode usw. wie erwartet funktionieren. Aber Änderungen an den Künstlereigenschaften (z. B. Farbe) werden im Allgemeinen nicht funktionieren, obwohl einige Anstrengungen unternommen wurden, damit einige häufig geänderte Attribute (Farbe usw.) berücksichtigt werden.

AxisArtist#

AxisArtist kann als Container-Künstler mit folgenden Attributen betrachtet werden, die Ticks, Labels usw. zeichnen werden:

  • line

  • major_ticks, major_ticklabels

  • minor_ticks, minor_ticklabels

  • offsetText

  • label

line#

Abgeleitet von der Line2D-Klasse. Verantwortlich für das Zeichnen einer Spines(?) Linie.

major_ticks, minor_ticks#

Abgeleitet von der Line2D-Klasse. Beachten Sie, dass Ticks Marker sind.

major_ticklabels, minor_ticklabels#

Abgeleitet von Text. Beachten Sie, dass es sich nicht um eine Liste von Text-Künstlern handelt, sondern um einen einzigen Künstler (ähnlich einer Sammlung).

axislabel#

Abgeleitet von Text.

Standard-AxisArtists#

Standardmäßig sind folgende Achsenkünstler definiert.

ax.axis["left"], ax.axis["bottom"], ax.axis["right"], ax.axis["top"]

Die Ticklabels und Achsenbeschriftungen der oberen und rechten Achse sind auf unsichtbar gesetzt.

Zum Beispiel, wenn Sie die Farbeigenschaften der Haupt-Ticklabels der unteren x-Achse ändern möchten

ax.axis["bottom"].major_ticklabels.set_color("b")

Ähnlich, um Ticklabels unsichtbar zu machen

ax.axis["bottom"].major_ticklabels.set_visible(False)

AxisArtist bietet eine Hilfsmethode zur Steuerung der Sichtbarkeit von Ticks, Ticklabels und Beschriftungen. Um Ticklabels unsichtbar zu machen,

ax.axis["bottom"].toggle(ticklabels=False)

Um alle Ticks, Ticklabels und (Achsen-)Beschriftungen unsichtbar zu machen

ax.axis["bottom"].toggle(all=False)

Um alle außer den Ticks ein- und auszuschalten

ax.axis["bottom"].toggle(all=False, ticks=True)

Um alle außer den (Achsen-)Beschriftungen ein- und auszuschalten

ax.axis["bottom"].toggle(all=True, label=False)

Die __getitem__-Methode von ax.axis kann mehrere Achsennamen entgegennehmen. Zum Beispiel, um die Ticklabels der Achsen "oben" und "rechts" einzuschalten,

ax.axis["top", "right"].toggle(ticklabels=True)

Beachten Sie, dass ax.axis["top", "right"] ein einfaches Proxy-Objekt zurückgibt, das den obigen Code in etwas wie das Folgende übersetzt:

for n in ["top", "right"]:
    ax.axis[n].toggle(ticklabels=True)

Daher werden alle Rückgabewerte in der for-Schleife ignoriert. Und Sie sollten es nicht mehr als eine einfache Methode verwenden.

Wie bei der Listenindizierung bedeutet ":" alle Elemente, d. h.

ax.axis[:].major_ticks.set_color("r")

ändert die Tickfarbe in allen Achsen.

Anleitung#

  1. Ändern von Tick-Positionen und -Beschriftungen.

    Dasselbe wie bei den ursprünglichen Achsen von Matplotlib.

    ax.set_xticks([1, 2, 3])
    
  2. Ändern von Achseneigenschaften wie Farbe usw.

    Ändern Sie die Eigenschaften der entsprechenden Künstler. Zum Beispiel, um die Farbe der Ticklabels zu ändern

    ax.axis["left"].major_ticklabels.set_color("r")
    
  3. Ändern der Attribute mehrerer Achsen

    ax.axis["left", "bottom"].major_ticklabels.set_color("r")
    

    oder um die Attribute aller Achsen zu ändern

    ax.axis[:].major_ticklabels.set_color("r")
    
  4. Um die Tickgröße (Länge) zu ändern, müssen Sie die Methode axis.major_ticks.set_ticksize verwenden. Um die Richtung der Ticks zu ändern (Ticks sind standardmäßig in die entgegengesetzte Richtung der Ticklabels), verwenden Sie die Methode axis.major_ticks.set_tick_out.

    Um den Abstand zwischen Ticks und Ticklabels zu ändern, verwenden Sie die Methode axis.major_ticklabels.set_pad.

    Um den Abstand zwischen Ticklabels und Achsenbeschriftung zu ändern, verwenden Sie die Methode axis.label.set_pad.

Rotation und Ausrichtung von TickLabels#

Dies ist auch ganz anders als bei Standard-Matplotlib und kann verwirrend sein. Wenn Sie Ticklabels drehen möchten, sollten Sie zuerst die Methode "set_axis_direction" in Betracht ziehen.

ax1.axis["left"].major_ticklabels.set_axis_direction("top")
ax1.axis["right"].label.set_axis_direction("left")
../../../_images/sphx_glr_simple_axis_direction01_001.png

Der Parameter für set_axis_direction ist einer von ["left", "right", "bottom", "top"].

Sie müssen einige grundlegende Konzepte von Richtungen verstehen.

  • Es gibt eine Referenzrichtung, die als die Richtung der Achsenlinie bei steigender Koordinate definiert ist. Zum Beispiel ist die Referenzrichtung der linken x-Achse von unten nach oben.

    Die Richtung, der Textwinkel und die Ausrichtungen der Ticks, Ticklabels und Achsenbeschriftungen werden relativ zur Referenzrichtung bestimmt.

  • label_direction und ticklabel_direction sind entweder die rechte Seite (+) der Referenzrichtung oder die linke Seite (-).

  • Ticks werden standardmäßig in die entgegengesetzte Richtung der Ticklabels gezeichnet.

  • Die Textrotation von Ticklabels und Beschriftungen wird in Bezug auf ticklabel_direction bzw. label_direction bestimmt. Die Rotation von Ticklabels und Beschriftungen ist verankert.

../../../_images/sphx_glr_axis_direction_001.png

Andererseits gibt es das Konzept der "axis_direction". Dies ist eine Standardeinstellung der obigen Eigenschaften für jede Achse: "unten", "links", "oben" und "rechts".

Standardwerte der axislabel-Eigenschaft#

Referenzrichtung

Label-Richtung

Label-Rotation

Horizontale Ausrichtung

Vertikale Ausrichtung

links

'-'

180

rechts

Mitte

unten

'+'

0

Mitte

oben

rechts

'+'

0

rechts

Mitte

oben

'-'

180

Mitte

unten

Standardwerte der ticklabel-Eigenschaft#

Referenzrichtung

Label-Richtung

Label-Rotation

Horizontale Ausrichtung

Vertikale Ausrichtung

links

'-'

90

rechts

Mitte

unten

'+'

0

Mitte

Basislinie

rechts

'+'

-90

rechts

Mitte

oben

'-'

180

Mitte

Basislinie

Und 'set_axis_direction("top")' bedeutet, die Textrotation usw. für Einstellungen anzupassen, die für die Achse "oben" geeignet sind. Das Konzept der Achsenrichtung wird bei gekrümmten Achsen deutlicher.

../../../_images/sphx_glr_demo_axis_direction_001.png

Die axis_direction kann auf der Ebene von AxisArtist oder auf der Ebene ihrer Kind-Künstler, d. h. Ticks, Ticklabels und Achsenbeschriftung, angepasst werden.

ax1.axis["left"].set_axis_direction("top")

ändert die axis_direction aller zugehörigen Künstler der Achse "links", während

ax1.axis["left"].major_ticklabels.set_axis_direction("top")

ändert nur die axis_direction der major_ticklabels. Beachten Sie, dass set_axis_direction auf der Ebene von AxisArtist die ticklabel_direction und label_direction ändert, während die Änderung der axis_direction von Ticks, Ticklabels und Achsenbeschriftung diese nicht beeinflusst.

Wenn Sie Ticks nach außen und Ticklabels innerhalb der Achsen haben möchten, verwenden Sie die Methode invert_ticklabel_direction.

ax.axis[:].invert_ticklabel_direction()

Eine verwandte Methode ist "set_tick_out". Sie macht die Ticks nach außen (tatsächlich macht sie Ticks in die entgegengesetzte Richtung der Standardrichtung).

ax.axis[:].major_ticks.set_tick_out(True)
../../../_images/sphx_glr_simple_axis_direction03_001.png

Zusammenfassend also:

  • Methoden von AxisArtist

    • set_axis_direction: "left", "right", "bottom" oder "top"

    • set_ticklabel_direction: "+" oder "-"

    • set_axislabel_direction: "+" oder "-"

    • invert_ticklabel_direction

  • Methoden von Ticks (major_ticks und minor_ticks)

    • set_tick_out: True oder False

    • set_ticksize: Größe in Punkten

  • Methoden von TickLabels (major_ticklabels und minor_ticklabels)

    • set_axis_direction: "left", "right", "bottom" oder "top"

    • set_rotation: Winkel relativ zur Referenzrichtung

    • set_ha und set_va: siehe unten

  • Methoden von AxisLabels (label)

    • set_axis_direction: "left", "right", "bottom" oder "top"

    • set_rotation: Winkel relativ zur Referenzrichtung

    • set_ha und set_va

Anpassen der Ausrichtung von Ticklabels#

Die Ausrichtung von Ticklabels wird speziell behandelt. Siehe unten

../../../_images/sphx_glr_demo_ticklabel_alignment_001.png

Anpassen des Abstands#

Um den Abstand zwischen Ticks und Ticklabels zu ändern

ax.axis["left"].major_ticklabels.set_pad(10)

Oder Ticklabels und Achsenbeschriftung

ax.axis["left"].label.set_pad(10)
../../../_images/sphx_glr_simple_axis_pad_001.png

GridHelper#

Um tatsächlich ein gekrümmtes Koordinatensystem zu definieren, müssen Sie Ihren eigenen Grid-Helfer verwenden. Eine verallgemeinerte Version der Grid-Helferklasse wird bereitgestellt und sollte in den meisten Fällen ausreichend sein. Ein Benutzer kann zwei Funktionen bereitstellen, die eine Transformation (und ihre Inverse) vom gekrümmten Koordinatensystem in das (rechtwinklige) Bildkoordinatensystem definieren. Beachten Sie, dass zwar Ticks und Gitter für gekrümmte Koordinaten gezeichnet werden, die Datentransformation der Achse selbst (ax.transData) immer noch rechtwinklig (Bild-)Koordinaten sind.

from mpl_toolkits.axisartist.grid_helper_curvelinear \
     import GridHelperCurveLinear
from mpl_toolkits.axisartist import Axes

# from curved coordinate to rectlinear coordinate.
def tr(x, y):
    x, y = np.asarray(x), np.asarray(y)
    return x, y-x

# from rectlinear coordinate to curved coordinate.
def inv_tr(x, y):
    x, y = np.asarray(x), np.asarray(y)
    return x, y+x

grid_helper = GridHelperCurveLinear((tr, inv_tr))

fig.add_subplot(axes_class=Axes, grid_helper=grid_helper)

Sie können stattdessen die Transform-Instanz von Matplotlib verwenden (aber eine inverse Transformation muss definiert sein). Oftmals hat der Koordinatenbereich in einem gekrümmten Koordinatensystem einen begrenzten Bereich oder kann Zyklen aufweisen. In solchen Fällen ist eine stärker angepasste Version des Grid-Helfers erforderlich.

import mpl_toolkits.axisartist.angle_helper as angle_helper

# PolarAxes.PolarTransform takes radian. However, we want our coordinate
# system in degree
tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform()

# extreme finder: find a range of coordinate.
# 20, 20: number of sampling points along x, y direction
# The first coordinate (longitude, but theta in polar)
#   has a cycle of 360 degree.
# The second coordinate (latitude, but radius in polar)  has a minimum of 0
extreme_finder = angle_helper.ExtremeFinderCycle(20, 20,
                                                 lon_cycle=360,
                                                 lat_cycle=None,
                                                 lon_minmax=None,
                                                 lat_minmax=(0, np.inf),
                                                 )

# Find a grid values appropriate for the coordinate (degree,
# minute, second). The argument is a approximate number of grids.
grid_locator1 = angle_helper.LocatorDMS(12)

# And also uses an appropriate formatter.  Note that the acceptable Locator
# and Formatter classes are different than that of Matplotlib's, and you
# cannot directly use Matplotlib's Locator and Formatter here (but may be
# possible in the future).
tick_formatter1 = angle_helper.FormatterDMS()

grid_helper = GridHelperCurveLinear(tr,
                                    extreme_finder=extreme_finder,
                                    grid_locator1=grid_locator1,
                                    tick_formatter1=tick_formatter1
                                    )

Auch hier ist die transData der Achse immer noch ein rechtwinkliges Koordinatensystem (Bildkoordinaten). Sie können manuell zwischen den beiden Koordinaten konvertieren oder Sie können Parasite Axes zur Bequemlichkeit verwenden.

ax1 = SubplotHost(fig, 1, 2, 2, grid_helper=grid_helper)

# A parasite axes with given transform
ax2 = ax1.get_aux_axes(tr, "equal")
# note that ax2.transData == tr + ax1.transData
# Anything you draw in ax2 will match the ticks and grids of ax1.
../../../_images/sphx_glr_demo_curvelinear_grid_001.png

FloatingAxis#

Eine schwebende Achse ist eine Achse, bei der eine ihrer Datenkoordinaten fixiert ist, d. h. ihre Position ist nicht in Achsenkoordinaten fixiert, sondern ändert sich, wenn sich die Datenlimits der Achse ändern. Eine schwebende Achse kann mit der Methode new_floating_axis erstellt werden. Es liegt jedoch in Ihrer Verantwortung, dass die resultierende AxisArtist ordnungsgemäß zur Achse hinzugefügt wird. Ein empfohlener Weg ist, sie als Element des Achsenattributs der Achsen hinzuzufügen.

# floating axis whose first (index starts from 0) coordinate
# (theta) is fixed at 60

ax1.axis["lat"] = axis = ax1.new_floating_axis(0, 60)
axis.label.set_text(r"$\theta = 60^{\circ}$")
axis.label.set_visible(True)

Siehe das erste Beispiel auf dieser Seite.

Aktuelle Einschränkungen und TODOs#

Der Code bedarf weiterer Verfeinerung. Hier ist eine unvollständige Liste von Problemen und TODOs:

  • Keine einfache Möglichkeit, benutzerdefinierte Tick-Positionen zu unterstützen (für gekrümmte Gitter). Eine neue Locator-Klasse muss erstellt werden.

  • FloatingAxis kann Koordinatenlimits haben, z. B. eine schwebende Achse bei x = 0, aber y erstreckt sich nur von 0 bis 1.

  • Die Position der Achsenbeschriftung von FloatingAxis muss optional als Koordinatenwert angegeben werden können. z. B. eine schwebende Achse bei x=0 mit Beschriftung bei y=1