From: Daniel H. <dh...@gm...> - 2010-08-23 02:00:45
|
I am searching for advice on how to handle selecting a specific font, and using that in a matplotlib figure. As a background, the font will be picked through the wx.FontDialog (common font dialog) provided by wxPython. So, what I will have is the font face (Arial, Times New Roman, Algerian, etc. etc.), the weight, the style (italic, normal) and the point size. All I want to do is create a matplotlib font that matches this, and use it in the plot. My first try was this: import matplotlib.pyplot as plt import matplotlib.font_manager as fm # this does not work. The title font is wrong. the_font = 'Century Schoolbook' fp = fm.FontProperties() fp.set_name(the_font) fp.set_size(24) plt.title('The Title that should be in Century Schoolbook',fontproperties=fp) print fp plt.show() But that didn't work. I know that "Century Schoolbook" is not really a font family, but in the docs it says that you can list a font there. The following does work, if I manually set the TrueType file explicitly: fp = fm.FontProperties() fp.set_file('c:\\Windows\Fonts\CENSCBK.TTF') fp.set_size(24) print fp plt.title('The Title that is in Century Schoolbook',fontproperties=fp) plt.show() So I guess the question is....how does one accomplish this, portably? I don't quite understand the ins and outs of fonts..... p.s. I did take a stab at creating a mapping between the font names / weights / styles like this: all_fontfiles = fm.win32InstalledFonts() allfonts = fm.createFontList(all_fontfiles) fontdict = {} for f in allfonts: fontdict[(f.name,f.style,f.weight)] = f.fname And I think I can get this to work, because this maps me to a TTF file for any name, style, and weight combination. But this seemed awfully hacky, and I don't know what problems I'll run into on other platforms (obviously, I would have get all_fontfiles above differently on each platform). If this is the only way to do it, I guess that's OK, but I thought that surely there was a better way. Thanks, -- Daniel Hyams dh...@gm... |
From: Michael D. <md...@st...> - 2010-08-23 14:12:25
|
On 08/22/2010 10:00 PM, Daniel Hyams wrote: > I am searching for advice on how to handle selecting a specific font, > and using that in a matplotlib figure. As a background, the font will > be picked through the wx.FontDialog (common font dialog) provided by > wxPython. So, what I will have is the font face (Arial, Times New > Roman, Algerian, etc. etc.), the weight, the style (italic, normal) > and the point size. All I want to do is create a matplotlib font that > matches this, and use it in the plot. My first try was this: > > import matplotlib.pyplot as plt > import matplotlib.font_manager as fm > > # this does not work. The title font is wrong. > the_font = 'Century Schoolbook' > fp = fm.FontProperties() > fp.set_name(the_font) > fp.set_size(24) > plt.title('The Title that should be in Century > Schoolbook',fontproperties=fp) > print fp > plt.show() > > But that didn't work. I know that "Century Schoolbook" is not really > a font family, but in the docs it says that you can list a font there. On my RHEL5 system (at least), the full name of that font is "Century Schoolbook L". You do, of course, have to match the font name exactly. You may want to experiment with using wx.Font.GetFaceName vs. wx.Font.GetFamilyString from the font chooser dialog and see if either returns the correct result. You can see the list of fonts that matplotlib found on your system by doing: from matplotlib import font_manager font_manager.fontManager.ttflist (This is not a public API -- but may help with debugging the issue here). Is the font you are hoping to match with in that list? Another thing you may want to try is deleting matplotlib's font cache, in case this font was installed after matplotlib was first run on your system. It is is in a file "fontList.cache" and lives in the user data area (can't remember the exact location of this on Windows off hand). > > The following does work, if I manually set the TrueType file explicitly: > > fp = fm.FontProperties() > fp.set_file('c:\\Windows\Fonts\CENSCBK.TTF') > fp.set_size(24) > print fp > plt.title('The Title that is in Century Schoolbook',fontproperties=fp) > plt.show() > > So I guess the question is....how does one accomplish this, portably? > I don't quite understand the ins and outs of fonts..... > > > p.s. > I did take a stab at creating a mapping between the font names / > weights / styles like this: > > all_fontfiles = fm.win32InstalledFonts() > allfonts = fm.createFontList(all_fontfiles) > fontdict = {} > for f in allfonts: > fontdict[(f.name <http://f.name>,f.style,f.weight)] = f.fname > > And I think I can get this to work, because this maps me to a TTF file > for any name, style, and weight combination. But this seemed awfully > hacky, and I don't know what problems I'll run into on other platforms > (obviously, I would have get all_fontfiles above differently on each > platform). If this is the only way to do it, I guess that's OK, but I > thought that surely there was a better way. That's basically a stricter way of doing what the matplotlib code already does. The matplotlib lookup is actually smarter because it handles approximate "nearest neighbor" matches. I think the problem is more likely one of the above (an inexact name match or an out-of-date font cache). Mike -- Michael Droettboom Science Software Branch Space Telescope Science Institute Baltimore, Maryland, USA |
From: Daniel H. <dh...@gm...> - 2010-08-23 15:08:35
|
Thanks for your response Michael! Deleting the fontList.cache indeed solved the problem. The first sample that I gave below now works fine under both Windows and Linux; whew...I would have never known about that cache file without your help. So, should the fontList.cache file be deleted each time my app runs, in case new fonts have been installed since the last invocation? How do we keep that cache up to date? On Mon, Aug 23, 2010 at 10:12 AM, Michael Droettboom <md...@st...>wrote: > On 08/22/2010 10:00 PM, Daniel Hyams wrote: > > I am searching for advice on how to handle selecting a specific font, and > using that in a matplotlib figure. As a background, the font will be picked > through the wx.FontDialog (common font dialog) provided by wxPython. So, > what I will have is the font face (Arial, Times New Roman, Algerian, etc. > etc.), the weight, the style (italic, normal) and the point size. All I > want to do is create a matplotlib font that matches this, and use it in the > plot. My first try was this: > > import matplotlib.pyplot as plt > import matplotlib.font_manager as fm > > # this does not work. The title font is wrong. > the_font = 'Century Schoolbook' > fp = fm.FontProperties() > fp.set_name(the_font) > fp.set_size(24) > plt.title('The Title that should be in Century > Schoolbook',fontproperties=fp) > print fp > plt.show() > > But that didn't work. I know that "Century Schoolbook" is not really a > font family, but in the docs it says that you can list a font there. > > On my RHEL5 system (at least), the full name of that font is "Century > Schoolbook L". You do, of course, have to match the font name exactly. > > You may want to experiment with using wx.Font.GetFaceName vs. > wx.Font.GetFamilyString from the font chooser dialog and see if either > returns the correct result. > > You can see the list of fonts that matplotlib found on your system by > doing: > > from matplotlib import font_manager > font_manager.fontManager.ttflist > > (This is not a public API -- but may help with debugging the issue here). > > Is the font you are hoping to match with in that list? > > Another thing you may want to try is deleting matplotlib's font cache, in > case this font was installed after matplotlib was first run on your system. > It is is in a file "fontList.cache" and lives in the user data area (can't > remember the exact location of this on Windows off hand). > > > The following does work, if I manually set the TrueType file explicitly: > > fp = fm.FontProperties() > fp.set_file('c:\\Windows\Fonts\CENSCBK.TTF') > fp.set_size(24) > print fp > plt.title('The Title that is in Century Schoolbook',fontproperties=fp) > plt.show() > > So I guess the question is....how does one accomplish this, portably? I > don't quite understand the ins and outs of fonts..... > > > p.s. > I did take a stab at creating a mapping between the font names / weights / > styles like this: > > all_fontfiles = fm.win32InstalledFonts() > allfonts = fm.createFontList(all_fontfiles) > fontdict = {} > for f in allfonts: > fontdict[(f.name,f.style,f.weight)] = f.fname > > And I think I can get this to work, because this maps me to a TTF file for > any name, style, and weight combination. But this seemed awfully hacky, and > I don't know what problems I'll run into on other platforms (obviously, I > would have get all_fontfiles above differently on each platform). If this > is the only way to do it, I guess that's OK, but I thought that surely there > was a better way. > > That's basically a stricter way of doing what the matplotlib code already > does. The matplotlib lookup is actually smarter because it handles > approximate "nearest neighbor" matches. I think the problem is more likely > one of the above (an inexact name match or an out-of-date font cache). > > Mike > > -- > Michael Droettboom > Science Software Branch > Space Telescope Science Institute > Baltimore, Maryland, USA > > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by > > Make an app they can't live without > Enter the BlackBerry Developer Challenge > http://p.sf.net/sfu/RIM-dev2dev > _______________________________________________ > Matplotlib-users mailing list > Mat...@li... > https://lists.sourceforge.net/lists/listinfo/matplotlib-users > > -- Daniel Hyams dh...@gm... |
From: Michael D. <md...@st...> - 2010-08-23 16:05:45
|
On 08/23/2010 11:08 AM, Daniel Hyams wrote: > Thanks for your response Michael! > > Deleting the fontList.cache indeed solved the problem. The first > sample that I gave below now works fine under both Windows and Linux; > whew...I would have never known about that cache file without your help. > > So, should the fontList.cache file be deleted each time my app runs, > in case new fonts have been installed since the last invocation? How > do we keep that cache up to date? The cache exists because it can take a long time to read through all of the font files on the system each time matplotlib is imported. It might be fast enough to simply stat the dates on all the files in the font directories (without reading their contents)... I don't know if experiments were done on this when the cache was originally added (that pre-dates me). Mike >> >> > On Mon, Aug 23, 2010 at 10:12 AM, Michael Droettboom <md...@st... > <mailto:md...@st...>> wrote: > > On 08/22/2010 10:00 PM, Daniel Hyams wrote: >> I am searching for advice on how to handle selecting a specific >> font, and using that in a matplotlib figure. As a background, >> the font will be picked through the wx.FontDialog (common font >> dialog) provided by wxPython. So, what I will have is the font >> face (Arial, Times New Roman, Algerian, etc. etc.), the weight, >> the style (italic, normal) and the point size. All I want to do >> is create a matplotlib font that matches this, and use it in the >> plot. My first try was this: >> >> import matplotlib.pyplot as plt >> import matplotlib.font_manager as fm >> >> # this does not work. The title font is wrong. >> the_font = 'Century Schoolbook' >> fp = fm.FontProperties() >> fp.set_name(the_font) >> fp.set_size(24) >> plt.title('The Title that should be in Century >> Schoolbook',fontproperties=fp) >> print fp >> plt.show() >> >> But that didn't work. I know that "Century Schoolbook" is not >> really a font family, but in the docs it says that you can list a >> font there. > On my RHEL5 system (at least), the full name of that font is > "Century Schoolbook L". You do, of course, have to match the font > name exactly. > > You may want to experiment with using wx.Font.GetFaceName vs. > wx.Font.GetFamilyString from the font chooser dialog and see if > either returns the correct result. > > You can see the list of fonts that matplotlib found on your system > by doing: > > from matplotlib import font_manager > font_manager.fontManager.ttflist > > (This is not a public API -- but may help with debugging the issue > here). > > Is the font you are hoping to match with in that list? > > Another thing you may want to try is deleting matplotlib's font > cache, in case this font was installed after matplotlib was first > run on your system. It is is in a file "fontList.cache" and lives > in the user data area (can't remember the exact location of this > on Windows off hand). > >> >> The following does work, if I manually set the TrueType file >> explicitly: >> >> fp = fm.FontProperties() >> fp.set_file('c:\\Windows\Fonts\CENSCBK.TTF') >> fp.set_size(24) >> print fp >> plt.title('The Title that is in Century >> Schoolbook',fontproperties=fp) >> plt.show() >> >> So I guess the question is....how does one accomplish this, >> portably? I don't quite understand the ins and outs of fonts..... >> >> >> p.s. >> I did take a stab at creating a mapping between the font names / >> weights / styles like this: >> >> all_fontfiles = fm.win32InstalledFonts() >> allfonts = fm.createFontList(all_fontfiles) >> fontdict = {} >> for f in allfonts: >> fontdict[(f.name <http://f.name>,f.style,f.weight)] = f.fname >> >> And I think I can get this to work, because this maps me to a TTF >> file for any name, style, and weight combination. But this >> seemed awfully hacky, and I don't know what problems I'll run >> into on other platforms (obviously, I would have get >> all_fontfiles above differently on each platform). If this is >> the only way to do it, I guess that's OK, but I thought that >> surely there was a better way. > That's basically a stricter way of doing what the matplotlib code > already does. The matplotlib lookup is actually smarter because > it handles approximate "nearest neighbor" matches. I think the > problem is more likely one of the above (an inexact name match or > an out-of-date font cache). > > Mike > > -- > Michael Droettboom > Science Software Branch > Space Telescope Science Institute > Baltimore, Maryland, USA > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by > > Make an app they can't live without > Enter the BlackBerry Developer Challenge > http://p.sf.net/sfu/RIM-dev2dev > _______________________________________________ > Matplotlib-users mailing list > Mat...@li... > <mailto:Mat...@li...> > https://lists.sourceforge.net/lists/listinfo/matplotlib-users > > > > > -- > Daniel Hyams > dh...@gm... <mailto:dh...@gm...> > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by > > Make an app they can't live without > Enter the BlackBerry Developer Challenge > http://p.sf.net/sfu/RIM-dev2dev > > > _______________________________________________ > Matplotlib-users mailing list > Mat...@li... > https://lists.sourceforge.net/lists/listinfo/matplotlib-users > -- Michael Droettboom Science Software Branch Space Telescope Science Institute Baltimore, Maryland, USA |