Skip to content
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

[MNT]: pyplot.xkcd() leads to findfont errors under Windows #27350

Open
bkasel opened this issue Nov 20, 2023 · 9 comments
Open

[MNT]: pyplot.xkcd() leads to findfont errors under Windows #27350

bkasel opened this issue Nov 20, 2023 · 9 comments

Comments

@bkasel
Copy link

bkasel commented Nov 20, 2023

Summary

any plot with the xkcd style pyplot.xkcd() generates a bunch of errors from the findfont function under Windows even when fonts like "Comic Neue" are installed. I also regenerated the font cache and copied the font files into the matplotlib site-packages font folder, but this did not help. (I am using mpl 3.8.2 on python 3.11)

I am unsure if this is an issue under other OSs but I have the same issue under Win10 and Win11

Proposed fix

In the end I modified the pyplot.py file in the xkcd function, to get rid of the errors

    rcParams.update({
        'font.font-family': ['xkcd', 'xkcd Script', 'Comic Neue', 'Comic Sans MS'],
...

to

   rcParams.update({
       'font.sans-serif': ['xkcd', 'xkcd Script', 'Comic Neue', 'Comic Sans MS'],
...
@story645
Copy link
Member

I'd assume this would be due to #27339 but the only change there was removing humor sans.

@QuLogic
Copy link
Member

QuLogic commented Nov 21, 2023

I think this is older than that; the caching on the warning seems either very specific, or non-existent, as it seems to trigger at all draws (e.g., pan or resize, and a bunch of warnings are printed.)

@story645
Copy link
Member

or non-existent, as it seems to trigger at all draws

That's what I thought was going on w/ the findfont warning - is why I started #26602

Also I don't know if it's a windows specific thing, but I think I have to delete my fontcache to force a rebuild.

@StefRe
Copy link
Contributor

StefRe commented Nov 23, 2023

These warnings are caused by _find_fonts_by_props introduced in #20740 with matplotlib 3.6.0.

This function searches the complete list of font.family:

for family in prop.get_family():

implicitly assuming that all entries are family names. If this list also contains concrete font names, a warning will be issued if a font name is not found. Prior to v3.6.0, only the existing font files from the font cache were reviewed in _findfont_cached.

See the following example:

import matplotlib as mpl
import matplotlib.pyplot as plt

with mpl.rc_context({'font.family': ["monospace", "DejaVu Sans Mono", "Bitstream Vera Sans Mono"]}):
    fig = plt.figure()
    fig.text(0.4, 0.5, "mimi\nimim", size=40)

Starting with v3.6.0 it returns the warnings WARNING:matplotlib.font_manager:findfont: Font family 'Bitstream Vera Sans Mono' not found.. No warnings occurred up to v3.5.3.

So to fix this concrete issue it would indeed be sufficient to set font.family to 'sans-serif' (just in case it has been changed from the default before) and then set the list of concrete fonts to 'font.sans-serif' as @bkasel already found out. This doesn't address, however, the underlying root cause.

@story645
Copy link
Member

story645 commented Nov 24, 2023

If this list also contains concrete font names, a warning will be issued if a font name is not found.

My preference would be to allow font-names as part of finding family names (or control w/ a flag that defaults to permissive), what am I missing for why that's a bad idea?

@StefRe
Copy link
Contributor

StefRe commented Nov 24, 2023

My preference would be to allow font-names as part of finding family names (...), what am I missing for why that's a bad idea?

I didn't say that font.family must not contain concrete font names (sorry if I phrased that in a misleading way). On the contrary, I think it might be sufficient to just emit the warning only for font families, not for concrete fonts (but I didn't check yet if this completely restores the old behavior):

@@ -1367,7 +1367,7 @@ class FontManager:
                         "none of the following families were found: %s",
                         family, ", ".join(self._expand_aliases(family))
                     )
-                else:
+                elif family in ["serif", "sans-serif", "cursive", "fantasy", "monospace"]:
                     _log.warning("findfont: Font family %r not found.", family)

@story645
Copy link
Member

didn't say that font.family must not contain concrete font names

I think I'm the one who phrased things weird, I was just asking if we could expand find font family to not raise a warning if the font exists

@StefRe
Copy link
Contributor

StefRe commented Nov 24, 2023

... to not raise a warning if the font exists

I guess it should read "if the font doesn't exist". If the font exists then findfont will not raise and no warning will be issued. But I think that we're both talking about the same thing.

@story645
Copy link
Member

story645 commented Nov 24, 2023

But I think that we're both talking about the same thing.

Probably - what I'm getting at is basically that when it comes to not found error messages, we should be assuming something like this relation for the rcparams: $font.[serif, fantasy, etc] \subset font.family$

so that if updating $font.sans-serif$ doesn't raise a warning, than updating $font.family$ also shouldn't. I know technically $family \neq font$ but there are lots of places in our examples were we pass in a font to a family parameter so we're kinda using them interchangeably anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants