149 votes

Enregistrer des figures Matplotlib interactives

Y a-t-il un moyen de sauvegarder une figure Matplotlib de sorte qu'elle puisse être réouverte et que l'interaction typique soit restaurée? (Comme le format .fig dans MATLAB?)

Je me retrouve à exécuter les mêmes scripts plusieurs fois pour générer ces figures interactives. Ou bien j'envoie à mes collègues plusieurs fichiers PNG statiques pour montrer différents aspects d'un tracé. Je préférerais leur envoyer l'objet figure et qu'ils interagissent avec eux-mêmes.

92voto

Demis Points 2423

Je viens de découvrir comment faire cela. Le "support expérimental de pickle" mentionné par @pelson fonctionne plutôt bien.

Essayer ceci:

# Tracer quelque chose
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
ax.plot([1,2,3],[10,-10,30])

Après avoir ajusté de manière interactive, enregistrez l'objet figure sous forme de fichier binaire:

import pickle
pickle.dump(fig, open('FigureObject.fig.pickle', 'wb')) # Cela est pour Python 3 - py2 peut avoir besoin de `file` à la place de `open`

Plus tard, ouvrez la figure et les ajustements devraient être enregistrés et l'interactivité GUI devrait être présente:

import pickle
figx = pickle.load(open('FigureObject.fig.pickle', 'rb'))

figx.show() # Afficher la figure, l'éditer, etc.!

Vous pouvez même extraire les données des tracés:

data = figx.axes[0].lines[0].get_data()

(Cela fonctionne pour les lignes, pcolor & imshow - pcolormesh fonctionne avec quelques astuces pour reconstruire les données aplaties.)

J'ai eu l'excellent conseil de Enregistrer les Figures Matplotlib en Utilisant Pickle.

0 votes

Je crois que ce n'est pas robuste aux changements de version, etc., et n'est pas compatible entre py2.x et py3.x. De plus, je pensais que la documentation pickle indiquait que nous devions configurer l'environnement de la même manière que lorsque l'objet a été picklé (sauvegardé), mais j'ai constaté que vous n'avez pas besoin d' import matplotlib.pyplot as plt lors du unpickling (chargement) - il enregistre les déclarations d'importation dans le fichier piqué.

5 votes

Vous devriez envisager de fermer les fichiers ouverts : par exemple with open('FigureObject.fig.pickle', 'rb') as file: figx = pickle.load(file)

1 votes

Je reçois juste : 'AttributeError: l'objet 'Figure' n'a pas d'attribut '_cachedRenderer''

42voto

pelson Points 5011

À partir de Matplotlib 1.2, nous avons maintenant un support expérimental pickle. Essayez et voyez si cela fonctionne bien pour votre cas. Si vous rencontrez des problèmes, veuillez nous le faire savoir sur la liste de diffusion de Matplotlib ou en ouvrant un problème sur github.com/matplotlib/matplotlib.

2 votes

Y a-t-il une raison pour laquelle cette fonctionnalité utile pourrait être ajoutée à l'option "Enregistrer sous" de la figure elle-même. Ajoutant .pkl peut-être?

0 votes

Bonne idée @dashesy. Je le soutiendrais si vous vouliez essayer de le mettre en œuvre?

1 votes

Est-ce que cela ne fonctionne que sur un sous-ensemble de back-ends? Lorsque j'essaie de mettre en conserve une figure simple sur OSX, j'obtiens PicklingError: Can't pickle : it's not found as _macosx.GraphicsContext.

36voto

dr jimbob Points 6876

Matplotlib depuis la version 1.2 vous permet de mettre en conserve les figures. Comme le notes de version indiquent, il s'agit d'une fonctionnalité expérimentale et ne prend pas en charge l'enregistrement d'une figure dans une version de matplotlib pour l'ouvrir dans une autre. Il est également généralement peu sûr de restaurer un pickle depuis une source non fiable.

