2

I'm wondering how could I save the data content of a plot generated using Matplotlib to a Numpy array.

As a example, suppose I generated a contour plot with the following code:

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)

plt.figure()
CS = plt.contour(X, Y, Z)
plt.show()

From that I get the following:

enter image description here

I'm wondering how I could save this data so, after some other manipulations, if I show that data with imshow, for example, I could recover the contours color mapped and filled like the original image.

EDIT:

I.e., I would like to be able to get the image generate by the contourf method, do some manipulation to it, like to apply some mask in specific areas, and then plot this modified data. For the contour case, I would like to use this plot with a bunch of levels represented to do the manipulations, instead of iterating over the cs.collection and do something (which I really don't know what) to obtain an equivalent numpy.array to represent this plot.

I know that I can save the image to a file than read this file but that seems a poor solution to me. I tried that solution too, but then I got the full plot, with green areas and so on, not just the real content.

Community
  • 1
  • 1
pceccon
  • 9,379
  • 26
  • 82
  • 158
  • I'm having trouble understanding exactly what you want, even from your 09/10/14 edit. Could you give a specific example (in python code) of what you would like to do with the fig and data before it's saved, and then maybe it would be possible to figure out how to save it so the same thing could be done in the reloaded figure. – tom10 Oct 09 '14 at 14:56

1 Answers1

4

For recent versions of matplotlib, you can use pickle to save the whole plot or just selected pieces, and even show the plot again from the pickled data:

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

if 0:  # to generate the file
    delta = 0.025
    x = np.arange(-3.0, 3.0, delta)
    y = np.arange(-2.0, 2.0, delta)
    X, Y = np.meshgrid(x, y)
    Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
    Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
    Z = 10.0 * (Z2 - Z1)

    ax = plt.subplot(111)
    CS = ax.contourf(X, Y, Z)

    pickle.dump(ax, open("mpl_test.pkl", "w"))
    pickle.dump(CS, open("contours.pkl", "w"))

else: # Then at a later time...

    x0 = pickle.load(open("mpl_test.pkl", "r"))
    x1 = pickle.load(open("contours.pkl", "r"))

    v = x1.collections[0].get_paths()[0].vertices   # get the vertices of the contour
    x, y = v[:,0]+.2, v[:,1]+.1                     # shift the contour
    x0.plot(x, y, 'w', linewidth=3)                 # add it to the plot as a white line

The example above first pickles the contour plot with the if clause, and then, at a latter time, using the else part. It then takes one of the contours and shifts it and replots it as a white line.

That is, this figure and modified contour are drawn completely from the reloaded pickled figure.

enter image description here

Contours, are mpl Paths, and can be more complicated than this example implies, so this method won't always work so well (though a generalized version of it the took into account other path data would -- see the docs linked above).

Pickling mpl items is a bit new and not fully documented or reliable, but is a useful feature.

IPython Notebook:
On the other hand, maybe what you really want is something like an IPython Notebook! There, the whole history of your computations is available, viewable, and runnable. Rather than storing the data, it allows you to easily re-access, modify what you did before, etc. It's very powerful. Here are a few links and examples: A, B, C, D.

tom10
  • 67,082
  • 10
  • 127
  • 137
  • Awesome method. However, what I would like to be open to do is to access the data and do some calculation, like apply a mask over it, and plot the result. This doesn't allow me to do that, right? – pceccon Oct 07 '14 at 20:40
  • 1
    It's a great feature. I think the way to think of it is that you can get (and possibly modify) every detail of how the plot is drawn, but nothing about what got you there. For example, the curves that define the contours are mpl paths ( http://matplotlib.org/api/path_api.html#matplotlib.path.Path ), and you can get their vertices, etc, but they are vector drawing curves, not just numpy arrays of x,y pairs. – tom10 Oct 07 '14 at 23:25
  • I added an example to illustrate. As I say there though, it might make it look more easy than the general problem is. – tom10 Oct 08 '14 at 02:03
  • A little add-on regarding the mentioned reliability the [matplotlib](http://matplotlib.org/users/whats_new.html#figures-are-picklable) documentation tells us that pickles "are unsupported when restoring a pickle saved in another matplotlib version and are insecure when restoring a pickle from an untrusted source" – makra Oct 14 '14 at 00:07
  • Yeah, what I would like was in fact to recover some array of the data plotted (but not my original data, the data obtained trough some plot method, as contour). But I understood that this is not provided. – pceccon Oct 21 '14 at 12:36