Hi,
I am trying to figure out how to produce a mixed-mode rendering PDF of a
contourf plot.
I tried something like this:
>>> from pylab import meshgrid, sin, cos, linspace, contourf, savefig, clf
>>> x, y = meshgrid(*(linspace(-1,1,500),)*2)
>>> z = sin(20*x**2)*cos(30*y)
>>> c = contourf(x,y,z,30,rasterized=True)
>>> savefig('tst0.pdf')
but this does not work. (The QuadContourSet c does not support set_rasterized()
so the rasterized argument is just ignored. Is the ignoring of the argument a
bug or a feature?)
I tried calling set_rasterized() on all of the of PathCollection objects in
c.collections but this did not help:
>>> for pc in c.collections:
>>> pc.set_rasterized(True)
>>> savefig('tst1.pdf')
While this helps, there are still 30 rasterized patches which renders slowly as
a PDF.
I found one possible solution: make a custom Collection subclass as shown below,
then remove all of the PathCollection instances from the figure, inserting
instead this new collection as a single rasterized entity:
>>> insert(c) # See code below for definition of insert()
>>> savefig('tst2.pdf')
The file-sizes are:
$ ls -lah *.pdf
... 4.2M Aug 13 02:38 tst0.pdf
... 1.8M Aug 13 02:38 tst1.pdf
... 629K Aug 13 02:40 tst2.pdf
but tst2.pdf looks as good as tst1.pdf, and is much faster to load. (There are
some faint white lines between the patches similar to those discussed before:
http://thread.gmane.org/gmane.comp.python.matplotlib.devel/8540/focus=8590
but the rasterizer here is in the PDF backend, so maybe something can be done?
Should I look into this as a potential bug? I am using the version of
matplotlib included with the latest EPD on a 32 bit Mac.)
Question: Is there some way of doing this with current matplotlib API, or is
some sort of extension like this required? If the latter, is there anything I
should be careful about? (The ListCollection should probably be inserted in
contourf rather than retroactively like this.)
Thanks,
Michael.
···
-----------------------------------------------
from matplotlib.collections import Collection
from matplotlib.artist import allow_rasterization
from matplotlib import pyplot as plt
class ListCollection(Collection):
def __init__(self, collections, **kwargs):
Collection.__init__(self, **kwargs)
self.set_collections(collections)
def set_collections(self, collections):
self._collections = collections
def get_collections(self):
return self._collections
@allow_rasterization
def draw(self, renderer):
for _c in self._collections:
_c.draw(renderer)
def insert(c):
collections = c.collections
for _c in collections:
_c.remove()
cc = ListCollection(collections, rasterized=True)
ax = plt.gca()
ax.add_artist(cc)
return cc