Frage

I plot rather complex data with matplotlib's imshow(), so I prefer to first visually inspect if it is all right, before saving. So I usually call plt.show(), see if it is fine, and then manually save it with a GUI dialog in the show() window. And everything was always fine, but recently I started getting a weird thing. When I save the figure I get a very wrong picture, though it looks perfectly fine in the matplotlib's interactive window. If I zoom to a specific location and then save what I see, I get a fine figure.

So, this is the correct one (a small area of the picture, saved with zooming first):enter image description here

And this one is a zoom into approximately the same area of the figure, after I saved it all:approx

For some reason pixels in the second one are much bigger! That is vary bad for me - as you can see, it looses a lot of details in there.

Unfortunately, my code is quite complicated and I wasn't able to reproduce it with some randomly generated data. This problem appeared after I started to plot two triangles of the picture separately: I read my two huge data files with np.loadtxt(), get np.triu(data1) and np.tril(data2), mask zeroes, NAs, -inf and +inf and then plot them on the same axes with plt.imshow(data, interpolation='none', origin='lower', extent=extent). I do lot's of other different things to make it nicer, but I guess it doesn't matter, because it all worked like a charm before.

Please, let me know, if you need to know anything else specific from my code, that could be relevant to this problem.

War es hilfreich?

Lösung

When you save a figure in png/jpg you are forced to rasterize it, convert it to a finite number of pixels. If you want to keep the full resolution, you have a few options:

  • Use a very high dpi parameter, like 900. Saving the plot will be slow, and many image viewers will take some time to open it, but the information is there and you can always crop it.
  • Save the image data, the exact numbers you used to make the plot. Whenever you need to inspect it, load it in Matplotlib in interactive mode, navigate to your desired corner, and save it.
  • Use SVG: it is a vector graphics format, so you are not limited to pixels.

Here is how to use SVG:

import matplotlib
matplotlib.use('SVG')
import matplotlib.pyplot as plt

# Generate the image
plt.imshow(image, interpolation='none')
plt.savefig('output_image')

Edit:

To save a true SVG you need to use the SVG backend from the beginning, which is unfortunately, incompatible with interactive mode. Some backends, like GTKCairo seem to allow both, but the result is still rasterized, not a true SVG.

This may be a bug in matplotlib, at least, to the best of my knowledge, it is not documented.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top