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

Font family [u'Helvetica'] not found with PyPlot backend #593

Closed
anowacki opened this issue Nov 29, 2016 · 7 comments
Closed

Font family [u'Helvetica'] not found with PyPlot backend #593

anowacki opened this issue Nov 29, 2016 · 7 comments
Labels

Comments

@anowacki
Copy link
Contributor

When using PyPlot, on my system (OS X 10.11, Julia v0.5.0) I always get the following:

$ julia -e 'using Plots; pyplot(); plot(rand(10), show=true)'
/Users/nowacki/.julia/v0.5/Conda/deps/usr/lib/python2.7/site-packages/matplotlib/font_manager.py:1288: UserWarning: findfont: Font family [u'Helvetica'] not found. Falling back to Bitstream Vera Sans
  (prop.get_family(), self.defaultFamily[fontext]))

This is regardless of whether I use Python and Matplotlib from MacPorts, or after installing it locally with Conda.jl (via ENV["PYTHON"]=""; Pkg.build("PyPlot")).

I believe this occurs because the default font set by Plots.jl is Helvetica (in src/components.jl:242?), but PyPlot cannot find it. This is curious, though, because PyPlot on its own has no problem using Helvetica when set in ~/.matplotlib/matplotlibrc and called separately:

$ cat ~/.matplotlib/matplotlibrc 
font.sans-serif : Helvetica
$ julia -e 'using PyPlot; plot(rand(10))'

I can confirm that PyPlot is reading this file for defaults:

$ julia -e 'using PyPlot; println(PyPlot.matplotlib[:matplotlib_fname]())'
/Users/nowacki/.matplotlib/matplotlibrc

and that it's also true when using Plots:

$ julia -e 'using Plots; pyplot(); println(PyPlot.matplotlib[:matplotlib_fname]())'
/Users/nowacki/.matplotlib/matplotlibrc

Note that deleting ~/.matplotlib and trying the first command also causes problems, hence my suspicion that it is the way that Plots is setting the default font which causes issues.

Please let me know what else might help fix the issue. Having to use Bitstream Vera Sans is one of the few impediments to using Plots.jl in publications right now!

@tbreloff
Copy link
Member

I get this warning constantly and I've tried several times to figure out the source of the issue and every time I fail. I don't have time to spend on this, so help is greatly appreciated!

@anowacki
Copy link
Contributor Author

Understood. Can you point to any information about how to go about debugging this? I've struggled to follow the code path which is why I stopped where I did.

@ma-laforge
Copy link
Contributor

I have the same problem on Linux.

The Problem (part A)

The reason for this message is quite simple: matplotlib.font_manager does not support/recognize font Helvetica. If you want to see which fonts matplotlib supports, take a look at:

PyPlot.matplotlib[:font_manager][:findSystemFonts]()

... But this lists the file path/names of supported fonts. File paths only hint to what might be acceptable font family name. If you are looking for the default sans-serif font used by matplotlib, simply run (first remove your entry in matplotlibrc):

p=PyPlot.matplotlib[:font_manager][:FontProperties](family="sans")
p[:get_name]()

On my system, the family name is called "DejaVu Sans". You can see that matplotlib recognizes this as a family:

p=PyPlot.matplotlib[:font_manager][:FontProperties](family="DejaVu Sans")
p[:get_name]()

If you run the above using family="Helvetica": you get the familiar warning message.

The Problem (part B)
Plots.jl is trying to provide a consistent result, idependent of the backend.

@anowacki:
As you mentionned, it does so by defining "Helvetica" as the default font in src/components.jl.

Temporary Solution 1
You can hack Plots.jl/src/components.jl

function font(args...)

  # defaults
  #family = "Helvetica"
  family = "DejaVu Sans"
  [...]

... As long as you remember to restore the file before your next Pkg.update() - or Plots.jl will not update.

Temporary Solution 2
You can manually set all font families:

p = plot()
p.subplots[1][:titlefont].family = "DejaVu Sans"
[... not sure where all the other fonts are defined...]
plot!(rand(10), show=true)

Suggested solution
@tbreloff:
It would be nice if you could overwrite the default font family of the entire plot with a single keyword:

default(fontfamily="DejaVu Sans")

... But even this is a bit annoying to do for every new Julia session. I personally like it when my module can read in its defaults from a variable that can be defined in the ~/.juliarc.jl file. For example:

DEFAULTS_PLOTS = Dict(
	:fontfamily => "DejaVu Sans"
)

@tbreloff
Copy link
Member

tbreloff commented Jan 5, 2017

It would be nice if you could overwrite the default font family of the entire plot with a single keyword

This is closely related to #555. The solution would be handled similar to background/foreground colors... fontfamily would be a plot-wide default, and guidefontfamily would default to :match, meaning that it would use the value in fontfamily when unspecified. It'll just be tedious busy-work to do it.

anowacki added a commit to anowacki/Plots.jl that referenced this issue Jan 6, 2017
Rather than specifying a specific typeface, set the font
*family* in the `family` field of `Font` as `sans-serif`
by default.

Fixes JuliaPlots#593.
anowacki added a commit to anowacki/Plots.jl that referenced this issue Jan 6, 2017
Rather than specifying a specific typeface, set the font
*family* in the `family` field of `Font` as `sans-serif`
by default.

Fixes JuliaPlots#593.
@anowacki
Copy link
Contributor Author

anowacki commented Jan 6, 2017

Thanks, @ma-laforge, for the detective work. If I may summarise, this arises because Plots is using the family property for the wrong thing. It should be one of sans-serif, serif, cursive, fantasy(!) or monospace. It's not meant to be a specific typeface. See the following in the default .matplotlibrc file:

# The font.family property has five values: 'serif' (e.g., Times),
# 'sans-serif' (e.g., Helvetica), 'cursive' (e.g., Zapf-Chancery),
# 'fantasy' (e.g., Western), and 'monospace' (e.g., Courier).  Each of
# these font families has a default list of font names in decreasing
# order of priority associated with them.  When text.usetex is False,
# font.family may also be one or more concrete font names.

I've just submitted PR #635 to set this value to sans-serif by default, which for me now produces text using whichever font I have specified for font.sans-serif in my .matplotlibrc file (which, for reference, is Helvetica).

Also tested with GR and PlotlyJS backends to check they don't complain, which they seem not to.

@ma-laforge
Copy link
Contributor

No problem @anowacki.

Note, however, that it is not wrong to specify the family name as "Helvetica" (it appears that family is the proper designation for font name). The problem is simply that this font does not appear to be installed - or at least cannot be located by the font manager.

Although I do agree that it is probably a better idea to request a generic font family, like sans-serif, this is only a partial fix.

For one: some of the backends might not recognize these names: Technically, they are not real font family names - they are simply aliases. (Side note: it is possible that all backends supported by Plots.jl are ok with these aliases, though).

I personally have noticed issues with the default font families using Cairo in Windows 7:
JuliaGraphics/Cairo.jl#138

...So, at the end of the day: I still believe there should be a mechanism for the user to overwrite the default font family name.

@tbreloff
Copy link
Member

tbreloff commented Jan 8, 2017 via email

tbreloff added a commit that referenced this issue Jan 9, 2017
Use `sans-serif` as default font family (fix #593)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants