Description
Bug report
Bug summary
When transforming BoundingBox objects their width and height are calculated wrong. This happens, supposedly, for backends that have a different dpi setting from 72. The issue is present, e.g., for the backends "svg", "pdf", "cairo" (pdf, ps, svg). It is not present, e.g., for the backends "ps", "png".
Code for reproduction
# Plot BoundingBox of Text object with PS backend
import matplotlib as mpl
mpl.use("PS")
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
ax.plot([0, 1], [1, 0], "bo", ms=20)
text = ax.text(x=0.3, y=0.1, s="sample text", fontsize=20, family="Serif")
fig.savefig("bbox.ps")
bbox_display = text.get_window_extent()
bbox_data = bbox_display.inverse_transformed(ax.transData)
bbox_data_2 = ax.transData.inverted().transform_bbox(bbox_display)
print(f"bbox_display = {bbox_display}")
print(f" width = {bbox_display.width} height = {bbox_display.height}")
print(f"bbox_data = {bbox_data}")
print(f"bbox_data = {bbox_data_2}")
print(f" width = {bbox_data.width} height = {bbox_data.height}")
rect_data = mpl.patches.Rectangle(
(bbox_data.x0, bbox_data.y0), bbox_data.width, bbox_data.height,
fill=False, lw=0.2, color="g")
ax.add_patch(rect_data)
fig.savefig("bbox.ps")
# Try the same with PDF backend
import matplotlib as mpl
mpl.use("PDF")
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
ax.plot([0, 1], [1, 0], "bo", ms=20)
text = ax.text(x=0.3, y=0.1, s="sample text", fontsize=20, family="Serif")
fig.savefig("bbox.pdf")
bbox_display = text.get_window_extent()
bbox_data = bbox_display.inverse_transformed(ax.transData)
bbox_data_2 = ax.transData.inverted().transform_bbox(bbox_display)
factor = 100 / 72
print(f"bbox_display = {bbox_display}")
print(f" width = {bbox_display.width} height = {bbox_display.height}")
print(f"bbox_data = {bbox_data}")
print(f"bbox_data = {bbox_data_2}")
print(f" width = {bbox_data.width} height = {bbox_data.height}")
print(f" ~width = {bbox_data.width * factor} ~height = {bbox_data.height * factor}")
rect_data = mpl.patches.Rectangle(
(bbox_data.x0, bbox_data.y0), bbox_data.width, bbox_data.height,
fill=False, lw=0.2, color="r")
ax.add_patch(rect_data)
rect_data_corrected = mpl.patches.Rectangle(
(bbox_data.x0, bbox_data.y0), bbox_data.width * factor, bbox_data.height * factor,
fill=False, lw=0.2, color="g", ls="--")
ax.add_patch(rect_data_corrected)
fig.savefig("bbox.pdf")
Actual outcome
PS output
bbox_display = Bbox(x0=171.22909090909093, y0=70.14774999999999, x1=288.9634659090909, y1=89.50712499999999)
width = 117.734375 height = 19.359375
bbox_data = Bbox(x0=0.30000000000000004, y0=0.08281973379629631, x1=0.6626450842853944, y1=0.1628436053240741)
bbox_data = Bbox(x0=0.30000000000000004, y0=0.08281973379629631, x1=0.6626450842853944, y1=0.1628436053240741)
width = 0.3626450842853943 height = 0.08002387152777779
PDF output
bbox_display = Bbox(x0=237.8181818181818, y0=99.04374999999999, x1=355.5525568181818, y1=118.40312499999999)
width = 117.734375 height = 19.359375
bbox_data = Bbox(x0=0.30000000000000004, y0=0.0876302083333334, x1=0.5611044606854839, y1=0.1452473958333334)
bbox_data = Bbox(x0=0.30000000000000004, y0=0.0876302083333334, x1=0.5611044606854839, y1=0.1452473958333334)
width = 0.2611044606854839 height = 0.0576171875
~width = 0.36264508428539427 ~height = 0.08002387152777778
Expected outcome
I expect that the BoundingBoxes for both used backends have the same width and height in Axes coordinates. However, this is not the case. The BoundingBox in the PDF version can be transformed to the correct size via multiplication of its width and height by the factor 100 / 72. Therefore, I assume that the default dpi of the backends plays a role here and is not handled properly.
Matplotlib version
- Operating system: Ubuntu 19.04
- Matplotlib version: 3.1.1
- Matplotlib backends: PDF (but several more are affected)
- Python version: 3.7.4
- Jupyter version (if applicable): 1.0.0
- Other libraries:
Matplotlib was installed via conda.
Possibly related issues