PerfectVector
Von Irene Kim8 Min. Lesezeit

Matplotlib-SVG: Diagramm und Logo als Pfade erhalten

Exportiere dein Matplotlib-Diagramm als SVG, ergänze separate Logopfade mit svgutils und prüfe die fertige Datei auf eingebettete Pixel, Platzierung und Schriftänderungen.

Auf dieser Seite

Damit ein Logo innerhalb einer Matplotlib-Abbildung als Vektor erhalten bleibt, exportiere das Diagramm als SVG und kombiniere es mit der vorhandenen SVG-Geometrie des Logos. Wenn du ein PNG mit OffsetImage einfügst, kann ein SVG entstehen, das neben den Vektorlinien des Diagramms auch ein Rasterbild enthält. Die Dateiendung allein verrät nicht, welche Teile Pfade sind.

Dieser Leitfaden trennt diese Aufgaben: Matplotlib zeichnet das Diagramm aus seinen Daten, und svgutils platziert daneben ein dekoratives Abzeichen. Liegt die Originalgrafik bereits als Vektor vor, verwende sie. Wenn nur eine geeignete Rasterillustration erhalten ist, rekonstruiere diese Illustration separat. Behalte numerische Markierungen, Achsen und Beschriftungen in der Diagrammquelle.

Der kurze Ablauf

Exportiere das Diagramm, ergänze die separate Grafik, prüfe das entstandene SVG und öffne dann genau die Datei erneut, die du liefern wirst. Behalte das Diagrammskript und die Grafikvorlage, damit du die Abbildung bei der nächsten Datenänderung neu erzeugen kannst.

Entscheiden, was in die Diagrammquelle gehört

Ein Logo ist eine Grafik; ein Achsenstrich gehört zum Diagramm. Wenn du beides als ein einziges Bild behandelst, erschwert das spätere Änderungen.

Inhalt der AbbildungBevorzugte QuelleWas du prüfen solltest
Linien, Markierungen, Achsen und DatenbeschriftungenMatplotlib-DiagrammcodeWerte, Beschriftungen und Darstellungsentscheidungen
Vorhandenes Vektorlogo oder VektorillustrationDie SVG-VorlagePfade, Begrenzungen und Abhängigkeiten
Rasterfoto oder MikroskopiebildOriginales RasterbildAuflösung bei der endgültigen Größe
Einfaches dekoratives Motiv, dessen Vektorquelle verloren istEin separat geprüfter RekonstruktionskandidatFormtreue und unerwünschte Bereiche

Eine vollständig aus Vektoren bestehende Abbildung ist nicht nötig, wenn einige Teilbilder Fotografien sind. Behalte diese als Rasterbilder bei. Ziel ist, für jede Komponente die passende Quelle zu erhalten und anschließend das zusammengesetzte Ergebnis zu prüfen.

Matplotlibs savefig-Referenz dokumentiert die ausdrückliche Wahl eines Ausgabeformats. Seine OffsetImage-API beschreibt einen Bildcontainer, keinen Importer für SVG-Pfade. Für die Diagnose auf Dateiebene lies, wie du Rasterbilder in einem SVG findest.

Was die gelieferten Dateien enthalten

Wir haben das Beispiel mit Python 3.12, Matplotlib 3.10.7 und svgutils 0.3.4 ausgeführt. Das Abzeichen ist eine eigene Zeichnung aus zwei Pfaden. Die vier dargestellten Werte sind Beispieldaten, kein Experiment und kein Produktbenchmark.

Der Vergleich verwendet in beiden Dateien dasselbe Diagramm. Links wird ein 32 × 32 großes PNG-Abzeichen mit OffsetImage eingefügt. Rechts werden seine SVG-Pfade mit dem exportierten Diagramm kombiniert. Die vergrößerten Ausschnitte stammen aus diesen tatsächlich gelieferten Dateien.

Tatsächliche Matplotlib-SVG-Dateien mit vergrößerten Abzeichenbereichen: links ein eingebettetes PNG-Abzeichen, rechts hinzugefügte SVG-Pfade des Abzeichens
Das Diagramm bleibt in beiden Dateien vektorbasiert. In diesem Testbeispiel enthält die Rasterversion ein image-Element; die zusammengesetzte Version ergänzt zwei Grafikpfade und enthält kein image-Element.

Das Zählen der SVG-Elemente ergab diese Ergebnisse:

Dateiimage-Elementepath-Elementetext-Elemente
Diagramm allein0815
Diagramm mit PNG-Abzeichen1815
Diagramm mit SVG-Pfaden des Abzeichens01015

Diese Zahlen gelten für dieses kleine Testbeispiel. Die Anzahl der Pfade ist kein Qualitätsmaßstab, und null image-Elemente beweisen nicht, dass jede SVG-Funktion in einer anderen Anwendung erhalten bleibt. Sie zeigen aber, dass das Abzeichen in dieser zusammengesetzten Datei Geometrie ist und kein eingebettetes PNG.

