3

for scientific conferences, the file size of papers is usually limited. I like to include my plots as pdfs, so text and lines stay crisp. When I create false colour plots or scatter plots with lots of data though, the exported pdf easily gets larger than the full paper is allowed to be.

Is there a way I could export only the axis area to bitmap, so I can include it in vector axes later? (or is there a better way to get a pdf with some elements embedded as bitmaps?)

I hope someone could help me here. As it's my first post, comments on how to improve my question are appreciated.

Roel
  • 197
  • 8
  • If you use `plt.imshow` with the `interpolation="none"` option to create your false-color plots, you should be able to achieve this. See also my related question: http://stackoverflow.com/questions/7346254/matplotlib-backend-differences-between-agg-and-cairo – David Zwicker May 31 '13 at 07:58

2 Answers2

6

You can tell individual Artists to be exported as rastered in vector output:

img = plt.imshow(...)
img.set_rasterized(True)

(doc)

tacaswell
  • 84,579
  • 22
  • 210
  • 199
  • 1
    Thanks! I also found that `fig.savefig('xxxxx.pdf')` also accepts a keyword argument to export in a sensible resolution, eg. `dpi=144`. I'm curious if your suggestion also works for `plt.pcolor`.. – Roel Jun 07 '13 at 22:51
  • `set_rastered` does not seem to work on pcolor. Maybe there is a similar function under anotehr name, but I don't seem to find it. – Roel Jun 07 '13 at 23:15
  • I believe it's supposed to be `set_rasterized(True)`. – sodd Jun 08 '13 at 09:12
  • @Roel nordev is right (which if you clicked through to the doc you would have seen) I apparently couldn't type when I answered this question. – tacaswell Jun 08 '13 at 15:35
  • Sorry about that, I overlooked the link :) Exactly what I needed, thanks! – Roel Jun 09 '13 at 14:17
0

I realised this workaround for a large scatter plot. It's not the least bit elegant, but it solves the issue for me. Recommendations on more elegant solutions are more than welcome ;)

    # -*- coding: utf-8 -*-
"""
Created on Sat Jun  1 17:21:53 2013

@author: roel
"""

import pylab as pl
from matplotlib._png import read_png


def bitmappify(ax, dpi=None):
    fig = ax.figure
    # safe plot without axes
    ax.set_axis_off()
    fig.savefig('bitmap.png', dpi=dpi, transparent=True)
    ax.set_axis_on()

    # remeber geometry
    xl = ax.get_xlim()
    yl = ax.get_ylim()
    xb = ax.bbox._bbox.corners()[:,0]
    xb = (min(xb), max(xb))
    yb = ax.bbox._bbox.corners()[:,1]
    yb = (min(yb), max(yb))

    # compute coordinates to place bitmap image later
    xb = (- xb[0] / (xb[1] - xb[0]),
        (1 - xb[0]) / (xb[1] - xb[0]))
    xb = (xb[0] * (xl[1] - xl[0]) + xl[0],
        xb[1] * (xl[1] - xl[0]) + xl[0])
    yb = (- yb[0] / (yb[1] - yb[0]),
        (1 - yb[0]) / (yb[1] - yb[0]))
    yb = (yb[0] * (yl[1] - yl[0]) + yl[0],
        yb[1] * (yl[1] - yl[0]) + yl[0])

    # replace the dots by the bitmap
    del ax.collections[:]
    del ax.lines[:]
    ax.imshow(read_png('bitmap.png'), origin='upper',
             aspect= 'auto', extent=(xb[0], xb[1], yb[0], yb[1]))

    # reset view
    ax.set_xlim(xl)
    ax.set_ylim(yl)

# create a plot
f, a = pl.subplots(1,1)
n = 1e4
a.scatter(pl.random(n)*2+6, pl.random(n)*3-12,
          c=pl.random(n), s=100*pl.random(n))

# safe as large pdf file for comparison
f.savefig('vector.pdf') # gives a large file: 3.8 MB

bitmappify(a, 144)

# save as smaller pdf
f.savefig('hybrid.pdf', dpi=144) # reasonably sized file: 0.5 MB
Roel
  • 197
  • 8