-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
PGF: Consistently set LaTeX document font size #26893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This could cause a mismatch between lengths when measuring vs. producing output for things that depend on the font size setting at the beginning of the document, e.g. unicode-math. Use \documentclass{article} without options here, which defaults to a font size of 10pt (same as the matplotlib rc default for font.size).
This allows the output .pgf file to be used in external documents with arbitrary font size settings (which should match the rc setting font.size). This avoids mismatches between matplotlib and external LaTeX documents for things that depend on the font size setting (e.g. unicode-math). If the LaTeX package scrextend is present, this also adjusts the standard LaTeX font commands (\tiny, ..., \normalsize, ..., \Huge) relative to font.size.
f44801a
to
d8ce139
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for opening your first PR into Matplotlib!
If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks.
You can also join us on gitter for real-time discussion.
For details on testing, writing docs, and our review process, please see the developer guide
We strive to be a welcoming and open project. Please follow our Code of Conduct.
Not sure what’s going on with the flake8 test thing – it doesn’t look like I changed anything about blank lines where it’s complaining. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good!
However, it may be worthwhile adding an image test to confirm that the new behavior is kept.
Also, it may be that one will need to install scrextend
in the CI to get it going (not sure if it is included in any standard distribution or not).
Finally, it may be helpful to add a note that this will work better if scrextend
is available. Maybe as an additional bullet at the end of https://github.com/matplotlib/matplotlib/blob/main/galleries/users_explain/text/pgf.py
(https://matplotlib.org/stable/users/explain/text/pgf.html)
Sounds like a good idea – I’ll get on that.
Either way, the use of
Not sure if this is necessary given the use of |
3a4a86e
to
ab50f7e
Compare
ab50f7e
to
4736de1
Compare
Then it should be fine I think! (Or rather, it would be nice that the required packages are explicitly stated somewhere, I may have missed it though, but this PR doesn't strictly add something to that.) |
@pwuertz Do you have bandwidth to review this? |
010af0d
to
0fec213
Compare
I’ve made the last requested change and rebased. So presumably it’s ready to merge? |
I think that the matplotlib/lib/matplotlib/texmanager.py Line 203 in eb62d69
|
Since |
Once again added all requested changes! |
Is there anything else that needs to be done? I don’t know what the codecov test is complaining about, nothing in there looks related to my changes. |
*([ | ||
r"\ifdefined\pdftexversion\else % non-pdftex case.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason for the change here and immediately below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s 14a5900. I guess it’s only tangentially related to the rest of this PR, but I noticed that \usepackage{fontspec}
was always included in the preamble, which is not necessarily desirable when doing custom font setup (i. e. pgf.rcfonts=False
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the ability to exclude \usepackage{fontspec}
is a very good improvement. It's sometimes necessary for consistency. From the documentation it sounds like fontspec
should only be used when pgf.rcfonts=True
, so this looks like an additional bugfix to me.
r" \%s{%s}[Path=\detokenize{%s/}]" | ||
% (command, path.name, path.parent.as_posix()) | ||
for command, path in zip( | ||
["setmainfont", "setsansfont", "setmonofont"], | ||
[pathlib.Path(fm.findfont(family)) | ||
for family in ["serif", "sans\\-serif", "monospace"]] | ||
) | ||
] if mpl.rcParams["pgf.rcfonts"] else []), | ||
r"\fi", | ||
] + [r"\fi"] if mpl.rcParams["pgf.rcfonts"] else []), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... i.e. here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
@@ -185,7 +205,7 @@ class LatexManager: | ||
@staticmethod | ||
def _build_latex_header(): | ||
latex_header = [ | ||
r"\documentclass{article}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these could have been left as they were originally (but removing the 12pt below) no? especially considering that we may want to make the documentclass configurable in the future, which would be more awkward to do if referencing a global.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean? These all have to be identical, so introducing a single name for them is just DRY. And in fact one of the first things one would do when making the documentclass configurable. I don’t see how it matters whether it’s a global constant or something else – that can always be changed with no effort. The point is to use a single variable for things that have to be the same.
) | ||
@pytest.mark.backend('pgf') | ||
@image_comparison(['pgf_document_font_size.pdf'], style='default', remove_text=True) | ||
def test_document_font_size(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- do you really need unicode-math for this test? I'd say it's not particularly relevant, no?
- you could do without the plot at all and simply use figtext() to draw text on an empty figure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Not
unicode-math
specifically, no. But if I remember correctly,unicode-math
(and other math font packages) select the font variant they use at package load time based on the document font size, and these variants have different metrics even for the same font size, which is what caused the original issue. So I’d either needunicode-math
or some random font package with the same behavior, andunicode-math
seems much more universal (especially since matplotlib already uses it by default). - I suppose I could. I just took the easiest path and used the example I already had in [Bug]: PGF font size mismatch between measurement and output #26892. Let me know if you really want me to make and test a new example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think I was mistaken with my comment that matplotlib uses unicode-math
(I was thinking of fontspec
). Nevertheless, the rest still applies.
I think this PR tries to fix too much. Isn't fixing the 12pt mismatch the only thing necessary to fix the original bug demonstrated by the code for reproduction? Everything else seems to target a slightly different bug (or bugs) that I do not know how to reproduce, but they sound to me like they might be solved by setting a custom Maybe I'm wrong, but I thought that the In other words, if the user could set the |
I really didn’t expect “tries to fix too much” on a PR that adds/changes 21 lines of code (excluding comments/tests/blanks)! I don’t know what you mean by “everything else” beyond adjusting the LaTeX font commands? Since there is currently no way to set the documentclass, Sure, making the documentclass configurable may be a better way to fix this than my (minimal!) change. Feel free to write that PR! |
@anntzer Do my answers resolve your review comments or do you want me to change anything about the PR? |
Yes, the "everything else" are the other font related changes (fixing a scope bug by defaulting to To be clear, I wasn't saying that the changes are bad or that they should not be merged. I actually think most are strong improvements and a dependency for a PR I'm currently writing too. I just did not fully understand the motivation behind the |
The following is a proof of concept of the possible consistency issue I mentioned: LaTeX source: \documentclass[12pt]{article}
\usepackage{pgf}
\begin{document}
\Huge Before
\input{plot.pgf}
\Huge After
\end{document} Python source: import matplotlib
matplotlib.use("pgf")
import matplotlib.pyplot as plt
# Set up PGF
matplotlib.rcParams.update({
"pgf.texsystem": "lualatex",
"font.family": "serif",
"text.usetex": True,
"pgf.rcfonts": False,
"font.size": 1,
"figure.autolayout": True,
"axes.labelsize": "xx-small",
})
# Create some sample data
x = [0, 1, 2, 3, 4]
y = [0, 0.2, 0.4, 0.1, 0.3]
# Create the plot
fig, ax = plt.subplots(figsize=(4.5, 3))
ax.plot(x, y)
ax.set_title("Sample Plot")
ax.set_xlabel(r"\Huge X")
ax.set_ylabel("Y")
# Save the plot
plt.savefig("plot.pgf")
plt.savefig("plot.png", dpi=300) I think the above example might demonstrate the problem I was alluding to. I use extremely big/small sizes to make the problem more obvious visually. The My recommended solution would be to leave the
I'm currently working on #28167 for this. |
Thank you @voidstarstar for your example. I agree we can't assume that the user will indeed be using koma-script just because it happens to be present in the install (if I understood the problem you're mentioning correctly). |
I think there is a lot of confusion going on here. First of all, Now, for @voidstarstar’s example: Of course, the assumption is that the user will set
How? matplotlib does not know anything about the user’s LaTeX file! That’s the whole point: Aligning the document font size used by the PGF backend with Now, I agree that the ideal solution for this problem would be for the user to be able to set the documentclass, at which point the code I’ve added which is setting the document font size could be removed. But I just wanted to fix the immediate problem to make things work by default, without workarounds in the custom preamble when making this PR! |
This seems like the core of my confusion. Please consider the following use case: A user is writing a LaTeX paper where the plots are somewhat small for space reasons due to journal imposed page limitations. The font size in the plots must be smaller than the document font size in order for the text to fit. By default, all of the text element sizes (
The 2nd half of my sentence mentions using
I agree. I'm personally not opposed to this as a temporary stepping stone solution. |
Setting the document font size doesn’t impair this use case at all. You can still set Let’s also keep in mind that you’d always have this problem with a hard-coded document font size (unless your document’s font size just happened to match the matplotlib-internal one), so I don’t see any alternative! |
That's a very good point, I agree. The hard-coded document font size is really the core issue, not your code. Your code at least has the benefit of allowing the user to set Sorry about the confusion, you are correct. I retract my example/problem mentioned above. This PR has my 👍 (for whatever that's worth). So it sounds to me like the best course of action would be:
|
@anntzer The problem I was mentioning was not really an issue with this PR, but rather an consequence of having a hard-coded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, this seems reasonable in any case and I'll trust @voidstarstar on the details.
PR summary
Currently, when using the PGF backend, different LaTeX document font size settings are used when measuring widths vs. producing output. Although this is usually not a problem (since all text produced by the PGF backend locally sets the font properties), packages used in the custom preamble (such as
unicode-math
) may depend on the font size settings, leading to incorrect width measurements since different outcomes are produced in the two cases. This fixes the issue by always setting the LaTeX font size to the rc settingfont.size
.Closes #26892.
PR checklist