Ein Diagramm mit vorhersehbaren Begrenzungen exportieren

Installiere die hier verwendeten Versionen in einer Projektumgebung:

python -m pip install matplotlib==3.10.7 svgutils==0.3.4

Speichere dies als plot.py und führe es in einem leeren Arbeitsordner aus:

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
 
plt.rcParams["svg.fonttype"] = "none"
 
fig = plt.figure(figsize=(6, 3), dpi=72)
ax = fig.add_axes([0.14, 0.22, 0.58, 0.65])
ax.plot([0, 1, 2, 3], [1, 2, 1.5, 3],
        marker="o", color="#173b40")
ax.set(xlabel="Example x", ylabel="Example y",
       title="Illustrative data only")
ax.spines[["top", "right"]].set_visible(False)
fig.savefig("plot.svg", format="svg")
plt.close(fig)

Die Achsen belegen nur einen Teil der Abbildung und lassen rechts Platz für das Abzeichen. Dieser Export hat einen viewBox von 0 0 432 216 und äußere Abmessungen von 432pt mal 216pt.

Halte diese Begrenzungen beim Platzieren externer Grafiken konstant. Das Hinzufügen von bbox_inches="tight" verändert die gespeicherten Begrenzungen, wie die savefig-Dokumentation erklärt. Wenn du eng zuschneiden musst, prüfe den exportierten viewBox und passe danach deine Koordinaten für die Zusammenstellung an.

Die Einstellung svg.fonttype="none" erhält die Beschriftungen des Beispiels als Text. Matplotlibs Schriftdokumentation beschreibt die Ausgabe als SVG-Text oder Pfade. Bearbeitbarer Text benötigt weiterhin eine geeignete Schrift in der Zielumgebung. Wenn du feste Buchstabenformen brauchst, wähle bewusst die Pfadausgabe und behalte die Diagrammquelle für Änderungen an Beschriftungen. Der Leitfaden zu Schriftänderungen in SVG erklärt diesen Zielkonflikt.

Die Grafik ergänzen, ohne sie zu rastern

Speichere dieses eigene Abzeichen als badge.svg neben plot.svg:

<svg xmlns="http://www.w3.org/2000/svg"
     width="100" height="100" viewBox="0 0 100 100">
  <path fill="#173b40" fill-rule="evenodd"
        d="M30 5H70L95 30V70L70 95H30L5 70V30Z
           M34 17L17 34V66L34 83H66L83 66V34L66 17Z"/>
  <path fill="#28bfa3" d="M53 23L30 55H47L43 77L70 43H53Z"/>
</svg>

Führe anschließend dieses Skript zum Zusammenstellen aus:

import svgutils.transform as sg
 
page = sg.SVGFigure("432pt", "216pt")
page.root.set("viewBox", "0 0 432 216")
 
chart = sg.fromfile("plot.svg").getroot()
badge = sg.fromfile("badge.svg").getroot()
badge.moveto(332, 76, scale_x=0.64)
 
page.append([chart, badge])
page.save("vector-logo.svg")

Das folgt dem Vorgehen Laden, Transformieren, Anhängen und Speichern aus dem svgutils-Tutorial zum Zusammenstellen von Abbildungen. Wir haben scale_x verwendet, das von svgutils 0.3.4 unterstützte Argument; das ältere Tutorial zeigt ein anderes Skalierungsargument.

Die 100 Einheiten breite Grafik des Abzeichens wird 64 Einheiten breit. Ihre obere linke Ecke liegt bei (332, 76) innerhalb des Koordinatensystems des Diagramms. Die ausdrücklichen äußeren Abmessungen und der viewBox machen diese Platzierung für dieses Testbeispiel eindeutig. Das sind Seitenkoordinaten, keine Datenkoordinaten: Wenn du einen Datenpunkt im Diagramm verschiebst, bewegt sich das Abzeichen nicht mit.

Für Anmerkungen, die an einen sich ändernden Datenpunkt gebunden sind, pflege eine bewusste Abbildung der Diagrammkoordinaten auf die exportierte Seite oder verwende ein Werkzeug, das diese Zuordnung bereitstellt. Eine feste Seitenposition eignet sich für ein Logo in einer Ecke oder ein separates illustratives Teilbild.

Die SVG-Vorlage kann Funktionen enthalten, die über Pfade hinausgehen. Ein SVG, das bereits ein PNG einbettet, bleibt auch nach dem Zusammenstellen gemischter Inhalt. Prüfe beim Kombinieren komplexerer Dateien außerdem referenzierte IDs, Schriften und extern verknüpfte Dateien. Dieses Beispiel vermeidet solche Abhängigkeiten im Abzeichen.

Die Datei prüfen und anschließend eine Änderung testen

Öffne vector-logo.svg in einem Browser oder deinem vorgesehenen Editor. Prüfe die zentrale Aussparung des Abzeichens, die Diagrammbeschriftungen und den freien Platz dazwischen. Prüfe die Datei sowohl in der tatsächlich verwendeten Größe als auch vergrößert.

