PerfectVector
Par Irene Kim9 min de lecture

SVG Matplotlib : garder graphique et logo en tracés

Exporte ton graphique Matplotlib en SVG, assemble des tracés de logo avec svgutils et vérifie les pixels intégrés, le placement et les polices du fichier livré.

Sur cette page

Pour garder un logo vectoriel dans une figure Matplotlib, exporte le graphique en SVG et assemble-le avec la géométrie SVG existante du logo. Placer un PNG avec OffsetImage peut produire un SVG contenant une image matricielle à côté des lignes vectorielles du graphique. L’extension seule ne te dit pas quelles parties sont des tracés.

Ce guide sépare ces tâches : Matplotlib dessine le graphique à partir de ses données, et svgutils place un badge décoratif à côté. Si le dessin original est déjà vectoriel, utilise-le. S’il ne reste qu’une illustration matricielle adaptée, reconstruis-la séparément. Conserve les repères numériques, les axes et les libellés dans la source du graphique.

La procédure en bref

Exporte le graphique, assemble le dessin distinct, examine le SVG obtenu, puis rouvre le fichier exact que tu livreras. Conserve le script du graphique et l’original du dessin pour pouvoir régénérer la figure à la prochaine révision des données.

Choisir ce qui appartient à la source du graphique

Un logo est un dessin ; une graduation d’axe fait partie du graphique. Traiter les deux comme une seule image complique les révisions ultérieures.

Contenu de la figureSource privilégiéePoints à vérifier
Lignes, marqueurs, axes et libellés de donnéesCode Matplotlib du graphiqueValeurs, libellés et choix de représentation
Logo ou illustration vectoriels existantsOriginal SVGTracés, limites et dépendances
Photographie ou panneau de microscopie matricielsImage matricielle originaleRésolution à la taille finale
Motif décoratif simple dont la source vectorielle est perdueProposition reconstruite examinée séparémentFidélité des formes et zones indésirables

Une figure entièrement vectorielle n’est pas nécessaire lorsque certains panneaux sont des photographies. Conserve-les en matriciel. L’objectif est de garder la bonne source pour chaque composant, puis de vérifier l’assemblage.

La référence savefig de Matplotlib explique comment sélectionner explicitement un format de sortie. Son API OffsetImage décrit un conteneur d’image, plutôt qu’un importateur de tracés SVG. Pour diagnostiquer le fichier lui-même, consulte comment trouver des images matricielles dans un SVG.

Ce que contiennent les fichiers livrés

Nous avons exécuté l’exemple avec Python 3.12, Matplotlib 3.10.7 et svgutils 0.3.4. Le badge est un dessin original à deux tracés. Les quatre valeurs du graphique sont des données illustratives, pas une expérience ni une mesure comparative de produit.

La comparaison utilise le même graphique dans les deux fichiers. À gauche, un badge PNG de 32 × 32 est inséré avec OffsetImage. À droite, ses tracés SVG sont assemblés avec le graphique exporté. Les zones agrandies proviennent de ces fichiers réellement livrés.

Fichiers SVG Matplotlib réels avec zones du badge agrandies : badge PNG intégré à gauche et tracés SVG du badge assemblés à droite
Le graphique reste vectoriel dans les deux fichiers. Dans cet exemple, la version matricielle contient un élément image ; la version assemblée ajoute deux tracés de dessin et ne contient aucun élément image.

Le comptage des éléments SVG donne ces résultats :

FichierÉléments imageÉléments pathÉléments text
Graphique seul0815
Graphique avec badge PNG1815
Graphique avec tracés SVG du badge01015

Ces nombres s’appliquent à ce petit exemple. Le nombre de tracés n’est pas une note de qualité, et l’absence d’éléments image ne prouve pas que toutes les fonctionnalités SVG survivront dans une autre application. Elle établit bien que le badge de ce fichier assemblé est de la géométrie plutôt qu’un PNG intégré.

Exporter un graphique aux limites prévisibles

Installe les versions utilisées ici dans un environnement de projet :

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

Enregistre ceci sous plot.py et exécute-le dans un dossier de travail vide :

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)

Les axes n’occupent qu’une partie de la figure, laissant de la place au badge à droite. Cet export possède un viewBox de 0 0 432 216, avec des dimensions extérieures de 432pt sur 216pt.

Garde ces limites stables pendant le placement du dessin externe. Ajouter bbox_inches="tight" modifie les limites enregistrées, comme l’explique la documentation de savefig. Si tu as besoin d’un recadrage ajusté, examine le viewBox exporté et mets ensuite à jour les coordonnées de l’assemblage.

Le réglage svg.fonttype="none" conserve les libellés de l’exemple sous forme de texte. La documentation des polices de Matplotlib décrit les choix de sortie SVG en texte ou en tracés. Le texte éditable a toujours besoin d’une police adaptée dans l’environnement destinataire. Si tu veux figer les formes des lettres, choisis délibérément la sortie en tracés et conserve la source du graphique pour modifier les libellés. Le guide des changements de police SVG explique ce compromis.

Assembler le dessin sans le pixelliser

Enregistre ce badge original sous badge.svg, à côté de 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>

Exécute ensuite ce script d’assemblage :

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

