J'ai trouvé un moyen relativement simple (bien que légèrement non conventionnel) de sauvegarder mes figures matplotlib. Cela fonctionne comme suit :
import libscript
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2*np.pi*t)
#
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('Aussi simple que possible, les gens')
plt.grid(True)
plt.show()
#
save_plot(fileName='plot_01.py',obj=sys.argv[0],sel='plot',ctx=libscript.get_ctx(ctx_global=globals(),ctx_local=locals()))
avec la fonction save_plot
définie comme ceci (version simple pour comprendre la logique) :
def save_plot(fileName='',obj=None,sel='',ctx={}):
"""
Save of matplolib plot to a stand alone python script containing all the data and configuration instructions to regenerate the interactive matplotlib figure.
Parameters
----------
fileName : [string] Path of the python script file to be created.
obj : [object] Function or python object containing the lines of code to create and configure the plot to be saved.
sel : [string] Name of the tag enclosing the lines of code to create and configure the plot to be saved.
ctx : [dict] Dictionary containing the execution context. Values for variables not defined in the lines of code for the plot will be fetched from the context.
Returns
-------
Return ``'done'`` once the plot has been saved to a python script file. This file contains all the input data and configuration to re-create the original interactive matplotlib figure.
"""
import os
import libscript
N_indent=4
src=libscript.get_src(obj=obj,sel=sel)
src=libscript.prepend_ctx(src=src,ctx=ctx,debug=False)
src='\n'.join([' '*N_indent+line for line in src.split('\n')])
if(os.path.isfile(fileName)): os.remove(fileName)
with open(fileName,'w') as f:
f.write('import sys\n')
f.write('sys.dont_write_bytecode=True\n')
f.write('def main():\n')
f.write(src+'\n')
f.write('if(__name__=="__main__"):\n')
f.write(' '*N_indent+'main()\n')
return 'done'
ou en définissant la fonction save_plot
comme ceci (meilleure version utilisant la compression zip pour produire des fichiers de figure plus légers) :
def save_plot(fileName='',obj=None,sel='',ctx={}):
import os
import json
import zlib
import base64
import libscript
N_indent=4
level=9#0 to 9, default: 6
src=libscript.get_src(obj=obj,sel=sel)
obj=libscript.load_obj(src=src,ctx=ctx,debug=False)
bin=base64.b64encode(zlib.compress(json.dumps(obj),level))
if(os.path.isfile(fileName)): os.remove(fileName)
with open(fileName,'w') as f:
f.write('import sys\n')
f.write('sys.dont_write_bytecode=True\n')
f.write('def main():\n')
f.write(' '*N_indent+'import base64\n')
f.write(' '*N_indent+'import zlib\n')
f.write(' '*N_indent+'import json\n')
f.write(' '*N_indent+'import libscript\n')
f.write(' '*N_indent+'bin="'+str(bin)+'"\n')
f.write(' '*N_indent+'obj=json.loads(zlib.decompress(base64.b64decode(bin)))\n')
f.write(' '*N_indent+'libscript.exec_obj(obj=obj,tempfile=False)\n')
f.write('if(__name__=="__main__"):\n')
f.write(' '*N_indent+'main()\n')
return 'done'
Cela utilise un module libscript
que j'ai créé, qui repose principalement sur les modules inspect
et ast
. Je peux essayer de le partager sur Github si un intérêt est exprimé (cela nécessiterait d'abord un peu de nettoyage et que je m'initie à Github).
L'idée derrière cette fonction save_plot
et le module libscript
est de récupérer les instructions python qui créent la figure (en utilisant le module inspect
), de les analyser (en utilisant le module ast
) pour extraire toutes les variables, fonctions et modules importés dont elles dépendent, de les extraire du contexte d'exécution et de les sérialiser sous forme d'instructions python (le code des variables sera comme t=[0.0,2.0,0.01]
... et le code des modules sera comme import matplotlib.pyplot as plt
...) ajoutés aux instructions de la figure. Les instructions python résultantes sont sauvegardées sous forme d'un script python dont l'exécution reconstruira la figure matplotlib d'origine.
Comme vous pouvez l'imaginer, cela fonctionne bien pour la plupart (si ce n'est pour toutes) les figures matplotlib.