57

I work in an psudo-operational environment where we make new imagery on receipt of data. Sometimes when new data comes in, we need to re-open an image and update that image in order to create composites, add overlays, etc. In addition to adding to the image, this requires modification of titles, legends, etc.

Is there something built into matplotlib that would let me store and reload my matplotlib.pyplot object for later use? It would need to maintain access to all associated objects including figures, lines, legends, etc. Maybe pickle is what I'm looking for, but I doubt it.

asked Sep 3, 2011 at 0:27
12
  • can't you simply put the figures into a list? Commented Sep 3, 2011 at 22:21
  • 11
    This would be a great feature (Matlab has it). I think, though, the answer is no, and the question is a duplicate stackoverflow.com/questions/4348733/…. Commented Sep 4, 2011 at 17:32
  • 1
    That works if you always have your data available. Here is my situation in timeline form. 1) Receive data from one satellite 2) Make multiple plots from data with associated legends, titles, etc. 3) Save figures for display on webpage 4) Get new data from different satellite that is needed for an overlay to the previous product (think satellite derived wind barbs overlain on satellite imagery) Commented Sep 4, 2011 at 19:42
  • 5) Need to retrieve an object containing all of the original matplotlib.pyplot information so that a new figure can be created and relevant parts updated (legends, titles, etc) The problem here is that the data from the second satellite may come in up to a few hours before or after the data from the first satellite. Since I can't have a process continually running to keep updating the figure, I need to figure out a way to save and update the matplotlib.pyplot object. Commented Sep 4, 2011 at 19:49
  • @tom10: Thanks for pointing out the duplicate. This could be really problematic for me, though...maybe I'll have to look into the matplotlib source and see if there is something that can be done about this problem. I'm guessing that my python skills are not quite up to snuff for adding a feature like this, though. Commented Sep 4, 2011 at 19:51

6 Answers 6

63

As of 1.2 matplotlib ships with experimental pickling support. If you come across any issues with it, please let us know on the mpl mailing list or by opening an issue on github.com/matplotlib/matplotlib

HTH

EDIT: Added a simple example

import matplotlib.pyplot as plt
import numpy as np
import pickle
ax = plt.subplot(111)
x = np.linspace(0, 10)
y = np.exp(x)
ax.plot(x, y)
pickle.dump(ax, open('myplot.pickle', 'w'))

Then in a separate session:

import matplotlib.pyplot as plt
import pickle
ax = pickle.load(open('myplot.pickle'))
plt.show()
Trenton McKinney
63.1k41 gold badges169 silver badges210 bronze badges
answered Oct 4, 2012 at 19:45
17
  • 2
    I'm having problems making pickling work with matplotlib. Is there any sample code showing how to use it? Commented Mar 4, 2013 at 22:18
  • 1
    I've added an example. If you're having problems after this example, it could be you've found a bug - please do let us know. HTH Commented Mar 5, 2013 at 9:52
  • 1
    as of Jan 2015, on Py3.5 this works great without many bugs that i've encountered, although I've been saving the fig, not the ax - not sure what the difference is (I didn't actually know Axes had a show() method.) Commented Feb 1, 2016 at 19:49
  • 1
    Thanks. But zoom rect option is not working after pickling. Zooming is fine in the original picture, but after loading figure from pickle, everything works fine without zoom option. Commented Jul 9, 2017 at 21:42
  • 2
    To re-show the saved figure, I found that creating a dummy figure as described in this answer helped bring the figure back to life. Commented Jul 24, 2018 at 20:19
17

A small modification to Pelson's answer for people working on a Jupyterhub

Use %matplotlib notebook before loading the pickle. Using %matplotlib inline did not work for me in either jupyterhub or jupyter notebook. and gives a traceback ending in AttributeError: 'module' object has no attribute 'new_figure_manager_given_figure'.

import matplotlib.pyplot as plt
import numpy as np
import pickle
%matplotlib notebook
ax = plt.subplot(111)
x = np.linspace(0, 10)
y = np.exp(x)
plt.plot(x, y)
with open('myplot.pkl','wb') as fid:
 pickle.dump(ax, fid)

Then in a separate session:

import matplotlib.pyplot as plt
import pickle
%matplotlib notebook
with open('myplot.pkl','rb') as fid:
 ax = pickle.load(fid)
plt.show()
answered Jul 21, 2016 at 16:01
1
  • In JulpyterLab, %matplotlib notebook did not work, but %matplotlib inline worked for me. Commented Oct 5, 2021 at 20:09
1

I produced figures for a number of papers using matplotlib. Rather than thinking of saving the figure (as in MATLAB), I would write a script that plotted the data then formatted and saved the figure. In cases where I wanted to keep a local copy of the data (especially if I wanted to be able to play with it again) I found numpy.savez() and numpy.load() to be very useful.

At first I missed the shrink-wrapped feel of saving a figure in MATLAB, but after a while I have come to prefer this approach because it includes the data in a format that is available for further analysis.

answered Jan 11, 2012 at 16:18
1
  • You can actually extract data from a saved Figure/Axis object, just like in Matlab. See Line.get_data() (and the Lines are stored in the Axis, which is stored in the Figure). I used to do this in Matlab quite a lot. Commented Feb 1, 2016 at 20:09
1

Tested in jupyter notebook.

import matplotlib.pyplot as plt
import numpy as np
import pickle
fig, axes = plt.subplots(figsize=(20, 5),nrows=1, ncols=2) 
x,y = np.arange(10), np.random.random(10)
axes[0].plot(x,y)
axes[1].plot(x,y)
plt.show()
# myfname = input("Save figure? [enter filename]: ") 
myfname = 'test'
if (myfname!=''):
 fig.savefig(f'./{myfname}.png')
 print(f'file saved to ./{myfname}.png')
 with open(f'./{myfname}.png.pkl','wb') as fid:
 pickle.dump(fig, fid)
 print(f'pickled to ./{myfname}.png.pkl') 
###################################
####### in a separate session
myfname = 'test'
with open(f'./{myfname}.png.pkl', 'rb') as fh:
 fig_loaded = pickle.load(fh)
print(fig_loaded.axes[0].lines[0].get_data()) # get data
fig_loaded # show fig
answered Apr 29, 2021 at 9:04
0

Did you try the pickle module? It serialises an object, dumps it to a file, and can reload it from the file later.

answered Oct 20, 2011 at 23:55
2
  • I don't think that pickle is able to serialise matplotlib objects. It seems to fail. One of the comments above mentions that pickle breaks axis objects (and likely other matplotlib objects besides). Commented Oct 28, 2011 at 21:16
  • 1
    I don't think pickle serialises nested objects by default. Maybe this hack will help: stackoverflow.com/questions/1947904/… Commented Nov 12, 2011 at 19:27
0

For anyone who has saved a figure as an image and wants to do this without using pickle:

Have you figure created in the first instance, ready to be saved as a png image. You can save with:

fig.savefig(filename) 

When it comes to loading that figure in subsequent instances, you can run:

fig = plt.imshow(plt.imread(filename)).get_figure()
answered Jan 28 at 11:41

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.