web-dev-qa-db-fra.com

tracés matplotlib savefig () différents de show ()

Lorsque j'utilise show() pour tracer les graphiques dans X, les graphiques ont une très bonne apparence. Cependant, lorsque je commence à utiliser savefig() pour générer une grande quantité de graphiques, la police, les lignes, les polygones générés par la savefig() générée sont tous plus petits que le graphique généré par la show() générée. . Mon environnement est Ubuntu et le backend de show() est Qt4Agg. Comment puis-je rendre le tracé show() et le tracé savefig() cohérents?

48
leon

savefig spécifie le DPI de la figure sauvegardée (la valeur par défaut est 100 si elle n'est pas spécifiée dans votre fichier .matplotlibrc, jetez un coup d'œil au dpi kwarg à savefig ). Il ne l’hérite pas du DPI de la figure originale.

Le DPI affecte la taille relative du texte et la largeur du trait sur les lignes, etc. Si vous voulez que les choses aient l’air identiques, passez fig.dpi à fig.savefig.

Par exemple.

import matplotlib.pyplot as plt

fig = plt.figure()
plt.plot(range(10))
fig.savefig('temp.png', dpi=fig.dpi)
56
Joe Kington

Vous restiturez vos tracés matplotlib vers différents périphériques (par exemple, à l'écran via Quartz ou vers un fichier via PDF à l'aide de différentes fonctions ( plot versus savefig) dont les paramètres sont presque identiques , pourtant les valeurs par défaut pour ces paramètres ne sont pas les mêmes pour les deux fonctions.

En d'autres termes, les savefig paramètres par défaut sont différents de les paramètres par défaut display paramètres.

Les aligner est simple si vous le faites dans le fichier de configuration matplotlib. Le fichier modèle est inclus avec le paquet source et est nommé matplotlibrc.template. Si vous n'en avez pas créé lors de l'installation de matplotlib, vous pouvez obtenir ce modèle à partir de la source matplotlib, ou à partir du site site Web de matplotlib .

Une fois que vous avez personnalisé ce fichier comme vous le souhaitez, renommez-le en matplotlibrc (sans extension) et enregistrez-le dans le répertoire . matplotlib (notez le préfixe '.') qui devrait se trouver dans votre répertoire personnel.

Les paramètres de configuration pour enregistrement des chiffres commencent aux environs de ligne 314 dans le matplotlibrc.template (première ligne précédant cette section est: ### SAUVEGARDE DES FIGURES).

En particulier, vous voudrez regarder ceux-ci:

savefig.dpi       : 100         # figure dots per inch
savefig.facecolor : white       # figure facecolor when saving
savefig.edgecolor : white       # figure edgecolor when saving
savefig.extension : auto        # what extension to use for savefig('foo'), or 'auto'

En dessous de ces lignes figurent les paramètres du type de police et divers paramètres spécifiques au format d'image.

Ces mêmes paramètres pour l'affichage, c'est-à-dire PLT.show (), commence à environ ligne 277 a dans le matplotlibrc.template (cette section est précédée de la ligne: ### FIGURE):

figure.figsize   : 8, 6          
figure.dpi       : 80            
figure.facecolor : 0.75       
figure.edgecolor : white     

Comme vous pouvez le constater en comparant les valeurs de ces deux blocs de paramètres, les paramètres par défaut pour le même attribut de figure sont différent pour savefig versus afficher (afficher).

27
doug

Vieille question, mais apparemment, Google l'aime et j'ai donc pensé mettre une réponse ici après quelques recherches sur ce problème.

Si vous créez une figure à partir de zéro, vous pouvez lui donner une option de taille lors de la création:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(3, 6))

plt.plot(range(10)) #plot example
plt.show() #for control

fig.savefig('temp.png', dpi=fig.dpi)

figsize (width, height) ajuste la dimension absolue de votre tracé et aide à vous assurer que les deux tracés se ressemblent.

Comme indiqué dans une autre réponse, l'option dpi affecte la taille relative du texte et la largeur du trait sur les lignes, etc. L'utilisation de l'option dpi = fig.dpi permet de s'assurer que taille relative de ceux-ci sont les mêmes pour show () et savefig ().

Alternativement, la taille de la figure peut être modifiée après la création avec:

fig.set_size_inches(3, 6, forward=True)

forward permet de changer la taille à la volée.

Si vous rencontrez des problèmes avec des bordures trop grandes dans l'image créée, vous pouvez les ajuster avec:

plt.tight_layout()
#or:
plt.tight_layout(pad=2)

ou:

fig.savefig('temp.png', dpi=fig.dpi, bbox_inches='tight')
#or:
fig.savefig('temp.png', dpi=fig.dpi, bbox_inches='tight', pad_inches=0.5)

La première option minimise simplement la mise en page et les bordures et la seconde option permet d'ajuster un peu manuellement les bordures. Ces conseils m'ont au moins aidé à résoudre mon problème de différentes images savefig () et show ().

8
brium-brium

J'ai corrigé cela dans ma source matplotlib, mais ce n'est pas une jolie solution. Toutefois, si vous êtes, comme moi, très attentif au graphisme, cela en vaut la peine.

Le problème semble être dans le backend backend; ils obtiennent chacun les valeurs correctes pour la largeur de trait, la taille de la police, etc., mais ils sont légèrement plus grands lorsqu'ils sont rendus sous la forme d'un fichier PDF ou PNG que lorsqu'ils sont rendus avec show ().

J'ai ajouté quelques lignes au source pour la génération PNG, dans le fichier matplotlib/backends/backend_agg.py. Vous pouvez effectuer des modifications similaires pour chaque serveur que vous utilisez ou trouver un moyen d’apporter des modifications plus astucieuses au même endroit;)

Ajouté à mon fichier matplotlib/backends/backend_agg.py:

    # The top of the file, added lines 42 - 44
42  # @warning: CHANGED FROM SOURCE to draw thinner lines
43  PATH_SCALAR = .8
44  FONT_SCALAR = .95

    # In the draw_markers method, added lines 90 - 91
89  def draw_markers(self, *kl, **kw):
90      # @warning: CHANGED FROM SOURCE to draw thinner lines
91      kl[0].set_linewidth(kl[0].get_linewidth()*PATH_SCALAR)
92      return self._renderer.draw_markers(*kl, **kw)

    # At the bottom of the draw_path method, added lines 131 - 132:
130 else:
131     # @warning: CHANGED FROM SOURCE to draw thinner lines
132     gc.set_linewidth(gc.get_linewidth()*PATH_SCALAR)
133     self._renderer.draw_path(gc, path, transform, rgbFace)

    # At the bottom of the _get_agg_font method, added line 242 and the *FONT_SCALAR
241     font.clear()
242     # @warning: CHANGED FROM SOURCE to draw thinner lines
243     size = prop.get_size_in_points()*FONT_SCALAR
244     font.set_size(size, self.dpi)

Donc, cela répond à mes besoins pour le moment, mais, selon ce que vous faites, vous pouvez implémenter des modifications similaires dans d'autres méthodes. Ou trouver une meilleure façon de faire la même chose sans autant de changements de ligne!

Mise à jour: Après avoir publié un problème dans le projet matplotlib de Github, j'ai été capable de localiser la source de mon problème: j'avais modifié le paramètre figure.dpi dans le fichier matplotlibrc. Si cette valeur est différente de la valeur par défaut, mes images savefig () sont différentes, même si je règle le dpi de savefig sur la même chose que dpi. Ainsi, au lieu de changer la source comme ci-dessus, j'ai simplement conservé le paramètre figure.dpi comme valeur par défaut de 80 et j'ai pu générer des images avec savefig () qui ressemblait à des images de show ().

Leon, avez-vous aussi changé ce réglage?

4
Karmel