Label padding around the axes depends on the length of the label when figure is saved as pdf.
The below code creates a figure and adds labels of different length. Those labels are not well aligned in the saved pdf version. Instead their padding towards the axes is depending on how many characters the label has. This issue is the more pronounced the larger the dpi (at constant figsize*dpi product).
The png files saved do not show this unexpected behaviour; all labels are aligned correctly. The expected output when saving the pdf file is of course the same as the png.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
a = np.random.rand(5,5)
for i in [1,1.25,1.5]:
plt.rcParams["axes.linewidth"] = i*0.1
fig = plt.figure(figsize=(i,i), dpi=int(500./i))
fig.subplots_adjust(0.44,0.44,0.56,0.56)
ax = fig.add_subplot(111)
ax.imshow(a)
ax.set_title("figsize {}, dpi {}".format((i,i), int(500./i)), size=i)
ax.set_yticklabels(["",1,10,100, "ABCDEFGH", "X"])
ax.set_xticklabels(["",1,10,100, "long long label", "short"])
ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(ticker.MultipleLocator(1))
ax.tick_params(axis='both', which='both', labelsize=i*0.5, length=i*0.5, width=i*0.05)
ax.tick_params(axis='x',which='both', rotation=90)
plt.savefig("fig_f{}.pdf".format(i))
plt.savefig("fig_f{}.png".format(i))
plt.show()
[reproduced with python 2.7, matplotlib 2.1, Qt4Agg backend as well as TkAgg backend]
The issue is with fontsize < 1. which it was in all your examples. In the PDF backend. Hard to get very worked up about cases where people want to plot fonts that are .35 mm high. Intellectually unsatisfying, but the easy solution is to make the figure bigger so the fonts can be larger than 1 pt.
changed the title [-]Labelpadding depends on label length in saved pdf file[/-][+]Alignment of labels incorrect if fontsize<1pt PDF backend[/+]on Dec 9, 2017
Is this a problem of the pdf rendering, not interpreting the positions correctly, or a problem of the pdf backend not setting those positions correctly?
I don't think the example is that pathological. You might want to create an image plot which has all points labeled and distribute it via pdf, such that the viewer may zoom into the pdf and see the labels, but that plot still having a defined size in inches (i.e. not to create a poster-size figure).
If you print, then it’s fine to render as a png. If you are looking at it on a screen then the figure size is arbitrary.
Yes this would be a nice bug to fix. I’m just not sure how high a priority it’ll get.
I have no idea if it’s a basic PDF limitation. It renders incorrectly in both Preview and Acrobat. It would be interesting to see if it happens in EPS and SVG.
I don't think we need to discuss the fact that it is often desired to create a pdf of predefined size. So I guess either it is possible to fix the issue or not, independent on whether everyone understands the use case of it.
It seems SVG is created just fine. So a possible workaround could be to convert svg to pdf outside of matplotlib. However I haven't found a way to do that (Inkscape seems to rasterize the pdf).
@anntzer 's suggestion to use cairo fails for me. The following image is the output from cairo matplotlib.use("Cairo") with cairocffi-0.8 installed.
On Sat, Dec 9, 2017 at 12:59 PM, Importance of Being Ernest < ***@***.***> wrote:
I don't think we need to discuss the fact that it is often desired to
create a pdf of predefined size. So I guess either it is possible to fix
the issue or not, independent on whether everyone understands the use case
of it.
It seems SVG is created just fine. So a possible workaround could be to
convert svg to pdf outside of matplotlib. However I haven't found a way to
do that (Inkscape seems to rasterize the pdf).
@anntzer <https://github.com/anntzer> 's suggestion to use cairo fails
for me. The following image is the output from cairo
matplotlib.use("Cairo") with cairocffi-0.8 installed.
[image: image]
<https://user-images.githubusercontent.com/23121882/33798030-1b65d7c4-dd12-11e7-954b-1a28c052b5f9.png>
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#9963 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-CjjdrJ6erMVtkGbrvlP7uxT1I2aks5s-spngaJpZM4Q7x26>
.
I tracked this all the way down into ft2font.cpp where it wasn't clear to me what happens. But what is happening here is that the width reported by font.get_width_height() of the text snippet stops decreasing when fontsize is less than 1. So the label gets put at the size=1.0 font x position:
@anntzer Does mplcairo output in PDF? I thought it was just an Agg replacement, but if it also puts all the vector outputs under one umbrella that seems very useful.
Edit: should have read the README. Answer = Yes.... Is there a roadmap to put this into the main repo at some point?
While this function allows fractional points as input values, the resulting ppem value for the given resolution is always rounded to the nearest integer.
If either the character width or height is zero, it is set equal to the other value.
If either the horizontal or vertical resolution is zero, it is set equal to the other value.
A character width or height smaller than 1pt is set to 1pt; if both resolution values are zero, they are set to 72dpi.
cairo natively outputs to raster/pdf/ps/svg so mplcairo is actually a replacement for all these backends (modulo a few features, I believe the only missing things are: URLs in svg (may possibly happen in the next cairo release, apparently), and use of the core 14 fonts just from the metrics and without embedding in pdf).
The plan to put this in the main repo is
merge Cairo rendering for Qt5 #8771 and cairo rendering for wx #9202 which cleanly separate the rendering and the windowing parts of qtagg and wxagg (I have a similar PR ready for tkagg but I'll wait until these are merged first, plus there are already enough open tk PRs lying around)
Oh, great, well at least the world is consistent. So do we try and work around this, or tell people who want to use unreadable fonts to readjust their expectations?
Interestingly the path (compile-time option) using libraqm (that handles right-to-left / complex layout languages) also has an issue with tiny fonts, but a different ones: the spaces between the glyphs are too big, although the texts are right-aligned correctly.
So is there a path to fix here? Throw a _log.info if the user tries to call font size <1 and maybe clip the PDF fontsize at 1 so at least it is rendered in the right spot, if at too large a size? If FreeType won't let us have fontsizes less than 1 pt, I don't see why we should jump through hoops to accommodate.
You could go the other route of trying to scale all the reported font dimensions by the <1 fontsize, but then you'd break the rendering for all the Agg/Cairo backends. That seems worse to me than restricting the scalability of the fontsize.
The "proper" solution is to get FreeType to change their routine. I am not sure why they don't allow small fontsizes.
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
Activity
jklymak commented on Dec 9, 2017
I can confirm this behaviour. Maybe some sort of roundoff issue w/ the PDF backend? But... those figure sizes are pretty pathological.
jklymak commented on Dec 9, 2017
The issue is with fontsize < 1. which it was in all your examples. In the PDF backend. Hard to get very worked up about cases where people want to plot fonts that are .35 mm high. Intellectually unsatisfying, but the easy solution is to make the figure bigger so the fonts can be larger than 1 pt.
jklymak commented on Dec 9, 2017
Here is the PDF... fig.pdf
ImportanceOfBeingErnest commented on Dec 9, 2017
Is this a problem of the pdf rendering, not interpreting the positions correctly, or a problem of the pdf backend not setting those positions correctly?
I don't think the example is that pathological. You might want to create an image plot which has all points labeled and distribute it via pdf, such that the viewer may zoom into the pdf and see the labels, but that plot still having a defined size in inches (i.e. not to create a poster-size figure).
anntzer commented on Dec 9, 2017
FWIW mplcairo renders this correctly :-)
jklymak commented on Dec 9, 2017
If you print, then it’s fine to render as a png. If you are looking at it on a screen then the figure size is arbitrary.
Yes this would be a nice bug to fix. I’m just not sure how high a priority it’ll get.
I have no idea if it’s a basic PDF limitation. It renders incorrectly in both Preview and Acrobat. It would be interesting to see if it happens in EPS and SVG.
ImportanceOfBeingErnest commented on Dec 9, 2017
I don't think we need to discuss the fact that it is often desired to create a pdf of predefined size. So I guess either it is possible to fix the issue or not, independent on whether everyone understands the use case of it.
It seems SVG is created just fine. So a possible workaround could be to convert svg to pdf outside of matplotlib. However I haven't found a way to do that (Inkscape seems to rasterize the pdf).
@anntzer 's suggestion to use cairo fails for me. The following image is the output from cairo matplotlib.use("Cairo") with cairocffi-0.8 installed.
WeatherGod commented on Dec 9, 2017
anntzer commented on Dec 9, 2017
https://github.com/anntzer/mplcairo
jklymak commented on Dec 10, 2017
I tracked this all the way down into ft2font.cpp where it wasn't clear to me what happens. But what is happening here is that the width reported by font.get_width_height() of the text snippet stops decreasing when fontsize is less than 1. So the label gets put at the size=1.0 font x position:
jklymak commented on Dec 11, 2017
@anntzer Does mplcairo output in PDF? I thought it was just an Agg replacement, but if it also puts all the vector outputs under one umbrella that seems very useful.
Edit: should have read the README. Answer = Yes.... Is there a roadmap to put this into the main repo at some point?
QuLogic commented on Dec 11, 2017
See these notes from FreeType's FT_Set_Char_Size which is used in set_size:
anntzer commented on Dec 11, 2017
cairo natively outputs to raster/pdf/ps/svg so mplcairo is actually a replacement for all these backends (modulo a few features, I believe the only missing things are: URLs in svg (may possibly happen in the next cairo release, apparently), and use of the core 14 fonts just from the metrics and without embedding in pdf).
The plan to put this in the main repo is
4 remaining items
jklymak commented on Dec 11, 2017
Oh, great, well at least the world is consistent. So do we try and work around this, or tell people who want to use unreadable fonts to readjust their expectations?
QuLogic commented on Dec 11, 2017
Well, I guess the question is how correct is mplcairo and how difficult it is to do whatever it is that it does to get it to work.
jklymak commented on Dec 11, 2017
OK, I can't reproduce the error in PNG:
EDIT: Oh, duh. I see. In PNG the font sizes never drop below 1 pt...
resulting png:
anntzer commented on Dec 13, 2017
Actually for mplcairo+pdf too the size plateaus at 1pt, not going lower. As noted by @QuLogic it's likely running into the same FreeType limitation.
I'm just calling cairo_scaled_font_text_to_glyphs, which does all the layouting: https://www.cairographics.org/manual/cairo-cairo-scaled-font-t.html#cairo-scaled-font-text-to-glyphs / https://github.com/anntzer/mplcairo/blob/master/src/_util.cpp#L537
Interestingly the path (compile-time option) using libraqm (that handles right-to-left / complex layout languages) also has an issue with tiny fonts, but a different ones: the spaces between the glyphs are too big, although the texts are right-aligned correctly.
jklymak commented on Dec 14, 2017
So is there a path to fix here? Throw a _log.info if the user tries to call font size <1 and maybe clip the PDF fontsize at 1 so at least it is rendered in the right spot, if at too large a size? If FreeType won't let us have fontsizes less than 1 pt, I don't see why we should jump through hoops to accommodate.
ImportanceOfBeingErnest commented on Dec 14, 2017
But why? At the moment you can use smaller font sizes. (As seen from this comment above)
Why would you break that?
jklymak commented on Dec 14, 2017
You can't use smaller fontsizes in the Agg or Cairo backends, and you can't position them properly in the PDF backend.
ImportanceOfBeingErnest commented on Dec 14, 2017
I guess I have to rethink what people mean by "scalable" when it comes to vectorgraphics.
jklymak commented on Dec 14, 2017
@ImportanceOfBeingErnest Any other options you had would be welcome.
You could go the other route of trying to scale all the reported font dimensions by the <1 fontsize, but then you'd break the rendering for all the Agg/Cairo backends. That seems worse to me than restricting the scalability of the fontsize.
The "proper" solution is to get FreeType to change their routine. I am not sure why they don't allow small fontsizes.
anntzer commented on Dec 14, 2017
Probably because font scaling is more complicated that just dilating or shrinking the whole thing (even for "scalable" fonts). See e.g. https://docs.google.com/document/d/1wpzgGMqXgit6FBVaO76epnnFC_rQPdVKswrDQWyqO1M/edit for a pretty good read (IMO).
github-actions commented on Apr 27, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
anntzer commented on Apr 27, 2023
I think this is essentially a limitation of freetype we're unlikely to work around.