Trying to use computer modern roman (cmr10) font in plot. Getting an error which prevents minus sign rendering in plot.
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('font',family = 'serif', serif = 'cmr10')
fig, ax = plt.subplots()
ax.set_title('This is a special font:')
ax.set_xlabel(r'This is the default font $\alpha\beta\gamma$')
ax.set_yticks([-1,0,1])
plt.show()
Output:
C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py:214: RuntimeWarning: Glyph 8722 missing from current font.
font.set_text(s, 0.0, flags=flags)
C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py:183: RuntimeWarning: Glyph 8722 missing from current font.
font.set_text(s, 0, flags=flags)
Expected outcome
Correct rendering of symbols
Matplotlib version
Operating system: Cygwin / Windows10 Enterprise 64 Bit
Likely due to #14567? Seems reasonable to special case unicode minus to map to normal minus given that we already special case it for other purposes and also #16366, just needs to figure out what are the fonts that need that and can also do it correctly (not mapping to a dash).
# From UTF #25: U+2212 minus sign is the preferred
(of course we can still fix it...).
I'm extremely confused as to why using cmr causes an warning in a StixFonts instance, though (as can be checked by breakpoint()ing at the warning position) :/
Setting font as Computer Modern Roman (matplotlib.rcParams.update({'font.family': 'cmr10'})) results in negative signs in ticklabels not rendering. Oddly, negative signs in titles & labels render fine.
I looked a bit more into this. Fundamentally, the problem is that we are relying on the old computer modern fonts, where symbols (e.g. minus) and letters/digits are in different font files (cmr10/cmsy10); moreover the "standard" (non-mathtext) Text object is only able to use a single font file at a time (and it would be quite a big surgery to change that limitation).
Fortunately, when using mathtext, you can use multiple fonts at the same time; so one needs to force the ticks to use mathtext with rcParams["axes.formatter.use_mathtext"] = True, and then we're not done yet, because the ticker uses \mathdefault to wrap ticks, i.e. use the "non-mathtext" font... so then we need to add a special-case to mathtext, when using cmr10 as the non-mathtext font, to look up the minus sign in cmsy10 instead:
diff --git i/lib/matplotlib/mathtext.py w/lib/matplotlib/mathtext.py
index 8b9df7e19..8fdc29cad 100644
--- i/lib/matplotlib/mathtext.py+++ w/lib/matplotlib/mathtext.py@@ -842,6 +842,10 @@ class UnicodeFonts(TruetypeFonts):
found_symbol = False
font = self._get_font(new_fontname)
if font is not None:
+ if font.family_name == "cmr10" and uniindex == 0x2212:+ font = get_font(+ cbook._get_data_path("fonts/ttf/cmsy10.ttf"))+ uniindex = 0xa1
glyphindex = font.get_char_index(uniindex)
if glyphindex != 0:
found_symbol = True
(probably a real patch would need to add a comment there). Together with rcParams["axes.formatter.use_mathtext"] = True, I think this is the only reasonable short-term fix. Brownie points for whoever makes a PR out of this.
Long term I would like to get rid of the numerous cmXX10 fonts and replace them by the monolithic Latin Modern Math font, which should avoid all these problems. I guess that the cmr fonts shipped by Matplotlib should not be considered as "usable" for anything else than rcParams["mathtext.fontset"] = "cm" (using them for font.family will cause lots of trouble, like here); if you want to use CM for regular text consider just downloading Latin Modern Math (for example) and using that.
I was able to get rid of the RuntimeWarning by declaring the font usage with:
plt.rcParams["font.serif"] = "cmr10"
Hence:
import matplotlib.pyplot as plt
plt.rcParams["font.serif"] = "cmr10"
fig, ax = plt.subplots()
ax.set_title('This is a special font:')
ax.set_xlabel(r'This is the default font $\alpha\beta\gamma$')
ax.set_yticks([-1, 0, 1])
plt.show()
And, it continues to work despite the declaration of the yticks, as in:
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["font.serif"] = "cmr10"
fig, ax = plt.subplots()
ax.set_title('This is a special font:')
ax.set_xlabel(r'This is the default font $\alpha\beta\gamma$')
ax.set_yticks(np.arange(-1, 1.25, 0.25))
plt.show()
This also happens with the xkcd plotting style using the "Humor Sans" font.
So uh, this is why #26854 is failing (the plt.xkcd examples seem to work because they don't have a negative in the labels anywhere): throws "glyph missing" warning for title, omits hyphen for ticks:
Activity
anntzer commented on Apr 2, 2020
Likely due to #14567? Seems reasonable to special case unicode minus to map to normal minus given that we already special case it for other purposes and also #16366, just needs to figure out what are the fonts that need that and can also do it correctly (not mapping to a dash).
anntzer commented on Apr 3, 2020
Ah, actually that's not a regression, the unicode minus comes from
matplotlib/lib/matplotlib/mathtext.py
Line 63 in bb75f73
I'm extremely confused as to why using cmr causes an warning in a StixFonts instance, though (as can be checked by breakpoint()ing at the warning position) :/
roussel-ryan commented on Apr 3, 2020
Ok thank you for the effort! I'm not sure if I can do anything to help, but please let me know if there is
casperdcl commented on Jul 5, 2020
Same issue here.
Setting font as Computer Modern Roman (matplotlib.rcParams.update({'font.family': 'cmr10'})) results in negative signs in ticklabels not rendering. Oddly, negative signs in titles & labels render fine.
Code for reproduction
Detailscasperdcl commented on Sep 2, 2020
unfortunately the only workaround I could come up with is:
which is annoying since 'font.family': ('cmr10', 'STIXGeneral') should really work.
anntzer commented on Sep 2, 2020
I looked a bit more into this. Fundamentally, the problem is that we are relying on the old computer modern fonts, where symbols (e.g. minus) and letters/digits are in different font files (cmr10/cmsy10); moreover the "standard" (non-mathtext) Text object is only able to use a single font file at a time (and it would be quite a big surgery to change that limitation).
Fortunately, when using mathtext, you can use multiple fonts at the same time; so one needs to force the ticks to use mathtext with rcParams["axes.formatter.use_mathtext"] = True, and then we're not done yet, because the ticker uses \mathdefault to wrap ticks, i.e. use the "non-mathtext" font... so then we need to add a special-case to mathtext, when using cmr10 as the non-mathtext font, to look up the minus sign in cmsy10 instead:
(probably a real patch would need to add a comment there). Together with rcParams["axes.formatter.use_mathtext"] = True, I think this is the only reasonable short-term fix. Brownie points for whoever makes a PR out of this.
Long term I would like to get rid of the numerous cmXX10 fonts and replace them by the monolithic Latin Modern Math font, which should avoid all these problems. I guess that the cmr fonts shipped by Matplotlib should not be considered as "usable" for anything else than rcParams["mathtext.fontset"] = "cm" (using them for font.family will cause lots of trouble, like here); if you want to use CM for regular text consider just downloading Latin Modern Math (for example) and using that.
fix cmr10 negative sign in cmsy10
ehremington commented on Sep 14, 2020
This also happens with the xkcd plotting style using the "Humor Sans" font.
x = np.linspace(0,10,20) y = 2*x-3 with plt.xkcd(): fig = plt.figure() ax = fig.add_subplot() ax.plot(x,y)adiazmont commented on Sep 21, 2020
I was able to get rid of the RuntimeWarning by declaring the font usage with:
plt.rcParams["font.serif"] = "cmr10"
Hence:
import matplotlib.pyplot as plt plt.rcParams["font.serif"] = "cmr10" fig, ax = plt.subplots() ax.set_title('This is a special font:') ax.set_xlabel(r'This is the default font $\alpha\beta\gamma$') ax.set_yticks([-1, 0, 1]) plt.show()And, it continues to work despite the declaration of the yticks, as in:
import numpy as np import matplotlib.pyplot as plt plt.rcParams["font.serif"] = "cmr10" fig, ax = plt.subplots() ax.set_title('This is a special font:') ax.set_xlabel(r'This is the default font $\alpha\beta\gamma$') ax.set_yticks(np.arange(-1, 1.25, 0.25)) plt.show()Hope this helps!
jonas-eschle commented on Nov 10, 2020
Are there any news on this?
fix cmr10 negative sign in cmsy10
casperdcl commented on Nov 10, 2020
just rebased #18397
fix cmr10 negative sign in cmsy10
fix cmr10 negative sign in cmsy10
story645 commented on Oct 31, 2023
So uh, this is why #26854 is failing (the plt.xkcd examples seem to work because they don't have a negative in the labels anywhere): throws "glyph missing" warning for title, omits hyphen for ticks:
