pythonmatplotlibcoordinatestransform

Making a poster: how to place Artists in a Figure using mm and top-left origin


I want to prepare a "portrait" A0 poster (841mm × 1189mm) placing different Artists (no Axes, but Rectangles and Texts) specifying their positions in mm from the top-left corner of the figure.

I have already figured out a possible procedure, e.g., if I want a rectangle, 40mm × 18mm, its top left corner positioned at (230mm, 190mm) from the top-left corner of the figure, I'd write

import matplotlib.pyplot as plt

fig = plt.figure(figsize(841/25.4, 25.4), layout='none')
fig.patches.append(plt.Rectangle((230, 190), 40, 18, transform=???))
# -------------------------------------------------------------///
fig.savefig('A0.pdf')

While I know that x_fig = x_mm/841 and y_fig = 1 - y_mm/1189I don't know how to define a proper transform to have the coordinates specified the way I'd like them.

How can I define a proper transform?


Solution

  • One option would be to scale the units to millimeters, then translate/flip the fig's "yaxis" :

    import matplotlib.pyplot as plt
    import matplotlib.transforms as mtransforms
    
    D = 300
    W, H = 120, 50
    # W, H = 841, 1189 # op
    
    mm = 1 / 25.4
    
    fig = plt.figure(figsize=(W * mm, H * mm), layout="none", dpi=D)
    
    rect = plt.Rectangle(
        (20, 15), 36, 20,
        # (230, 190), 400, 180, # op
        fc="springgreen", ec="k",
        transform=mtransforms.Affine2D()
        .scale(mm * fig.dpi).scale(1, -1)
        .translate(0, fig.get_figheight() * fig.dpi),
    )
    
    fig.patches.append(rect)
    
    # fig.savefig("A0.pdf", dpi=D) # invisible rectangle !
    # fig.savefig("A0.png", dpi=D) # works just fine !
    

    NB: The figure below uses a random paper-type (120x50) and a Ruler for clarity.

    enter image description here