5.5 Cores e mapas de cores

Escolher um conjunto apropriado de cores ou barra de cores para sua plotagem é uma parte essencial para apresentação de resultados. Colors.jl é suportado em Makie.jl para que você possa usar cores nomeadas ou passar valores RGB ou RGBA. Além disso, os mapas de cores ColorSchemes.jl e PerceptualColourMaps.jl também podem ser usados. Vale a pena saber que você pode reverter um mapa de cores fazendo Reverse(:colormap_name) para obter uma cor transparente ou mapa de cores com color=(:red,0.5) e colormap=(:viridis, 0.5).

Diferentes casos de uso serão mostrados a seguir. Então vamos definir um tema personalizado com novas cores e uma paleta de cores.

Por padrão Makie.jl tem um conjunto predefinido de cores para percorrê-las automaticamente. Conforme mostrado nas figuras anteriores, onde nenhuma cor específica foi definida. A substituição desses padrões é feita chamando a palavra-chave color na função de plotagem e especificando uma nova cor por meio de um Symbol ou String. Veja isso em ação no exemplo a seguir:

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()
Figure 21: Set colors and cycle.

Onde, nas duas primeiras linhas, usamos a palavra-chave color para especificar nossa cor. O resto está usando o padrão do conjunto de cores do ciclo. Mais tarde, aprenderemos como fazer um ciclo personalizado.

Em relação aos mapas de cores, já estamos familiarizados com a palavra-chave colormap para heatmaps e scatters. Aqui, mostramos que um mapa de cores também pode ser especificado por meio de um Symbol ou uma String, semelhante a cores. Ou até mesmo um vetor de cores RGB. Vamos fazer nosso primeiro exemplo chamando mapas de cores como Symbol, String e cgrad para valores categóricos. Cheque ?cgrad para mais informações.

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
Figure 22: Reverse colormap sequential and colorrange.

Ao definir um colorrange geralmente os valores fora deste intervalo são coloridos com a primeira e a última cor do mapa de cores. No entanto, às vezes é melhor especificar a cor desejada em ambas as extremidades. Fazemos isso com highclip e 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
Figure 23: Diverging Colormap with low and high clip.

Mas mencionamos que também vetores RGB são opções válidas. Para o nosso próximo exemplo, você pode passar o mapa de cores personalizado perse ou usar cgrad para forçar um Colorbar categórico.

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
Figure 24: Categorical Colormap.

Por fim, os tiques na barra de cores para o caso categorial não são centralizados por padrão em cada cor. Isso é corrigido passando ticks personalizados, como em cbar.ticks = (positions, ticks). A última situação é passar uma tupla de duas cores para o colormap como símbolos, strings ou uma mistura. Você obterá um mapa de cores interpolado entre essas duas cores.

Além disso, cores codificadas em hexadecimal também são aceitas. Então, no topo do nosso mapa de calor, vamos colocar um ponto semitransparente usando:

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
Figure 25: Colormap from two colors.

5.5.1 Ciclo personalizado

Aqui, poderíamos definir um Tema global com um novo ciclo de cores, mas essa não é a maneira recomendada de fazer isso. É melhor definir um novo tema e usar como mostramos antes. Vamos definir um novo com um cycle para :color, :linestyle, :marker e um novo padrão colormap. Vamos adicionar esses novos atributos ao nosso publication_theme anterior.

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

E aplique-o a uma função de plotagem como a seguinte:

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())
Figure 26: Custom theme with new cycle and colormap.

Neste ponto, você deve ter controle completo sobre suas cores, estilos de linha, marcadores e mapas de cores para seus plots. A seguir, veremos como gerenciar e controlar layouts.



CC BY-NC-SA 4.0 Jose Storopoli, Rik Huijzer, Lazaro Alonso