Il suit la méthode de chargement, transformation, ajout et enregistrement du tutoriel d’assemblage de figures svgutils. Nous avons utilisé scale_x, l’argument pris en charge par svgutils 0.3.4 ; l’ancien tutoriel montre un autre argument de mise à l’échelle.

Le dessin du badge de 100 unités devient large de 64 unités. Son coin supérieur gauche se trouve à (332, 76) dans le système de coordonnées du graphique. Les dimensions extérieures explicites et le viewBox rendent ce placement sans ambiguïté pour cet exemple. Ce sont des coordonnées de page, pas de données : déplacer un point de données dans le graphique ne déplacera pas le badge avec lui.

Pour des annotations liées à un point de données variable, maintiens une correspondance explicite entre les coordonnées du graphique et la page exportée, ou utilise un outil d’assemblage qui gère ce lien. Un placement fixe sur la page convient à un logo en coin ou à un panneau illustratif séparé.

L’original SVG peut contenir d’autres éléments que des tracés. Un SVG qui intègre déjà un PNG conserve son contenu mixte après l’assemblage. Vérifie aussi les identifiants référencés, les polices et les ressources liées externes lorsque tu combines des fichiers plus complexes. Le badge de cet exemple évite ces dépendances.

Examiner le fichier, puis tester une révision

Ouvre vector-logo.svg dans un navigateur ou dans l’éditeur prévu. Vérifie l’ouverture centrale du badge, les libellés du graphique et l’espace vide entre les deux. Examine le fichier à sa taille d’utilisation réelle et en agrandissement.

Une petite vérification XML permet de confirmer la structure sans se fier à l’aperçu :

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

Pour l’exemple fourni, elle affiche image 0, path 10 et text 15. La comparaison matricielle affiche image 1, tout en conservant les huit tracés du graphique. Dans cette comparaison, la référence d’image contient des données PNG ; c’est un contenu matriciel autonome, pas un fichier de logo externe manquant.

Change maintenant la dernière valeur y illustrative dans plot.py, réexécute-le, puis réexécute l’assemblage. Le graphique devrait changer tandis que le badge reste à sa position réservée sur la page. Cette vérification de révision détecte une procédure qui semble correcte une seule fois, mais dépend d’un ancien export du graphique.

Vérifie séparément l’étape suivante de livraison. Si la figure doit entrer dans un document, la procédure SVG pour LaTeX explique les choix d’export et de libellés. Un aperçu réussi dans le navigateur ne suffit pas à établir la conformité à une revue ou la conservation des éléments dans le PDF final.

Reconstruire seulement le dessin qui en a besoin

Lorsque la source du graphique existe, exporte depuis celle-ci. La vectorisation ne peut pas restaurer les données numériques ou les commandes de tracé à partir d’une capture d’écran.

PerfectVector convient au cas plus limité d’un logo décoratif simple ou d’une illustration qui n’existe plus qu’en image matricielle. Avec sa procédure de reconstruction des illustrations scientifiques, recadre sur ce dessin, affiche la proposition vectorielle et examine les ouvertures, les formes fines et les zones de fond indésirables. Laisse les axes, les marques de mesure et les libellés hors de la vectorisation. Assemble le SVG du dessin accepté avec le graphique natif, puis répète les vérifications du fichier livré.

Utilise l’original vectoriel chaque fois que tu l’as. Redessine manuellement une marque simple si la vectorisation perd un détail essentiel. Garde les panneaux photographiques en matriciel. La présentation de la vectorisation d’images explique ce que cette opération peut reconstruire avant que tu choisisses cette voie.

FAQ

Enregistrer une figure Matplotlib en SVG rend-il un logo PNG vectoriel ? Non. Dans la procédure OffsetImage testée, le graphique s’exporte comme géométrie vectorielle tandis que le logo PNG reste un élément image dans le SVG.

Puis-je placer le logo SVG avec des coordonnées de données ? L’assemblage présenté ici utilise des coordonnées de page exportée. Un logo lié à un point de données exige une correspondance explicite de coordonnées ou un outil qui maintient ce lien.

Pourquoi mes libellés sont-ils devenus des tracés ? Le réglage de sortie des polices SVG de Matplotlib détermine si les libellés sont exportés en texte ou en tracés de glyphes. Choisis ce réglage avant l’export et conserve la source du graphique pour les changements de texte ultérieurs.

Sources

  1. Matplotlib — savefig — Export SVG explicite et effet des cadres englobants ajustés.
  2. Matplotlib — OffsetImage — Comportement du conteneur d’image utilisé pour la comparaison matricielle.
  3. Matplotlib — Polices dans Matplotlib — Choix de sortie SVG en texte ou en tracés de glyphes.
  4. svgutils — Créer des figures de qualité pour publication — Export séparé du graphique, assemblage SVG, transformations et enregistrement d’une figure assemblée.

Exporte le graphique depuis son code et conserve le dessin séparément. S’il ne reste qu’un motif décoratif matriciel, prépare une proposition de dessin SVG, examine ses ouvertures et ses limites, puis assemble-la avec ton graphique et vérifie les pixels, le placement et les changements de libellés dans le fichier exact livré.

Plus depuis le blog

Repartez d’un SVG plus net
et plus facile à modifier