web-dev-qa-db-fra.com

Classe d'axes - définit explicitement la taille (largeur/hauteur) des axes en unités données

Je veux créer une figure à l'aide de matplotlib où je peux spécifier explicitement la taille des axes, c'est-à-dire que je veux définir la largeur et la hauteur de la bbox d'axes.

J'ai regardé partout et je ne peux pas trouver de solution à cela. Ce que je trouve généralement, c’est comment ajuster la taille de la figure complète (y compris les graduations et les libellés), en utilisant par exemple fig, ax = plt.subplots(figsize=(w, h))

C’est très important pour moi car je veux avoir une échelle 1: 1 des axes, c’est-à-dire qu’une unité sur papier correspond à 1 unité dans la réalité. Par exemple, si xrange est compris entre 0 et 10 avec un tick principal = 1 et que l’axe des x est 10cm, alors un tick principal = 1cm. Je vais enregistrer cette figure au format pdf pour l'importer dans un document latex.

Cette question a soulevé un sujet similaire mais la réponse ne résout pas mon problème (en utilisant le code plt.gca().set_aspect('equal', adjustable='box'))

De cet autre question je vois qu'il est possible d’obtenir la taille des axes, mais pas comment les modifier explicitement.

Toutes les idées sur la façon dont je peux définir la taille de la boîte des axes et pas seulement la taille de la figure. La taille de la figure doit s'adapter à la taille des axes.

Merci!

Pour ceux qui sont familiers avec pgfplots in latex, il aimerait avoir quelque chose de similaire à l’option scale only axis (voir ici par exemple).

3
Gabriel

La taille des axes est déterminée par la taille de la figure et les espacements de la figure, qui peuvent être définis à l'aide de figure.subplots_adjust() . En sens inverse, cela signifie que vous pouvez définir la taille des axes en définissant la taille de la figure en tenant compte des espacements de la figure:

import matplotlib.pyplot as plt

def set_size(w,h, ax=None):
    """ w, h: width, height in inches """
    if not ax: ax=plt.gca()
    l = ax.figure.subplotpars.left
    r = ax.figure.subplotpars.right
    t = ax.figure.subplotpars.top
    b = ax.figure.subplotpars.bottom
    figw = float(w)/(r-l)
    figh = float(h)/(t-b)
    ax.figure.set_size_inches(figw, figh)

fig, ax=plt.subplots()

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

set_size(5,5)

plt.show()

Il semble que Matplotlib dispose de nouvelles classes d’aide permettant de définir des axes de taille fixe Demo axes de taille fixe

2
Max

J'ai trouvé que la réponse Importance of BeEnRests qui modifie la taille de la figure pour ajuster la taille des axes fournit des résultats incohérents avec les paramètres spécifiques de matplotlib que j'utilise pour produire des tracés prêts pour la publication. De légères erreurs étaient présentes dans la taille de la figure finale et je n’ai pas pu trouver un moyen de résoudre le problème avec son approche. Pour la plupart des cas d'utilisation, je pense que ce n'est pas un problème, cependant les erreurs étaient notables lors de la combinaison de plusieurs pdf pour la publication.

Au lieu de développer un exemple de travail minimal pour trouver le vrai problème que j'ai avec l'approche de redimensionnement de la figure, j'ai plutôt trouvé un moyen de contourner le problème qui utilise la taille des axes fixes en utilisant la classe de diviseur.

from mpl_toolkits.axes_grid1 import Divider, Size
def fix_axes_size_incm(axew, axeh):
    axew = axew/2.54
    axeh = axeh/2.54

    #lets use the tight layout function to get a good padding size for our axes labels.
    fig = plt.gcf()
    ax = plt.gca()
    fig.tight_layout()
    #obtain the current ratio values for padding and fix size
    oldw, oldh = fig.get_size_inches()
    l = ax.figure.subplotpars.left
    r = ax.figure.subplotpars.right
    t = ax.figure.subplotpars.top
    b = ax.figure.subplotpars.bottom

    #work out what the new  ratio values for padding are, and the new fig size.
    neww = axew+oldw*(1-r+l)
    newh = axeh+oldh*(1-t+b)
    newr = r*oldw/neww
    newl = l*oldw/neww
    newt = t*oldh/newh
    newb = b*oldh/newh

    #right(top) padding, fixed axes size, left(bottom) pading
    hori = [Size.Scaled(newr), Size.Fixed(axew), Size.Scaled(newl)]
    vert = [Size.Scaled(newt), Size.Fixed(axeh), Size.Scaled(newb)]

    divider = Divider(fig, (0.0, 0.0, 1., 1.), hori, vert, aspect=False)
    # the width and height of the rectangle is ignored.

    ax.set_axes_locator(divider.new_locator(nx=1, ny=1))

    #we need to resize the figure now, as we have may have made our axes bigger than in.
    fig.set_size_inches(neww,newh)

Les choses à noter:

  • Une fois que vous appelez set_axes_locator() sur une instance d'axe, vous désactivez la fonction tight_layout().
  • La taille de la figure d'origine que vous choisissez ne sera pas pertinente, et la taille finale de la figure est déterminée par la taille des axes que vous choisissez et par la taille des étiquettes/étiquettes de ticks/ticks sortants.
  • Cette approche ne fonctionne pas avec les barres d'échelle de couleur.
  • Ceci est mon tout premier poste de débordement de pile.
0
BongaCodeBuddy