Makie: How to make a figure with exactly correct font size?

Hi all,

I’m using Makie to make figures for a publication and I want to be able to insert a figure (e.g., 6.5" by 3" figure) into word so that font size of my various labels is exactly correct (e.g., Ariel 11 that will match exactly Ariel 11 of my text) . This is important for me as journals often have specific requirement of font size to be no more than 8 or some other specific font requirement.

By default, it seems that font size in Makie changes depending on resolution so it is challenging to make a figure that can be inserted into word so that font sizes are correct.

Is there a way to make a figure using Makie that will have correct font sizes when inserted into word?

For example the following code:

using CairoMakie
scaler = 0.5
resolution = scaler .* (800,600)
fig=Figure(resolution=resolution)
ax = Axis(fig[1, 1], title="Figure", xlabel="xlabel", ylabel="ylabel")
lines!(ax,[1,2,3,4,5],[1,2,3,4,5], label="line")
fig

Produces this image with scaler =0.5:

Or this image with scaler = 1 with fonts of completely different size in proportion to figure:

I’ve read this but I don’t believe it answers my question: Exporting a Figure with physical dimensions

Actually never mind, I figured it out.
Turns out this link does explain it after all :grimacing:
If you make plots using svg graphics then font size is exact and you can save the image as png with any resolution.

For example to make 6.5" by 3" figure with fontsize 12:

using CairoMakie
CairoMakie.activate!(type = "svg")
size_inches = (6.5, 3)
size_pt = 72 .* size_inches
fig=Figure(resolution= size_pt, fontsize=12)
ax = Axis(fig[1, 1], title="Figure", xlabel="xlabel", ylabel="ylabel")
lines!(ax,[1,2,3,4,5],[1,2,3,4,5], label="line")
save("figure.png", fig, px_per_unit = 10)
#you can change px_per_unit to change resolution but relative sizes of font vs figure will stay the same.

EDIT: as pointed out by @jules, CairoMakie.activate!(type = "svg") actually doesn’t matter and as long as you set figure size (e.g., 6.5" by 3") using code below, paste the figure in word (or any text editor) and rescale it to exactly figure size (e.g., 6.5" by 3") then font will be exactly correct. You can also increase px_per_unit or pt_per_unit to increase resolution of your .png figure if it appears pixelated but that will not change the font size of image rescale to figure size (e.g., 6.5" by 3").

size_inches = (6.5, 3)
size_pt = 72 .* size_inches
2 Likes

Note that activate!(type="svg") only means that inline graphics will by default be displayed as svg. It does not change anything about how figures or resolutions behave. The same figure can be saved as svg, pdf or png and in that moment the units of font sizes, line widths, etc are solidified into whatever metric the backend uses, unit times pt_per_unit for svg and pdf and unit times px_per_unit for png.

Oh… you’re right. It actually doesn’t matter if I do activate!(type="svg") or activate!(type="png") or if I save as .pdf or .png.
So I guess my solution above works but activate!(type="svg") doesn’t matter contrary to what I assumed.

Would it be correct to say that as long as I set figure resultion as below (72 being the key) then everything will be correct font size regardless of any other things like activate!(type="svg"), activate!(type="png"), px_per_unit or pt_per_unit?

size_inches = (4, 3)
size_pt = 72 .* size_inches
fig=Figure(resolution= size_pt)

No, pt_per_unit in the save() call matters if you export to SVG or PDF. Its default value is 0.75 if I remember correctly, because in CSS 1px == 0.75pt. So if you want to treat your figure’s units as pt, you should make sure to use save(..., pt_per_unit = 1) (I’d have to check again if 0.75 is really the default).

The activation settings don’t matter for saving, just for inline display.

Hmmm… if I use the code below with pt_per_unit = 1 or pt_per_unit = 10 I get the same font size if I rescale .pdf to 6.5" width using illustrator so that suggests to me that that it doesn’t matter. The only difference is if I use pt_per_unit = 10 I basically get a figure with higher resolution but same font size if I paste it into word at 6.5" width image. Am I missing something?

using CairoMakie
CairoMakie.activate!(type = "png")
size_inches = (6.5, 3)
size_pt = 72 .* size_inches
fig=Figure(resolution= size_pt, fontsize=12)
ax = Axis(fig[1, 1], title="Figure", xlabel="xlabel", ylabel="ylabel")
lines!(ax,[1,2,3,4,5],[1,2,3,4,5], label="line")
save("figure.pdf", fig, pt_per_unit = 10)

But that’s exactly the effect that you’re undoing :slight_smile:

It’s like this:

linewidth = 1
px_per_unit = 1 => 1px
px_per_unit = 2 => 2px
pt_per_unit = 1 => 1pt
pt_per_unit = 2 => 2pt

Everything is scaled together, so the figure looks the same in vector format if you adjust the zoom level. That probably happens if you put it into Word, some sort of scaling. You could try looking at the two pdfs in a pdf viewer at fixed zoom scale, then you should see the difference.

If you do this:

text(..., fontsize = 12)
save("xxx.pdf", fig, pt_per_unit = 1)

Then the font will have fontsize 12pt and look perfect in a document with fontsize 12pt, but only if you paste the pdf into the word document at its correct physical size and not scaled.

Agreed.
By increasing px_per_unit or pt_per_unit I make the figure have more pixels but the relative proportions of all items are all same so if I rescale it to same size it will look more or less the same but figure with higher px_per_unit or pt_per_unit will have higher resolutin (ie be less pixelated) which might or might not be possible to see depending on image.

But if I change the 72 in code below that changes relative proportion of font size and image so even if I rescale to 6.5" by 3" the font will always be wrong size unless it is exactl 72 as described here

size_inches = (6.5, 3)
size_pt = 72 .* size_inches

Yes pt to inch conversion is fixed with 72, both are physical length metrics.

1 Like