Pour partager/modifier ultérieurement des graphiques (qui nécessitent d'abord un traitement important des données et qui pourraient nécessiter des ajustements des mois plus tard, par exemple lors d'une révision par les pairs pour une publication scientifique), je recommande toujours le flux de travail suivant : (1) avoir un script de traitement des données qui, avant de générer un graphique, enregistre les données traitées (qui seront utilisées dans votre graphique) dans un fichier et (2) avoir un script de génération de graphique séparé (que vous ajustez au besoin) pour recréer le graphique. De cette manière, pour chaque graphique, vous pouvez rapidement exécuter un script et le régénérer (et copier rapidement vos paramètres de graphique avec de nouvelles données). Cela dit, mettre en conserve une figure pourrait être pratique pour une analyse de données à court terme/interactive/exploratoire.

Si vous utilisez une version vraiment ancienne qui ne prend pas encore en charge cette fonctionnalité, je vous suggère soit (a) de séparer le traitement des données de la génération du graphique (qui enregistre les données avec un nom unique) et d'écrire un script de génération de graphique (chargeant un fichier spécifié des données sauvegardées) et l'éditer comme bon vous semble, soit (b) enregistrer au format PDF/SVG/PostScript et éditer dans un éditeur de graphique sophistiqué tel que Adobe Illustrator (ou Inkscape).

2 votes

Un peu surpris que cela ne soit pas mis en œuvre.. Mais bon, je vais enregistrer les données traitées dans un fichier intermédiaire et envoyer cela ainsi qu'un script pour le tracé à mes collègues. Merci.

2 votes

Je soupçonne que la mise en oeuvre est difficile, c'est pourquoi elle fonctionne si mal sur MATLAB. À l'époque où je l'utilisais, les figures avaient tendance à faire planter MATLAB, et même des versions légèrement différentes n'étaient pas capables de lire les fichiers .fig les unes des autres.

6 votes

pickle fonctionne désormais sur les figures MPL, donc cela peut être fait et semble fonctionner raisonnablement bien - presque comme un fichier de figure ".fig" de Matlab. Voir ma réponse ci-dessous (pour le moment ?) pour un exemple de comment le faire.

7voto

ptomato Points 24461

Pourquoi ne pas simplement envoyer le script Python? Les fichiers .fig de MATLAB nécessitent que le destinataire dispose de MATLAB pour les afficher, c'est donc à peu près équivalent à envoyer un script Python qui nécessite Matplotlib pour être affiché.

Alternativement (décharge de responsabilité : je n'ai pas encore essayé cela), vous pourriez essayer de mettre en conserve la figure :

import pickle
output = open('figure interactive.pickle', 'wb')
pickle.dump(gcf(), output)
output.close()

3 votes

Malheureusement, les figures matplotlib ne sont pas pickleables, donc cette approche ne fonctionnera pas. En réalité, il y a trop d'extensions C en arrière-plan qui ne prennent pas en charge le pickling. Je suis entièrement d'accord pour juste envoyer le script + les données, cependant... Je suppose que je n'ai jamais vraiment vu l'intérêt des fichiers .fig sauvegardés de matlab, donc je ne les ai jamais utilisés. Envoyer à quelqu'un du code autonome et des données a été le plus simple à long terme, de mon expérience en tout cas. Néanmoins, ce serait bien si les objets de figure de matplotlib étaient pickleables.

1 votes

Même nos données prétraitées sont assez volumineuses et la procédure de traçage est complexe. On dirait que c'est le seul recours. Merci.

1 votes

Les figures sont apparemment désormais pickleable - ça fonctionne très bien! Exemple ci-dessous.

2voto

Steve Tjoa Points 15116

Bonne question. Voici le texte du document de pylab.save :

pylab ne fournit plus de fonction d'enregistrement, bien que l'ancienne fonction pylab soit toujours disponible sous le nom matplotlib.mlab.save (vous pouvez toujours y faire référence dans pylab en tant que "mlab.save"). Cependant, pour les fichiers texte brut, nous recommandons numpy.savetxt. Pour enregistrer des tableaux numpy, nous recommandons numpy.save, et son analogue numpy.load, qui sont disponibles dans pylab sous les noms np.save et np.load.

0 votes

Cela enregistre les données de l'objet a pylab, mais ne vous permet pas de régénérer la figure.

0 votes

Correct. Je devrais clarifier que la réponse n'était pas une recommandation d'utiliser pylab.save. En fait, d'après le texte de la doc, il semble que l'on ne devrait pas l'utiliser.

0 votes

Y a-t-il une méthode externe pour envoyer une figure 3D ? Peut-être même une interface graphique simple vers un fichier exe...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X