Saving Matplotlib Interactive Drawings

Is there a way to save the Matplotlib shape so that it can be opened again and restore the typical interaction? (How is the .fig format in MATLAB?)

I run the same scripts many times to create these interactive shapes. Or I send my colleagues several static PNG files to show different aspects of the plot. I would rather send the shape object and make them interact with it myself.

+79
python matplotlib
03 Dec '10 at 18:41
source share
6 answers

This will be a great feature, but AFAIK is not implemented in Matplotlib and it will probably be difficult to implement itself because of how the numbers are stored.

I would suggest either (a) separately process the data from the creation of the figure (which saves the data with a unique name), and write the number generating the script (loading the specified file of saved data) and editing, since you see the correspondence or (b) save as PDF / SVG / PostScript and edit in some fantastic graphics editor, such as Adobe Illustrator (or Inkscape ).

+20
Dec 03 '10 at 19:03
source share

As in Matplotlib 1.2, we have experimental pickle support. Let him see if this is good for your business. If you have any questions, please let us know in the Matplotlib mailing list or by opening the github.com/matplotlib/matplotlib problem.

+32
04 Oct
source share

I just found out how to do this. The "experimental salinity support" mentioned by @pelson works quite well.

Try the following:

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

After interactive configuration, save the curly object as a binary file:

 import pickle pickle.dump(fig, open('FigureObject.fig.pickle', 'wb')) # This is for Python 3 - py2 may need `file` instead of `open` 

Later, open the shape, and the settings should be saved, and the interactivity of the GUI should be present:

 import pickle figx = pickle.load(open('FigureObject.fig.pickle', 'rb')) figx.show() # Show the figure, edit it, etc.! 

You can even extract data from graphs:

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

(It works for strings, pcolor and imshow - pcolormesh works with some tricks to restore smoothed data .)

I got great advice from Saving Matplotlib Shapes Using Pickle .

+19
Jan 30 '16 at 9:29
source share

Why not just send a Python script? MATLAB.fig files require the receiver to have MATLAB to display them, so it’s roughly equivalent to sending a Python script that requires Matplotlib to display.

Alternatively (disclaimer: I have not tried this yet), you can try to draw a figure:

 import pickle output = open('interactive figure.pickle', 'wb') pickle.dump(gcf(), output) output.close() 
+7
Dec 04 '10 at 1:56
source share
Good question. Here is the text of the document from pylab.save :

pylab no longer provides a save function, although the old pylab function is still available as matplotlib.mlab.save (you can still refer to it in pylab as "mlab.save"). However, for plain text files, we recommend numpy.savetxt. To save numpy arrays, we recommend numpy.save and its analog numpy.load, which are available in pylab as np.save and np.load.

+1
Dec 03 '10 at 18:59
source share

I figured out a relatively simple way (but a bit unconventional) to save my matplotlib metrics. I do like this:

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

with the save_plot function defined as follows (simple version for understanding the logic):

 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' 

or by defining the save_plot function as follows (the best version using zip compression to create lighter save_plot files):

 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' 

This uses the libscript module of my own, which mainly relies on the inspect and ast modules. I can try to share it with Github if interest is expressed (at first I needed to clear a bit, and I started with Github).

The idea of ​​this save_plot and libscript is to extract the python commands that create the drawing (using the inspect module), analyze them (using the ast module), to extract all variables, functions and modules import it, extract them from the execution context and serialize them as python instructions (the code for the variables will be like t=[0.0,2.0,0.01] ... and the code for the modules will be like import matplotlib.pyplot as plt ...) added to the drawing instructions. The resulting python instructions are saved as python script whose execution will rebuild the original matplotl drawing ib.

As you can imagine, this works well for most (if not all) matplotlib digits.

0
Nov 07 '17 at 14:48
source share



All Articles