Vector images are great, except when they shouldn’t be vector. Figures with intricate detail can actually benefit from being rasterized. This can reduce file size and help the figure load more quickly. Python’s Matplotlib has an option to rasterize certain elements, but it doesn’t always work as simply as expected.
This post describes a function that (i) lets you rasterize any chosen elements when you export the figure and (ii) overcomes problems with the current implementation of rasterizing objects with Matplotlib.
How to rasterize in Matplotlib
For most plot types, it is as simple as including
rasterized=True
in the call to, say, pcolormesh or scatter. For example,
from numpy.random import randn N = 10000 plt.scatter(x=randn(N), y=randn(N), s=20*randn(N), rasterized=True)
The resolution of the rasterization is set by the dpi argument when saving:
plt.savefig('output.pdf', dpi=300)
Simplifying matters
Setting rasterized=True
does not always work as easily as you might expect. For example, filled contour plots (plt.contourf
) appear to ignore the setting and Basemap maps (m.fillcontinents
) don’t give the option. Furthermore, it would be simpler if we could specify which objects to rasterize when we export the figure as opposed to early in the code. For these reasons, I have developed a function entitled rasterize_and_save
that works much like plt.savefig
, but takes as an argument a list of objects to rasterize.
Consider an example containing various plot types. We want to rasterize all but the line plot.
from numpy.random import randn X, Y, Z = randn(9, 9), randn(9, 9), randn(9, 9) fig, axs = plt.subplots(ncols=2, nrows=2) (ax1, ax2), (ax3, ax4) = axs cax1 = ax1.contourf(Z) cax2 = ax2.scatter(X, Y, s=Z) cax3 = ax3.pcolormesh(Z) cax4 = ax4.plot(Z[:, 0]) rasterize_list = [cax1, cax2, cax3] rasterize_and_save('out.svg', rasterize_list, dpi=300)
All but the last two lines will be familiar to Matplotlib users. The penultimate line specifies which objects will be rasterized. The final line exports the figure as an svg image at a resolution of 300 dpi. Here’s the (annotated) result:
Keeping some of the panels as vector elements is as simple as changing the objects contained in rasterize_list
. Also, note how the contour plot is rasterized. This works because the rasterize_and_save
function does the hard work of changing the rasterized setting on each filled contour individually.
Thanks for posting this. However, how do you use this with other savefig keyword arguments? I’d like to include “bbox_inches = ‘tight'”; however, no approach I use allows this to be recognized. Thanks again!
The raster_and_save function includes an argument entitled savefig_kw that allows you to pass extra keyword options to savefig as a dict. In your case, you want something like raster_and_save(…, savefig_kw=dict(bbox_inches=’tight’))
Excellent, thanks. I realize I was slightly off in my syntax—everything works as expected!