Skip to content

Instantly share code, notes, and snippets.

@demisjohn
Last active February 11, 2021 15:14
Show Gist options
  • Save demisjohn/883295cdba36acbb71e4 to your computer and use it in GitHub Desktop.
Save demisjohn/883295cdba36acbb71e4 to your computer and use it in GitHub Desktop.
How to use Python's `pickle` to save/load matplotlib Figures to/from a file.
'''
To save python objects of any sort, to a file.
'''
import pickle as pkl
pkl.dump( fig, open('FigureObject.pickle', 'wb') )
pkl.dump( fig, open('FigureObject.pickle', 'wb'), fix_imports=True ) # fix_imports makes it py2x compatible - untested
'''
Load python objects from file
'''
import pickle as pkl
# import other modules needed to work with the figure, such as np, plt etc.
figx = pkl.load( open('TLM Curves v3 (H38+others)'+'.pickle', 'rb') )
# display the loaded figure:
import matplotlib.pyploy as plt # think this is necessary...haven't tested
figx.show() # show the figure, edit it etc.!
data = figx.axes[0].lines[0].get_data() # extract data from the figure! works for lines, pcolor & imshow (pcolormesh with some tricks to reconstruct the flattened data)
@demisjohn
Copy link
Author

@Anunalla
Copy link

Hi
I used the method you have described here to reload a pcolor image that I pickled beforehand but it evokes the error "list index out of range". The below is my code. I would appreciate it if you could take a look at it and advice me on what is wrong with it. Thank you

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pickle

Fs = 8000
f = 1000
sample =20000
x = np.arange(sample)
y = np.sin(2 * np.pi * f * x / Fs)
plt.figure()
plt.plot(x, y)
plt.xlabel('voltage(V)')
plt.ylabel('sample(n)')
plt.show()

dt=1.0/Fs
winsize=1024
shift=int(winsize/2)
frqlen=shift
datalen=len(y)
FFTdata=np.zeros((0,frqlen))
fftfreq=np.fft.fftfreq(winsize,d=dt)[:frqlen]
for i in range(0,datalen,shift):
xdata=x[i:i+winsize]
if len(xdata)<>winsize:
break
fftdata=np.fft.fft(xdata,winsize)
absdata=np.abs(fftdata)[:frqlen]
logpower=10* np.log(absdata ** 2).reshape((1,len(absdata)))
FFTdata=np.append(FFTdata,logpower,axis=0)
sampleno=np.arange(1,len(FFTdata)+1)
fig,ax=plt.subplots()
FFTdata=FFTdata.T
im=ax.pcolor(sampleno,fftfreq,FFTdata)
cbar=fig.colorbar(im)
fig.show()

pickle.dump(fig,open("dumptrial.p",'wb'))

figure=pickle.load(open("dumptrial.p",'rb'))
figure.show()
data=figure.axes[0].images[0].get_data()

@peci1
Copy link

peci1 commented Sep 18, 2018

typo: pyploy -> pyplot

@fomightez
Copy link

fomightez commented Feb 14, 2020

If you are trying to unpickle the plot in another Jupyter notebook and seeing nothing where you expect the plot to be shown, or are seeing errors like 'NoneType' object has no attribute 'print_figure' or 'NoneType' object has no attribute 'manager' as you try various combinations of plt.show() and .show(), etc., you'll want to see this StackOverflow answer here. It is because you need another canvas manager before you can show your figure. You can hijack a dummy one to use for your unpickled matplotlib figure x to display it in a notebook cell, like so:

%matplotlib inline

import matplotlib.pyplot as plt

def make_manager(fig):
    # create a dummy figure and use its
    # manager to display "fig"  ; based on https://stackoverflow.com/a/54579616/8508004
    dummy = plt.figure()
    new_manager = dummy.canvas.manager
    new_manager.canvas.figure = fig
    fig.set_canvas(new_manager.canvas)

make_manager(x)
x.show()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment