在展示结果时,其中重要的一步是为图选择一组合适的颜色或 colorbar。 Makie.jl
支持使用 Colors.jl ,因此你可以使用 named colors 而不是传递 RGB
或 RGBA
值。 另外,也可以使用 ColorSchemes.jl 和 PerceptualColourMaps.jl 中的颜色图。 值得了解的是,可以使用 Reverse(:colormap_name)
反转颜色图 ,也可以通过 color=(:red,0.5)
and colormap=(:viridis, 0.5)
获得透明的颜色或颜色图。
下文介绍不同的用例。 接下来使用新的颜色和颜色栏(Colorbar)调色盘来创建自定义主题。
默认情况下, Makie.jl
已经预定义一组颜色,可以循环使用该组颜色。 之前的图因此并未设置任何特定颜色。 覆盖这些默认颜色的方法是,在绘图函数中调用 color
关键字并使用 Symbol
或 String
指定新的颜色。 该操作如下所示:
function set_colors_and_cycle()
# Epicycloid lines
x(r, k, θ) = r * (k .+ 1.0) .* cos.(θ) .- r * cos.((k .+ 1.0) .* θ)
y(r, k, θ) = r * (k .+ 1.0) .* sin.(θ) .- r * sin.((k .+ 1.0) .* θ)
θ = LinRange(0, 6.2π, 1000)
axis = (; xlabel=L"x(\theta)", ylabel=L"y(\theta)",
title="Epicycloid", aspect=DataAspect())
figure = (; resolution=(600, 400), font="CMU Serif")
fig, ax, _ = lines(x(1, 1, θ), y(1, 1, θ); color="firebrick1", # string
label=L"1.0", axis=axis, figure=figure)
lines!(ax, x(4, 2, θ), y(4, 2, θ); color=:royalblue1, #symbol
label=L"2.0")
for k = 2.5:0.5:5.5
lines!(ax, x(2k, k, θ), y(2k, k, θ); label=latexstring("$(k)")) #cycle
end
Legend(fig[1, 2], ax, latexstring("k, r = 2k"), merge=true)
fig
end
set_colors_and_cycle()
这里通过color
关键字指定了上例前两条曲线的颜色。 其余使用默认的颜色集。 稍后将学习如何使用自定义颜色循环。
关于颜色图,我们已经非常熟悉用于热力图和散点图的 colormap
。下面展示的是,颜色图也可以像颜色那样通过 Symbol
或 String
进行指定。 此外,也可以是 RGB
颜色的向量。 下面是第一个例子,通过 Symbol
, String
和分类值的 cgrad
来指定颜色图。 输入 ?cgrad
查看更多信息。
figure = (; resolution=(600, 400), font="CMU Serif")
axis = (; xlabel=L"x", ylabel=L"y", aspect=DataAspect())
fig, ax, pltobj = heatmap(rand(20, 20); colorrange=(0, 1),
colormap=Reverse(:viridis), axis=axis, figure=figure)
Colorbar(fig[1, 2], pltobj, label = "Reverse colormap Sequential")
fig
当设置 colorrange
后,超出此范围的颜色值会被相应地设置为颜色图的第一种和最后一种颜色。 但是,有时最好自行指定两端的颜色。这可以通过 highclip
和 lowclip
实现:
using ColorSchemes
figure = (; resolution=(600, 400), font="CMU Serif")
axis = (; xlabel=L"x", ylabel=L"y", aspect=DataAspect())
fig, ax, pltobj=heatmap(randn(20, 20); colorrange=(-2, 2),
colormap="diverging_rainbow_bgymr_45_85_c67_n256",
highclip=:black, lowclip=:white, axis=axis, figure=figure)
Colorbar(fig[1, 2], pltobj, label = "Diverging colormap")
fig
另外 RGB
向量也是合法的选项。 在下面的例子中, 你可以传递一个自定义颜色图 perse 或使用 cgrad
来创建分类值的 Colorbar
。
using Colors, ColorSchemes
figure = (; resolution=(600, 400), font="CMU Serif")
axis = (; xlabel=L"x", ylabel=L"y", aspect=DataAspect())
cmap = ColorScheme(range(colorant"red", colorant"green", length=3))
mygrays = ColorScheme([RGB{Float64}(i, i, i) for i in [0.0, 0.5, 1.0]])
fig, ax, pltobj = heatmap(rand(-1:1, 20, 20);
colormap=cgrad(mygrays, 3, categorical=true, rev=true), # cgrad and Symbol, mygrays,
axis=axis, figure=figure)
cbar = Colorbar(fig[1, 2], pltobj, label="Categories")
cbar.ticks = ([-0.66, 0, 0.66], ["-1", "0", "1"])
fig
最后,分类值的颜色栏标签默认不在每种颜色间居中。 添加自定义标签可修复此问题,即 cbar.ticks = (positions, ticks)
。 最后一种情况是传递颜色的元组给 colormap
,其中颜色可以通过 Symbol
, String
或它们的混合指定。 然后将会得到这两组颜色间的插值颜色图。
另外,也支持十六进制编码的颜色作为输入。因此作为示范,下例将在热力图上放置一个半透明的标记。
figure = (; resolution=(600, 400), font="CMU Serif")
axis = (; xlabel=L"x", ylabel=L"y", aspect=DataAspect())
fig, ax, pltobj = heatmap(rand(20, 20); colorrange=(0, 1),
colormap=(:red, "black"), axis=axis, figure=figure)
scatter!(ax, [11], [11], color=("#C0C0C0", 0.5), markersize=150)
Colorbar(fig[1, 2], pltobj, label="2 colors")
fig
可以通过新的颜色循环定义全局 Theme
,但通常 不建议 这样做。 更好的做法是定义新的主题并像上节那样使用它。 定义带有 :color
, :linestyle
, :marker
属性的新 cycle
和默认的 colormap
。 下面为之前的 publication_theme
增加一些新的属性。
function new_cycle_theme()
# https://nanx.me/ggsci/reference/pal_locuszoom.html
my_colors = ["#D43F3AFF", "#EEA236FF", "#5CB85CFF", "#46B8DAFF",
"#357EBDFF", "#9632B8FF", "#B8B8B8FF"]
cycle = Cycle([:color, :linestyle, :marker], covary=true) # alltogether
my_markers = [:circle, :rect, :utriangle, :dtriangle, :diamond,
:pentagon, :cross, :xcross]
my_linestyle = [nothing, :dash, :dot, :dashdot, :dashdotdot]
Theme(
fontsize=16, font="CMU Serif",
colormap=:linear_bmy_10_95_c78_n256,
palette=(color=my_colors, marker=my_markers, linestyle=my_linestyle),
Lines=(cycle=cycle,), Scatter=(cycle=cycle,),
Axis=(xlabelsize=20, xgridstyle=:dash, ygridstyle=:dash,
xtickalign=1, ytickalign=1, yticksize=10, xticksize=10,
xlabelpadding=-5, xlabel="x", ylabel="y"),
Legend=(framecolor=(:black, 0.5), bgcolor=(:white, 0.5)),
Colorbar=(ticksize=16, tickalign=1, spinewidth=0.5),
)
end
然后将它应用到绘图函数中,如下所示:
function scatters_and_lines()
x = collect(0:10)
xh = LinRange(4, 6, 25)
yh = LinRange(70, 95, 25)
h = randn(25, 25)
fig = Figure(resolution=(600, 400), font="CMU Serif")
ax = Axis(fig[1, 1], xlabel=L"x", ylabel=L"f(x,a)")
for i in x
lines!(ax, x, i .* x; label=latexstring("$(i) x"))
scatter!(ax, x, i .* x; markersize=13, strokewidth=0.25,
label=latexstring("$(i) x"))
end
hm = heatmap!(xh, yh, h)
axislegend(L"f(x)"; merge=true, position=:lt, nbanks=2, labelsize=14)
Colorbar(fig[1, 2], hm, label="new default colormap")
limits!(ax, -0.5, 10.5, -5, 105)
colgap!(fig.layout, 5)
fig
end
with_theme(scatters_and_lines, new_cycle_theme())
此时,通过颜色,曲线样式,标记和颜色图,你已经能够 完全控制 绘图结果。 下一部分将讨论如何管理和控制 布局。