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
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:
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.
3 thoughts on “Vector and raster in one with Matplotlib”
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!
Comments are closed.