Search code examples
pythonmatplotlibpdfcoordinate-transformation

I'm using a custom transformation, the PNG is OK but the PDF is empty


This question is a follow up to Making a poster: how to place Artists in a Figure using mm and top-left origin

This code:

import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D

mm, dpi = 1/25.4, dpi
w, h = 841, 1189
trans = Affine2D().scale(mm*dpi).scale(1,-1).translate(0,h*mm*dpi)

fig = plt.figure(figsize=(w*mm, h*mm), layout='none', dpi=dpi)
fig.patches.append(
    plt.Rectangle((230, 190), 40, 18, transform=trans))
fig.savefig('A0.pdf')
fig.savefig('A0.png')

produces an empty PDF, while the PNG file is correct.

Unfortunately the print shop with the wide inkjet plotter wants a PDF. While I could transform the raster file to PDF, I'd prefer to produce directly a correct PDF.

Is there something wrong in my code or it shouldn't happen and it's a bug I have to report to Matplotlib devs?


This code, that does not use the custom transformation, produces a correct PDF, with the rectangle in the correct position and the right dimensions.

import numpy as np
import matplotlib.pyplot as plt

mm, dpi = 1/25.4, 96
w, h = 841, 1189
fig = plt.figure(dpi=dpi, layout='none', figsize=(w*mm,h*mm))
fig.patches.append(plt.Rectangle((660/w, 1-1000/h), 40/w, -40/h,
                                 transform=fig.transFigure))
fig.savefig('A0.pdf')

UPDATE

...
fig = plt.figure(figsize=(w*mm, h*mm), layout='none', dpi=dpi)
fig.patches.append(
    plt.Rectangle((230, 190), 40, 18, transform=trans))
fig.patches.append(
    plt.Rectangle((600/w, 1-190/h), 40/w, -18/h, transform=fig.transFigure))
fig.savefig('A0.pdf')

produces a non empty PDF, but only the second rectangle, drawn w/o using the custom transformation, is visible.


Solution

  • If you ever find yourself plotting something and having to specify the dpi manually, you are going to have problems if you try and save at a different dpi. The correct way to do this so it is dpi invariant, but still in physical space, is:

    import matplotlib.pyplot as plt
    from matplotlib.transforms import Affine2D
    
    mm = 1.0/25.4
    w, h = 841.0, 1182.0
    fig = plt.figure(figsize=(w*mm, h*mm), layout='none')
    
    trans = Affine2D().scale(mm).scale(1,-1).translate(0,h*mm) + fig.dpi_scale_trans
    fig.patches.append(
        plt.Rectangle((230, 190), 40, 18, transform=trans))