matplotlib savefig () zeichnet sich von show () ab

72

Wenn ich show()die Grafiken einzeichne X, sehen die Grafiken sehr gut aus. Wenn ich jedoch anfange, savefig()eine große Anzahl von Diagrammen zu savefig()generieren, sehen Schriftart, Linien und Polygone der show()generierten Diagramme kleiner aus als das generierte Diagramm. Meine Umgebung ist Ubuntu und das Backend für show()ist Qt4Agg. Wie kann ich die show()Handlung erstellen und die savefig()Handlung sieht konsistent aus?

Leon
quelle

Antworten:

77

savefigGibt die DPI für die gespeicherte Zahl an (Die Standardeinstellung ist 100, wenn sie nicht in Ihrer .matplotlibrc angegeben ist. Schauen Sie sich das dpikwarg ansavefig ). Es erbt es nicht von der DPI der Originalfigur.

Die DPI wirkt sich auf die relative Größe des Texts und die Breite des Strichs auf Linien usw. aus. Wenn Sie möchten, dass die Dinge identisch aussehen, gehen Sie fig.dpizu fig.savefig.

Z.B

import matplotlib.pyplot as plt

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

Sie rendern Ihre matplotlib- Diagramme auf verschiedenen Geräten (z. B. über Quarz auf dem Bildschirm oder per PDF in eine Datei mit verschiedenen Funktionen ( Diagramm gegenüber savefig ), deren Parameter nahezu identisch sind, deren Standardwerte für diese Parameter jedoch nicht identisch sind beide Funktionen.

Anders ausgedrückt, die savefig sind Standard - Parameter unterscheiden sich von den Standardanzeigeparameter.

Das Ausrichten ist einfach, wenn Sie dies in der Konfigurationsdatei matplotlib tun . Die Vorlagendatei ist im Quellpaket enthalten und heißt matplotlibrc.template . Wenn Sie bei der Installation von matplotlib keine erstellt haben, können Sie diese Vorlage von der matplotlib- Quelle oder von der matplotlib-Website herunterladen .

Wenn Sie diese Datei nach Ihren Wünschen angepasst haben, benennen Sie sie in matplotlibrc (keine Erweiterung) um und speichern Sie sie im Verzeichnis .matplotlib (beachten Sie das führende '.'), Das sich in Ihrem Home-Verzeichnis befinden sollte.

Die Konfigurationsparameter zum Speichern von Zahlen beginnen ungefähr in Zeile 314 in der mitgelieferten matplotlibrc.template (erste Zeile vor diesem Abschnitt lautet: ### SAVING FIGURES).

Insbesondere sollten Sie sich diese ansehen:

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'

Unter diesen Zeilen befinden sich die Einstellungen für den Schrifttyp und verschiedene bildformatspezifische Parameter.

Dieselben Parameter für die Anzeige , dh PLT.show () , beginnen ungefähr in Zeile 277a in der matplotlibrc.template (diesem Abschnitt geht die Zeile voraus: ### ABBILDUNG):

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

Wie Sie durch einen Vergleich der Werte dieser beiden Blöcke von Parametern, die Standardeinstellungen für die gleiche Zahl Attribut sind sehen anders für savefig gegenüber Display ( an ).

Doug
quelle
Das Ändern dieser Konfiguration stimmt immer noch nicht mit der Schriftgröße und Linienbreite überein, die zwischen show () und savefig () übereinstimmen. Obwohl ich hinzufügen möchte, dass das manuelle Speichern des Diagramms aus dem Qt-Widget in Ordnung ist. Nur die Zeit es nicht in Ordnung ist , ist savefig mit ()
leon
21

Alte Frage, aber anscheinend gefällt es Google, also dachte ich, ich hätte hier nach einigen Recherchen zu diesem Problem eine Antwort gegeben.

Wenn Sie eine Figur von Grund auf neu erstellen, können Sie ihr beim Erstellen eine Größenoption geben:

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 (Breite, Höhe) passt die absolute Abmessung Ihres Diagramms an und stellt sicher, dass beide Diagramme gleich aussehen.

Wie in einer anderen Antwort angegeben, wirkt sich die Option dpi auf die relative Größe des Texts und die Breite des Strichs auf Linien usw. aus. Mit der Option dpi = fig.dpi wird sichergestellt, dass die relative Größe sowohl für show () als auch für savefig gleich ist () .

Alternativ kann die Figurengröße nach der Erstellung geändert werden mit:

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

Vorwärts ermöglicht das Ändern der Größe im laufenden Betrieb.

Wenn Sie Probleme mit zu großen Rändern im erstellten Bild haben, können Sie diese entweder anpassen mit:

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

oder:

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)

Die erste Option minimiert nur das Layout und die Ränder und die zweite Option ermöglicht das manuelle Anpassen der Ränder. Diese Tipps haben mir zumindest geholfen, mein Problem mit verschiedenen Bildern von savefig () und show () zu lösen .

Brium-Brium
quelle
4

Ich habe dies in meiner matplotlib-Quelle behoben, aber es ist keine schöne Lösung. Wenn Sie jedoch wie ich sehr genau wissen, wie das Diagramm aussieht, lohnt es sich.

Das Problem scheint in den Rendering-Backends zu liegen. Sie erhalten jeweils die richtigen Werte für Linienbreite, Schriftgröße usw., die jedoch beim Rendern als PDF oder PNG etwas größer sind als beim Rendern mit show ().

Ich habe der Quelle für die PNG-Generierung in der Datei matplotlib / backends / backend_agg.py einige Zeilen hinzugefügt. Sie können ähnliche Änderungen für jedes Backend vornehmen, das Sie verwenden, oder einen Weg finden, um eine cleverere Änderung an einem einzelnen Ort vorzunehmen;)

Zu meiner matplotlib / backends / backend_agg.py Datei hinzugefügt:

    # 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)

Das entspricht vorerst meinen Anforderungen, aber je nachdem, was Sie tun, möchten Sie möglicherweise ähnliche Änderungen in anderen Methoden implementieren. Oder finden Sie einen besseren Weg, um dasselbe ohne so viele Zeilenwechsel zu tun!

Aktualisieren: Nachdem ich ein Problem im matplotlib-Projekt bei Github veröffentlicht hatte, konnte ich die Ursache meines Problems ermitteln: Ich hatte die Einstellung figure.dpi in der matplotlibrc-Datei geändert. Wenn dieser Wert vom Standardwert abweicht, werden meine savefig () - Bilder anders ausgegeben, auch wenn ich die savefig dpi so festgelegt habe, dass sie mit der Abbildung dpi übereinstimmt. Anstatt die Quelle wie oben zu ändern, habe ich einfach die Einstellung figure.dpi als Standardeinstellung 80 beibehalten und konnte mit savefig () Bilder generieren, die wie Bilder aus show () aussahen.

Leon, hast du auch diese Einstellung geändert?

Karmel
quelle
Ich habe hier gerade ein Problem hinzugefügt, in der Hoffnung, dass eine bessere Lösung erstellt werden kann: github.com/matplotlib/matplotlib/issues/786
Karmel