Nice fonts with Plots, GR and LaTeXStrings

This not a question, just something that might be helpful to others. With Plots 1.12 and GR0.57.4 (at least), and using these options below, one can get a plot with homogeneous fonts (“Computer Modern”) in every element.

using Plots
using LaTeXStrings

plot_font = "Computer Modern"
default(fontfamily=plot_font,
linewidth=2, framestyle=:box, label=nothing, grid=false)
scalefontsizes(1.3)

plot(sort(rand(10)),sort(rand(10)),label="Legend")
plot!(xlabel=L"\textrm{Standard text}(r) / \mathrm{cm^3}")
plot!(ylabel="Same font as everything")
annotate!(0.2,0.8,text("My note",plot_font,12))

savefig("./plot.pdf")


Previously
const plot_font = "Computer Modern"
const PLOTS_DEFAULTS = Dict(:theme=>:default,
:fontfamily => plot_font,
:linewidth => 2,
:framestyle => :box,
:label => "",
:grid => false)
using Plots
using LaTeXStrings

plot(sort(rand(10)),sort(rand(10)),label="Legend")
plot!(xlabel=L"\textrm{Standard text}(r) / \mathrm{cm^3}")
plot!(ylabel="Same font as everything")
annotate!(0.2,0.8,text("My note",plot_font,12))

savefig("./plot.pdf")



Additionally, some basic latex is good to know:

• \textm removes the math mode from a latex string.
• \mathrm removes the italics (not math mode) from the latex string, such that, for example, the exponent looks nicely placed in a non-italic string.

What I would like sometimes is to change everything to sffamily fonts. But that I was unable to do consistently yet.

29 Likes
using Unitful, Plots, Latexify, UnitfulRecipes, UnitfulLatexify
default(; # Plots defaults
fontfamily="Computer modern",
label="" # only explicit legend entries
)
set_default(; # Latexify defaults
#unitformat=:slash # in case you want m/s
)
x = rand(10)u"m"
v = x./(4u"s") .+ 0.3*randn(10)u"m/s"

plot(x, v; xguide="x", yguide="v", unitformat=latexify)
4 Likes

3 Likes

Note that it does not produce the correct placement for the exponent of the unit (the difference between using mathrm and textrm):

that example:

using \mathrm{ms^{-1}}:

(not that everyone needs to have obsessive compulsive disorder, though, but if you are a developer of that, maybe that is something to improve in the packages).

1 Like

It’s actually $v\;/\;\mathrm{m}\,\mathrm{s}^{-1}$ which I would consider the more correct behaviour.

Well, I don’t agree that produced the correct output there. Actually here all look the same, and correspond to what I think is the correct placement:

ms^{-1}: ms^{-1}

\mathrm{ms^{-1}}: \mathrm{ms^{-1}}

\mathrm{ms}^{-1}: \mathrm{ms}^{-1}

\textrm{ms}^{-1}: \textrm{ms}^{-1}

(in the plot above the -1 is clearly moved upwards).

Staring at them like this, I’m becoming more and more convinced they are both the wrong height.

Yes, that seems to be a bug in GR’s LaTeX rendering. Syntactically I still think your version is wrong, but I guess I could implement it in UnitfulLatexify as a workaround.

1 Like

In latex they all look the same to me:

thus, it is a rendering issue indeed in GR.

1 Like

Anyway, you made me notice that the default keyword is properly setting the fonts to all elements (that was not working in some previous version). Thus, the initial example can be made simpler:

using Plots
using LaTeXStrings

plot_font = "Computer Modern"
default(fontfamily=plot_font,
linewidth=2, framestyle=:box, label=nothing, grid=false)

plot(sort(rand(10)),sort(rand(10)),label="Legend")
plot!(xlabel=L"\textrm{Standard text}(r) / \mathrm{cm^3}")
plot!(ylabel="Same font as everything")
annotate!(0.2,0.8,text("My note",plot_font,12))

savefig("./plot.pdf")


I opened an issue here. It seems like the gull wings are to blame:

2 Likes

It would be nice if text would inherit the default font from default so that the last line could be simply
annotate!(0.2,0.8,text("My note",12))

2 Likes

@lmiq, thanks for this very useful post.
In case it might be of interest, the following example provides some additional formatting options:

using LaTeXStrings, Printf, Plots; gr()

plot_font = "Computer Modern";
default(fontfamily=plot_font,framestyle=:box, label=nothing, grid=false, tickfontsize=7)

u = 15  # persistent wind speed in m/s  (~30 knot)
st0 =  "Significant wave height vs persistent wind speed ("
st1 =  @sprintf(":  u = %i m/s → ", u)
st2 =  @sprintf(" = %.1f m", 0.24*u^2/9.8)
plot(title=L"\textbf{%$st0} \mathbf{H_s \approx 0.24 u^2/g} ) \textit{%$st1} {H_s} \textit{%$st2}", titlefont=font(8,plot_font)) plot!(ylims=(0,30))  To produce: 5 Likes Thanks @rafael.guerra This is very useful! 1 Like This example  using LaTeXStrings, Printf, Plots; gr() worked fine about 6 months ago but it doesn’t seem to work anymore. No problem with the pgfplotsx() backend though. Any clues? The problem is with the unicode arrow in julia> st1 ": u = 15 m/s → "  You can replace that with the actual latex symbol, like: julia> v = 15 15 julia> plot(rand(10),title=L"\textit{v = %$v m/s \rightarrow}")



1 Like

Well done @lmiq for the detective work.

NB: still a bit annoying and confusing that gr() doesn’t consume the unicode symbol of the right arrow anymore (also in text strings spaces need now to be replaced by ~)

They have been working on the LaTeX parser recently, leading to some regressions. You may want to open an issue there on GR.jl.

1 Like

Thank you for this. Any idea how I can change the font used by LatexStrings to Palladio? It’s what I use in my thesis, and I’d like to have the plots match that. Setting the font family in default() seems to affect Plots only, but not the LatexStrings labels.

This will be difficult to do. Depending on your backend, Plots uses Mathjax or a homebrew version thereof to render TeX strings (it doesn’t actually use the fact that your string is a LaTeXString, but rather the fact that LaTeXStrings include  automatically, so this is a question for Plots rather than LaTeXStrings).

For the Plotly and PlotlyJS backends, you can use a user-defined config file:
https://docs.juliaplots.org/latest/backends/#MathJax

which I guess could be used for this. but I don’t know MathJax, I saw someone say that the available fonts are limited anyway.

If this was an issue for me I would probably use the PGFPlots backend, so you’re actually leaving the rendering to LaTeX itself. If the compilation times get too large, you can add a recipe to your makefile to compile those image files to pdf before including them in the document.

2 Likes