Repository navigation
Description
I try to draw a circle in display coordinates around a point to avoid stretching when the axes are not equal. Using the pdf backend, the following code will give me a circle that is not centered on the point anymore:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import ipdb
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
# plot two points
ax.plot((0.2,0.7),(0.5,0.5), "o")
ax.set_xlim((0,1))
# get the display coordinates
x, y = ax.transData.transform((0.2,0.5))
# plot a circle around the point
circle = mpatches.Circle((x,y),50,fill=None)
# add to figure
fig.artists.append(circle)
# save to pdf - circle will not be centered on (0.2,0.5)
fig.savefig("displaced.pdf")
# save to pdf - circle will not be centered on (0.2,0.5)
fig.savefig("displaced.pdf", dpi=fig.dpi)
# save to png - circle will not be centered on (0.2,0.5)
fig.savefig("displaced.png")
# save to png - circle will be centered on (0.2,0.5)
fig.savefig("displaced.png", dpi=fig.dpi)
# show plot - circle will be centered
plt.show(block=True)The reason for this can be found inFigureCanvasPdf.print_pdf()
def print_pdf(self, filename, **kwargs):
image_dpi = kwargs.get('dpi', 72) # dpi to use for images
self.figure.set_dpi(72) # there are 72 pdf points to an inch
such that the input dpi will be ignored and the scaling will be off at some point. It seems like RendererPDF can handle arbitrary dpi, as it uses a scaling factor to 72dpi, and a change to
self.figure.set_dpi(image_dpi)
solved my problem. I'm not sure though if this is just a typo or a quick fix to some other problem that is not documented here. If someone can ok this, I will open a pull request.
\ Edit
I guess I missunderstood the idea behind this, since I just reverted any scaling altogether. Then I don't really know, why this is happening.
Activity
tacaswell commentedon Aug 12, 2014
@jkseppan Can you comment on this? I think 72 is a magic number in pdfs.
I think this is related to #2831.
jkseppan commentedon Aug 18, 2014
There's some earlier discussion here: http://thread.gmane.org/gmane.comp.python.matplotlib.devel/4306/
Yeah, 72 is just the number of PostScript points in an inch.
jkseppan commentedon Aug 18, 2014
The same seems to happen when saving to svg. I agree that it looks like #2831 is related.
jklymak commentedon May 10, 2018
Thanks to @ImportanceOfBeingErnest pointing this out on gitter:
jklymak commentedon May 10, 2018
The problem with the original code is that you cannot set the position in pixel co-ordinates and expect anything nice to happen when you print to vector backends because as you noted the dpi changes. Using the
fig.dpi_scale_transformdoes everything in inches, and the drawing changes as the dpi of the figure changes at draw and print time.jklymak commentedon May 10, 2018
Better as now the ellipse follows the data point under pan and zoom...