randy.pubPersonal homepage |
Author | Randy Boyes | |
| Updated | |||
| Nav | Home Publications Resume Posts | ||
TidierPlots.jl has full support for Makie themes. For example:
using TidierPlots
using Random
using DataFrames
using Makie
Random.seed!(123)
n = 200
df = DataFrame(x = randn(n) / 2, y = randn(n))
plot1 = ggplot(df) +
geom_histogram(aes(x = :x),
color = (:orangered, 0.5),
strokewidth = 0.5) +
lims(x = c(-4, 4)) + theme_minimal() # theme_minimal is from Makie
// Image matching '/assets/posts/themes/code/themes_plot1' not found. //
Lets make this plot fit a little better with the monospace theme we've got going on this site. First - the most obvious change. We need to change the font.
juliamono = "https://cdn.jsdelivr.net/gh/cormullion/juliamono/webfonts/JuliaMono-Light.woff2"
randy_pub_theme = Theme(
fonts=(;regular=juliamono)
)
plot2 = ggplot(df) +
geom_histogram(aes(x = :x),
color = (:orangered, 0.5),
strokewidth = 0.5) +
lims(x = c(-4, 4)) + randy_pub_theme
// Image matching '/assets/posts/themes/code/themes_plot2' not found. //
The syntax looks a little funny if you're coming from R, so it's worth a little detour to talk about which elements can be used in themes, and how to pass them in. Makie themes can contain settings for the Attributes of any object. To change the font, we want to edit the "fonts" Attribute of the Figure which says it needs a "dictionary" that ties font styles (e.g. "regular") to fonts ("JuliaMono-Light"). I honestly don't know why it says it wants a dictionary and then demands a named tuple instead, but that's the way it works. For more info, see the explanation here.
Edits to the overall figure are done directly within the Theme call, while changes to "Blocks" are done within a "UppercaseBlockName = (tuple of Attributes)" argument to Theme. We're going to need to change a lot of options for Axis (whose Attributes are listed here in order to make this theme look right. Lets start by getting rid of the background and all of the axis lines except the bottom.
randy_pub_theme = Theme(
fonts=(;regular=juliamono),
backgroundcolor = :transparent,
Axis = (
backgroundcolor = :transparent,
leftspinevisible = false,
rightspinevisible = false,
topspinevisible = false,
xgridcolor = :transparent,
ygridcolor = :transparent,
)
)
plot3 = ggplot(df) +
geom_histogram(aes(x = :x),
color = (:transparent, 0.5), strokewidth = 1) +
lims(x = c(-4, 4)) + randy_pub_theme
// Image matching '/assets/posts/themes/code/themes_plot3' not found. //
Notice that there are two different calls to "background = :transparent". The one inside the Axis group makes the Axis background transparent, and the one at the base level makes the figure's background transparent.
Now we need to align the figure with the monospace grid.
randy_pub_theme = Theme(
fonts=(;regular=juliamono),
backgroundcolor = :transparent,
Axis = (
backgroundcolor = :transparent,
leftspinevisible = false,
rightspinevisible = false,
topspinevisible = false,
xgridcolor = :transparent,
ygridcolor = :transparent,
width = 468,
height = 365,
yticklabelpad = .25,
),
Hist = (strokewidth = 1, bins = 21)
)
plot3a = ggplot(df) +
geom_histogram(aes(x = :x),
color = (:transparent, 0.5), strokewidth = 1) +
lims(x = c(-4, 4), y = c(0, 30)) + randy_pub_theme
// Image matching '/assets/posts/themes/code/themes_plot3a' not found. //
We need to tweak the colors now for dark mode:
randy_pub_theme_dark = Theme(
fonts=(;regular=juliamono),
backgroundcolor = :transparent,
Axis = (
backgroundcolor = :transparent,
leftspinevisible = false,
rightspinevisible = false,
topspinevisible = false,
bottomspinecolor = :white,
xticklabelcolor = :white,
xtickcolor = :white,
yticklabelcolor = :white,
ytickcolor = :white,
xgridcolor = :transparent,
ygridcolor = :transparent,
width = 468,
height = 365,
yticklabelpad = .25
),
Hist = (strokecolor = :white, strokewidth = 1, bins = 21)
)
plot4 = ggplot(df) +
geom_histogram(aes(x = :x),
color = (:transparent, 0.5)) +
lims(x = c(-4, 4), y = c(0, 30)) + randy_pub_theme_dark
// Image matching '/assets/posts/themes/code/themes_plot4' not found. //
Success! There's lots more than can be done here but I'm happy with the basic look. We can also use a little html to swap out the theme based on user's dark mode setting: