Skip to content

Commit f127b63

Browse files
authored
Cheat sheet (#714)
Adds a cheat sheet built with Typst to the docs, to give a very condensed overview what common building blocks are available.
1 parent b599f97 commit f127b63

File tree

5 files changed

+336
-3
lines changed

5 files changed

+336
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ docs/package-lock.json
88
docs/src/changelog.md
99
.vscode/settings.json
1010
/scratch
11+
docs/cheatsheet.pdf

docs/Project.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
1414
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
1515
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1616
Shapefile = "8e980c4a-a4fe-5da2-b3a7-4b4b0353a2f4"
17+
Typst_jll = "eb4b1da6-20f6-5c66-9826-fdb8ad410d0e"
1718
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
1819
ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"
1920

21+
[sources]
22+
AlgebraOfGraphics = {path = ".."}
23+
2024
[compat]
2125
Documenter = "1"
2226
DocumenterVitepress = "0.2"
23-
24-
[sources]
25-
AlgebraOfGraphics = { path = ".." }
27+
Typst_jll = "0.14"

docs/cheatsheet.jl

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
using AlgebraOfGraphics
2+
using CairoMakie
3+
using Makie.Colors
4+
using Typst_jll
5+
6+
struct Typst
7+
s::String
8+
end
9+
10+
11+
to_typst(io::IO, v::AbstractVector) = foreach(v) do el
12+
to_typst(io, el)
13+
end
14+
15+
to_typst(io::IO, s::String) = print(io, s) # just simple, no escaping
16+
17+
function assetname!(io, ext)
18+
ref = get(io, :assetcounter, nothing)
19+
i = ref[]
20+
ref[] += 1
21+
path = "$i.$ext"
22+
return path
23+
end
24+
25+
function to_typst(io::IO, x::Union{Makie.Figure, Makie.FigureAxisPlot, AlgebraOfGraphics.FigureGrid})
26+
p = assetname!(io, "pdf")
27+
Makie.save(p, x)
28+
return print(io, "#image($(repr(p)))")
29+
end
30+
31+
struct SVG
32+
path::String
33+
end
34+
35+
function to_typst(io::IO, s::SVG)
36+
p = assetname!(io, "svg")
37+
cp(s.path, p)
38+
return print(io, "#image($(repr(p)))")
39+
end
40+
41+
"""
42+
render(x; pdf_path, png_path)
43+
44+
Render the cheatsheet document `x` to PDF and optionally PNG.
45+
If `pdf_path` is provided, the PDF will be saved there.
46+
If `png_path` is provided, a PNG preview will be saved there.
47+
"""
48+
function render(x; pdf_path = joinpath(@__DIR__, "cheatsheet.pdf"), png_path = nothing)
49+
assetcounter = Ref(0)
50+
return mktempdir() do dir
51+
cd(dir) do
52+
open("script.typ", "w") do io
53+
to_typst(IOContext(io, :assetcounter => assetcounter), x)
54+
end
55+
fontpath = Makie.assetpath("fonts")
56+
run(`$(typst()) compile script.typ --font-path $fontpath`)
57+
if png_path !== nothing
58+
run(`$(typst()) compile script.typ script.png --font-path $fontpath --ppi 150`)
59+
end
60+
end
61+
cp(joinpath(dir, "script.pdf"), pdf_path, force = true)
62+
if png_path !== nothing
63+
cp(joinpath(dir, "script.png"), png_path, force = true)
64+
end
65+
end
66+
end
67+
68+
makieyellow = colorant"#e8cb26"
69+
makieblue = colorant"#3182bb"
70+
makiered = colorant"#dd3366"
71+
72+
set_theme!(
73+
Axis = (;
74+
width = 35,
75+
height = 35,
76+
xticksvisible = false,
77+
yticksvisible = false,
78+
xticklabelsvisible = false,
79+
yticklabelsvisible = false,
80+
xautolimitmargin = (0.15, 0.15),
81+
yautolimitmargin = (0.15, 0.15),
82+
xlabelpadding = 0,
83+
ylabelpadding = 0,
84+
titlegap = 1,
85+
),
86+
Colorbar = (;
87+
labelpadding = 0,
88+
ticklabelsvisible = false,
89+
ticksvisible = false,
90+
spinewidth = 0,
91+
width = 5,
92+
),
93+
Legend = (;
94+
rowgap = 0,
95+
colgap = 0,
96+
padding = 1,
97+
patchlabelgap = 3,
98+
# nbanks = 2,
99+
titlegap = -2,
100+
patchsize = (6, 6),
101+
framevisible = false,
102+
tellheight = true,
103+
),
104+
colgap = 3,
105+
rowgap = 3,
106+
fontsize = 6 / 0.75,
107+
figure_padding = (2, 2, 2, 2),
108+
backgroundcolor = :transparent,
109+
linecolor = makiered,
110+
markercolor = makiered,
111+
markersize = 8,
112+
patchcolor = makiered,
113+
colormap = [makieblue, "gray90"],
114+
palettes = (;
115+
color = [makiered, makieblue, makieyellow],
116+
),
117+
)
118+
119+
macro vec(x)
120+
x isa String && return x
121+
@assert x isa Expr && x.head === :string
122+
return esc(Expr(:vect, x.args...))
123+
end
124+
125+
126+
datasets = """
127+
df_one = (A=[1,4,6,8], B=[2,6,4,5], C=[3,2,1,0], D=["a","b","c","d"])
128+
df_two = (E=repeat(["e","f"],inner=50), F=[randn(50);randn(50).+3])
129+
df_three = (G=1:30, H=sin.(range(0,2pi,30)).+rand.(), I=cos.(range(0,2pi,30)).+rand.())
130+
df_four = (J=repeat(1:3,3), K=repeat(1:3,inner=3), L=[0,1,2,0.5,2,4,1,4,5])
131+
df_five = (M=repeat(1:3,3), N=[0,2,3,0.5,3.5,5,1,5,7], O=repeat(["g","h","i"],inner=3))
132+
df_six = (P=1:4, Q=["A","B","A","B"], R=4:-1:1, S=[0.5,0.6,0.3,0.7], T=[5.1,3.9,2.7,1.5], U=[1,1,2,2])
133+
"""
134+
135+
eval(Meta.parseall(datasets))
136+
137+
function plottable(args...)
138+
@assert iseven(length(args))
139+
v = Any["#table(columns: 2, stroke: none, inset: 0pt, column-gutter: 5pt"]
140+
for (i, j) in Iterators.partition(args, 2)
141+
push!(
142+
v, ",[",
143+
i,
144+
"],table.cell(align: horizon, [",
145+
j,
146+
"])"
147+
)
148+
end
149+
push!(v, ")")
150+
return v
151+
end
152+
153+
block(title, content) = [
154+
"#block(fill: oklch(97%, 0.02, 0deg), inset: 0pt, radius: 4pt, clip: true, [#block(fill: oklch(92%, 0.04, 0deg), width: 100%, inset: 4pt, sticky: true)[*$title*]\n#block(inset: 4pt)[",
155+
content,
156+
"]])",
157+
]
158+
159+
logo = SVG(joinpath(@__DIR__, "src", "assets", "logo_with_text.svg"))
160+
161+
doc = [
162+
@vec(
163+
"""
164+
#set page(width: 297mm, height: 210mm, margin: 0.5cm)
165+
#set text(font: "Helvetica", size: 7pt)
166+
#show raw: set text(font: "Dejavu Sans Mono")
167+
168+
#table(
169+
columns: 3,
170+
inset: 0pt,
171+
column-gutter: (0pt, 10pt),
172+
stroke: none,
173+
align: horizon,
174+
box([$(logo)], height: 7em),
175+
table.cell(
176+
text(size: 3em, fill: gray, weight: "bold", style: "italic")[Cheat Sheet],
177+
),
178+
table.cell(block(raw($(repr(datasets))), fill: oklch(97%, 0.02, 270deg), inset: 4pt, radius: 4pt)),
179+
)
180+
181+
#columns(4, gutter: 1em)[
182+
"""
183+
),
184+
block(
185+
"`data(df_one) * mapping(:A, :B)`", plottable(
186+
data(df_one) * mapping(:A, :B) * visual(Scatter) |> draw,
187+
"`* visual(Scatter)`",
188+
data(df_one) * mapping(:A, :B, color = :C) * visual(Scatter) |> draw,
189+
"`* mapping(color=:C)\n* visual(Scatter)`",
190+
data(df_one) * mapping(:A, :B, color = :C) * visual(Scatter) |> draw(scales(Color = (; colormap = :plasma))),
191+
"`* mapping(color=:C)\n* visual(Scatter) |>\ndraw(scales(Color=(;colormap=:plasma))`",
192+
data(df_one) * mapping(:A, :B, color = :D) * visual(Scatter) |> draw,
193+
"`* mapping(color=:D)\n* visual(Scatter)`",
194+
data(df_one) * mapping(:A, :B, color = :D) * visual(Scatter) |> draw(scales(Color = (; palette = :Set1_5))),
195+
"`* mapping(color=:D)\n* visual(Scatter) |>\ndraw(scales(Color=(;palette=:Set1_5))`",
196+
data(df_one) * mapping(:A, :B) * visual(Lines) |> draw,
197+
"`* visual(Lines)`",
198+
data(df_one) * mapping(:A, :B) * visual(ScatterLines) |> draw,
199+
"`* visual(ScatterLines)`",
200+
data(df_one) * mapping(:A, :B) * visual(Stairs) |> draw,
201+
"`* visual(Stairs)`",
202+
data(df_one) * mapping(:D, :B) * visual(BarPlot) |> draw,
203+
"`* visual(BarPlot)`",
204+
data(df_one) * mapping(:D, :B) * visual(BarPlot, direction = :x) |> draw,
205+
"`* visual(BarPlot,direction=:x)`",
206+
data(df_one) * (mapping(:A, :B) * visual(Scatter, markersize = 5) + mapping(:A, :B, text = :D => verbatim) * visual(Makie.Text, align = (:center, :center))) |> draw,
207+
"`* mapping(text=:D=>verbatim)\n* visual(Makie.Text)`",
208+
data(df_one) * (mapping(:A, :B) * visual(Scatter, markersize = 5) + mapping(:A, :B, text = :D => verbatim) * visual(Annotation, color = :black)) |> draw,
209+
"`* mapping(text=:D=>verbatim)\n* visual(Annotation)`",
210+
)
211+
),
212+
block(
213+
"`data(df_one) * mapping(:A)`", plottable(
214+
data(df_one) * mapping(:A) * visual(HLines) |> draw,
215+
"`* visual(HLines)`",
216+
data(df_one) * mapping(:A) * visual(VLines) |> draw,
217+
"`* visual(VLines)`",
218+
)
219+
),
220+
block(
221+
"`data(df_two) * mapping(:E, :F)`", plottable(
222+
data(df_two) * mapping(:E, :F) * visual(Violin) |> draw,
223+
"`* visual(Violin)`",
224+
data(df_two) * mapping(:E, :F) * visual(Violin, orientation = :horizontal) |> draw,
225+
"`* visual(Violin,orientation=:horizontal)`",
226+
data(df_two) * mapping(:E, :F) * visual(BoxPlot, strokecolor = makiered, color = :white, strokewidth = 1, outliercolor = makiered, markersize = 5) |> draw,
227+
"`* visual(BoxPlot)`",
228+
data(df_two) * mapping(:E, :F) * visual(BoxPlot, orientation = :horizontal, strokecolor = makiered, color = :white, strokewidth = 1, outliercolor = makiered, markersize = 5) |> draw,
229+
"`* visual(BoxPlot,orientation=:horizontal)`",
230+
)
231+
),
232+
block(
233+
"`data(df_two) * mapping(:F)`", plottable(
234+
data(df_two) * mapping(:F) * histogram() |> draw,
235+
"`* histogram()`",
236+
data(df_two) * mapping(:F) * AlgebraOfGraphics.density() |> draw,
237+
"`* AoG.density()`",
238+
data(df_two) * mapping(:F) * visual(QQNorm, markersize = 3, qqline = :fit) |> draw,
239+
"`* visual(QQNorm)`",
240+
)
241+
),
242+
block(
243+
"`data(df_three) * mapping(:G, :H)`", plottable(
244+
data(df_three) * mapping(:G, :H) * (visual(Scatter, markersize = 2) + smooth()) |> draw,
245+
"`* smooth()`",
246+
data(df_three) * mapping(:G, :H) * (visual(Scatter, markersize = 2) + linear()) |> draw,
247+
"`* linear()`",
248+
data(df_three) * mapping(:H, :I) * (AlgebraOfGraphics.density() + visual(Scatter, markersize = 2)) |> draw,
249+
"`* AoG.density()`",
250+
)
251+
),
252+
block(
253+
"`data(df_four) * mapping(:J, :K, :L)`", plottable(
254+
data(df_four) * mapping(:J, :K, :L) * visual(Heatmap) |> draw,
255+
"`* visual(Heatmap)`",
256+
data(df_four) * mapping(:J, :K, :L) * contours(levels = 5) |> draw,
257+
"`* contours(bands=4)`",
258+
data(df_four) * mapping(:J, :K, :L) * filled_contours(bands = 4) |> draw,
259+
"`* filled_contours(bands=4)`",
260+
)
261+
),
262+
block(
263+
"`data(df_five) * mapping(:M, :N)`", plottable(
264+
data(df_five) * mapping(:M, :N, group = :O) * visual(Lines) |> draw,
265+
"`* mapping(group=:O)\n* visual(Lines)`",
266+
data(df_five) * mapping(:M, :N, color = :O) * visual(Lines) |> draw,
267+
"`* mapping(color=:O)\n* visual(Lines)`",
268+
data(df_five) * mapping(:M, :N, linestyle = :O) * visual(Lines) |> draw,
269+
"`* mapping(linestyle=:O)\n* visual(Lines)`",
270+
data(df_five) * mapping(:M, :N, marker = :O) * visual(ScatterLines) |> draw,
271+
"`* mapping(marker=:O)\n* visual(ScatterLines)`",
272+
data(df_five) * mapping(:M, :N, color = :O, dodge = :O) * visual(BarPlot) |> draw,
273+
"`* mapping(color=:O,dodge=:O)\n* visual(BarPlot)`",
274+
data(df_five) * mapping(:M, :N, color = :O, stack = :O) * visual(BarPlot) |> draw,
275+
"`* mapping(color=:O,stack=:O)\n* visual(BarPlot)`",
276+
data(df_five) * mapping(:M, :N, row = :O) * visual(Lines) |> draw(axis = (; width = 30, height = 15)),
277+
"`* mapping(row=:O)\n* visual(Lines)`",
278+
data(df_five) * mapping(:M, :N, col = :O) * visual(Lines) |> draw(axis = (; width = 15, height = 30)),
279+
"`* mapping(col=:O)\n* visual(Lines)`",
280+
data(df_five) * mapping(:M, :N, layout = :O) * visual(Lines) |> draw(axis = (; width = 20, height = 20)),
281+
"`* mapping(layout=:O)\n* visual(Lines)`",
282+
)
283+
),
284+
block(
285+
"`data(df_six)`", plottable(
286+
data(df_six) * (mapping(:P, :R) * visual(BarPlot) + mapping(:P, :R, :S) * visual(Errorbars, color = :black)) |> draw,
287+
"`* (mapping(:P,:R) * visual(BarPlot)\n+ mapping(:P,:R,:S) * visual(Errorbars))`",
288+
data(df_six) * (mapping(:P, :R) * visual(BarPlot) + mapping(:P, :R, :S, :S => x -> 2x) * visual(Errorbars, color = :black)) |> draw,
289+
"`* (mapping(:P,:R) * visual(BarPlot)\n+ mapping(:P,:R,:S,:S=>x->2x) * visual(Errorbars))`",
290+
data(df_six) * (mapping(:P, :R) * visual(BarPlot) + mapping(:P, :S, :T) * visual(Rangebars, color = :black)) |> draw,
291+
"`* mapping(group=:O)\n* visual(Lines)`",
292+
data(df_six) * (mapping(:U, :R, dodge = :Q, color = :Q) * visual(BarPlot) + mapping(:U, :R, :S, dodge_x = :Q) * visual(Errorbars, color = :black)) |> draw,
293+
"`* (mapping(:U,:R,dodge=:Q,color=:Q) * visual(BarPlot)\n+ mapping(:U,:R,:S,dodge_x=:Q) * visual(Errorbars))`",
294+
)
295+
),
296+
block(
297+
"Others", plottable(
298+
data(df_one) * mapping(:A, :B) * visual(Scatter) + mapping(2, 0.4) * visual(ABLines) |> draw,
299+
"`data(df_one) * mapping(:A,:B) * visual(Scatter) + mapping(2,0.4) * visual(ABLines)`",
300+
data(df_one) * mapping(:A, :B) * visual(Scatter) + mapping(-5, -17, 4, 6) * visual(Annotation, color = :black, text = "Here", shrink = (0, 5), style = Ann.Styles.LineArrow(head = Ann.Arrows.Line(length = 3))) |> draw,
301+
"`mapping(-5,-17,4,6) * visual(Annotation, text=\"Here\", style=Ann.Styles.LineArrow())`",
302+
)
303+
),
304+
"] // columns",
305+
]
306+
307+
function build_cheatsheet(; pdf_path = joinpath(@__DIR__, "cheatsheet.pdf"), png_path = nothing)
308+
return render(doc; pdf_path, png_path)
309+
end

docs/make.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ DocMeta.setdocmeta!(AlgebraOfGraphics, :DocTestSetup, :(using AlgebraOfGraphics)
88

99
cp(joinpath(@__DIR__, "..", "CHANGELOG.md"), joinpath(@__DIR__, "src", "changelog.md"), force = true)
1010

11+
module Cheatsheet
12+
@info "Building cheatsheet..."
13+
# VitePress serves files from the public folder at the site root
14+
publicpath = joinpath(@__DIR__, "src", "public")
15+
mkpath(publicpath)
16+
pdf_path = joinpath(publicpath, "cheatsheet.pdf")
17+
png_path = joinpath(publicpath, "cheatsheet.png")
18+
include(joinpath(@__DIR__, "cheatsheet.jl"))
19+
build_cheatsheet(; pdf_path, png_path)
20+
@info "Cheatsheet built successfully"
21+
end
22+
1123
makedocs(;
1224
modules = [AlgebraOfGraphics],
1325
authors = "Pietro Vertechi",

docs/src/index.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ hero:
2424

2525
AlgebraOfGraphics (AoG) defines a language for data visualization, inspired by the grammar-of-graphics system made popular by the R library [ggplot2](https://ggplot2.tidyverse.org/). It is based on the plotting package [Makie.jl](https://docs.makie.org/stable/) which means that most capabilities of Makie are available, and AoG plots can be freely composed with normal Makie figures.
2626

27+
## Cheat Sheet
28+
29+
````@raw html
30+
<a href="./cheatsheet.pdf" target="_blank" style="display: block; max-width: 20em;">
31+
<img src="/cheatsheet.png" alt="AlgebraOfGraphics Cheat Sheet" style="width: 100%; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
32+
</a>
33+
<p style="margin-top: 0.5em;"><a href="./cheatsheet.pdf" target="_blank">📄 Download Cheat Sheet (PDF)</a></p>
34+
````
35+
2736
## Example
2837

2938
In AlgebraOfGraphics, a few simple building blocks can be combined using `+` and `*` to quickly create complex visualizations, like this:

0 commit comments

Comments
 (0)