Saya menemukan cara yang relatif sederhana (namun sedikit tidak konvensional) untuk menyimpan gambar matplotlib saya. Ini bekerja seperti ini:
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)
#<plot>
plt.plot(t, s)
plt.xlabel('time (s)')
plt.ylabel('voltage (mV)')
plt.title('About as simple as it gets, folks')
plt.grid(True)
plt.show()
#</plot>
save_plot(fileName='plot_01.py',obj=sys.argv[0],sel='plot',ctx=libscript.get_ctx(ctx_global=globals(),ctx_local=locals()))
dengan fungsi yang save_plot
didefinisikan seperti ini (versi sederhana untuk memahami logika):
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'
atau mendefinisikan fungsi save_plot
seperti ini (versi yang lebih baik menggunakan kompresi zip untuk menghasilkan file gambar yang lebih ringan):
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'
Ini membuat saya menggunakan modul libscript
sendiri, yang sebagian besar bergantung pada modul inspect
dan ast
. Saya dapat mencoba membagikannya di Github jika ada minat yang diungkapkan (pertama-tama perlu pembersihan dan saya harus memulai dengan Github).
Ide di balik save_plot
fungsi dan libscript
modul ini adalah untuk mengambil instruksi python yang membuat gambar (menggunakan modul inspect
), menganalisisnya (menggunakan modul ast
) untuk mengekstrak semua variabel, fungsi, dan impor modul yang diandalkan, mengekstraknya dari konteks eksekusi dan membuat serialisasi. sebagai instruksi python (kode untuk variabel akan seperti t=[0.0,2.0,0.01]
... dan kode untuk modul akan seperti import matplotlib.pyplot as plt
...) diawali dengan petunjuk gambar. Instruksi python yang dihasilkan disimpan sebagai skrip python yang eksekusinya akan membangun kembali gambar matplotlib asli.
Seperti yang dapat Anda bayangkan, ini berfungsi dengan baik untuk sebagian besar (jika tidak semua) figur matplotlib.