Eine kleine XML-Prüfung kann die Struktur unabhängig von der Vorschau bestätigen:

import xml.etree.ElementTree as ET
 
root = ET.parse("vector-logo.svg").getroot()
ns = "{http://www.w3.org/2000/svg}"
for tag in ("image", "path", "text"):
    print(tag, len(root.findall(".//" + ns + tag)))

Für das bereitgestellte Testbeispiel gibt dies image 0, path 10 und text 15 aus. Der Rastervergleich gibt image 1 aus und behält die acht Pfade des Diagramms bei. In diesem Vergleich enthält die Bildreferenz PNG-Daten; es handelt sich um eigenständig eingebetteten Rasterinhalt, nicht um eine fehlende externe Logodatei.

Ändere nun den letzten beispielhaften y-Wert in plot.py, führe das Skript erneut aus und wiederhole die Zusammenstellung. Das Diagramm sollte sich verändern, während das Abzeichen auf seiner reservierten Seitenposition bleibt. Diese Änderungsprüfung deckt einen Ablauf auf, der einmal richtig aussieht, aber von einem alten Diagrammexport abhängt.

Prüfe den nächsten Übergabeschritt separat. Wenn die Abbildung in ein Dokument eingefügt werden soll, erklärt der LaTeX-SVG-Ablauf die Export- und Beschriftungsmöglichkeiten. Eine erfolgreiche Browservorschau allein belegt weder die Einhaltung von Zeitschriftenvorgaben noch den Erhalt in einer endgültigen PDF.

Nur die Grafik rekonstruieren, die rekonstruiert werden muss

Wenn die Diagrammquelle vorhanden ist, exportiere daraus. Eine Vektorisierung kann numerische Daten oder Diagrammbefehle nicht aus einem Screenshot wiederherstellen.

PerfectVector eignet sich für den engeren Fall, dass ein einfaches dekoratives Logo oder eine Illustration nur als Rasterbild erhalten ist. Schneide mit seinem Ablauf zur Rekonstruktion wissenschaftlicher Grafiken auf diese Grafik zu, sieh dir den Vektorkandidaten an und prüfe Aussparungen, dünne Formen und unerwünschte Hintergrundbereiche. Halte Achsen, Messmarkierungen und Beschriftungen aus der Nachzeichnung heraus. Kombiniere das akzeptierte Grafik-SVG mit dem nativ erzeugten Diagramm und wiederhole dann die Prüfungen der gelieferten Datei.

Verwende die ursprüngliche Vektorvorlage, wann immer du sie hast. Zeichne ein einfaches Zeichen von Hand neu, wenn bei der Nachzeichnung ein wichtiges Detail verloren geht. Behalte fotografische Teilbilder als Rasterbilder. Der Überblick zur Bildvektorisierung erklärt, was eine Nachzeichnung rekonstruieren kann, bevor du diesen Weg wählst.

FAQ

Wird ein PNG-Logo zum Vektor, wenn ich eine Matplotlib-Abbildung als SVG speichere? Nein. Im getesteten OffsetImage-Ablauf wird das Diagramm als Vektorgeometrie exportiert, während das PNG-Logo ein image-Element innerhalb des SVG bleibt.

Kann ich das SVG-Logo mit Datenkoordinaten platzieren? Die hier gezeigte Zusammenstellung verwendet exportierte Seitenkoordinaten. Ein an einen Datenpunkt gebundenes Logo benötigt eine ausdrückliche Koordinatenabbildung oder ein Werkzeug, das diese Zuordnung aufrechterhält.

Warum wurden meine Beschriftungen zu Pfaden? Matplotlibs Einstellung für die SVG-Schriftausgabe steuert, ob Beschriftungen als Text oder als Glyphenpfade exportiert werden. Wähle diese Einstellung vor dem Export und behalte die Diagrammquelle für spätere Textänderungen.

Quellen

  1. Matplotlib — savefig — Ausdrücklicher SVG-Export und die Wirkung enger Begrenzungsrahmen.
  2. Matplotlib — OffsetImage — Verhalten des für den Rastervergleich verwendeten Bildcontainers.
  3. Matplotlib — Schriften in Matplotlib — Ausgabeoptionen für SVG-Text und Glyphenpfade.
  4. svgutils — Abbildungen in Publikationsqualität erstellen — Separater Diagrammexport, SVG-Zusammenstellung, Transformationen und Speichern einer zusammengesetzten Abbildung.

Exportiere das Diagramm aus seinem Code und halte die Grafik separat. Wenn nur ein dekoratives Rastermotiv übrig ist, erstelle einen SVG-Grafikkandidaten, prüfe seine Aussparungen und Begrenzungen, kombiniere ihn dann mit deinem Diagramm und prüfe die tatsächlich gelieferte Datei auf Pixel, Platzierung und Beschriftungsänderungen.

Mehr aus dem Blog

Starte mit einer sauberen SVG,
die leichter zu bearbeiten ist