JuliaPlots / Plots.jl

Powerful convenience for Julia visualizations and data analysis
https://docs.juliaplots.org
Other
1.83k stars 353 forks source link

New colorscheme for Plots.jl 2.0 #4966

Open isentropic opened 1 month ago

isentropic commented 1 month ago

@BeastyBlacksmith @t-bltg So I've been on search on new colorschemes and what we could choose. I think we should also update the color gradient while at it too. Upon hearing feedback I think we should settle with colorblind friendly scheme: https://juliagraphics.github.io/ColorSchemes.jl/stable/basics/#For-CVD-(color-vision-deficient-or-%22color-blind:)-users Upon which tol_bright looks good to me https://juliagraphics.github.io/ColorSchemes.jl/stable/basics/#For-CVD-(color-vision-deficient-or-%22color-blind:)-users looks good to ne

For the colorgradient, upon watching this and this setting viridis or some of the other 3 would be good in my opinion.

I'm hoping we could reach some consensus here

isentropic commented 1 month ago

These look really good as suggested by @cormullion esp the batlow gradient and catergorical if it is as good as advertised

BeastyBlacksmith commented 1 month ago

@cormullion can I also get the categorial palette of the scientific gradients somehow in ColorSchemes.jl?

BeastyBlacksmith commented 1 month ago

Its hard to judge without examples, so here is some code and pictures:

using StatsPlots
@userplot BackendPlot
@recipe function f(bp::BackendPlot; n = 4, colorgradient = :inferno)
           t = range(0, 3π, length = 100)
           d = rand(3, 3)

           plot_title := "p = $(plotattributes[:color_palette]), cg = $colorgradient"
           layout := n

           @series begin
               subplot := 1
               f = s -> -cos(s) * log(s)
               g = t -> sin(t) * log(t)
               f1 = s -> -cos(s) * log(s) + 5
               g1 = t -> sin(t) * log(t) + 5
               f2 = s -> -cos(s) * log(s) + 10
               g2 = t -> sin(t) * log(t) + 10
               linewidth --> 3
               [f g f1 g1 f2 g2]
           end

           @series begin
               subplot := 2 + (n > 2)
               RecipesBase.recipetype(:groupedbar, d)
           end

           if n > 2
               @series begin
                   subplot := 2
                   line_z := t
                   label := false
                   seriestype := surface
                   seriescolor := colorgradient
                   t, t, (x, y) -> x * sin(x) - y * cos(y)
               end

               @series begin
                   subplot := 4
                   seriestype := contourf
                   seriescolor := colorgradient
                   t, t, (x, y) -> x * sin(x) - y * cos(y)
               end
           end
       end

schemes = [:batlowW, :batlowK, :lipari, :navia, :imola, :devon, :lajolla, :bamako, :davos, :bilbao, :lapaz, :acton]

mkdir("plots_colors")
for scheme in fschemes
     savefig(backendplot(colorgradient = scheme, palette = :tol_bright), joinpath("plots_colors", "$scheme.png"))
end

lapaz acton navia lajolla imola devon davos lipari batlowK

BeastyBlacksmith commented 1 month ago

I like navia, lajolla, devon and lipari

cormullion commented 1 month ago

ColorSchemes.jl is very minimalist - the SVG swatches in the docs are drawn with Luxor.

Screenshot 2024-07-18 at 15 01 00
Code ```julia using Luxor, ColorSchemes function draw_scheme(schemename, pos=O; swatchwidth=800, swatchheight=20) @layer begin translate(pos) cols = colorschemes[schemename].colors setline(0.5) t = Tiler(swatchwidth, swatchheight, 1, length(cols), margin = 0) for (i, c) in enumerate(cols) sethue(c) box(t, i, :fillstroke) end sethue("white") text(string(schemename), Point(-swatchwidth/2 - 20, 0), halign=:right) end end schemes = [ :mpetroff_10, :tol_YlOrBr, :tol_land_cover, :tol_light, :mk_15, :mpetroff_6, :tol_ylorbr, :tol_PRGn, :tol_medcontrast, :tol_prgn, :okabe_ito, :tol_highcontrast, :ibm_cvd, :tol_BuRd, :mk_12, :tol_rainbow, :tol_muted, :tol_iridescent, :tol_bright, :tol_incandescent, :tol_vibrant, :tol_bu_rd, :tol_sunset, :mpetroff_8, :mk_8, :tol_nightfall, ] Drawing(650, 700, "/tmp/cs.svg") origin() background("#121212") translate(boxtopcenter() + (0, 30)) for cs in schemes draw_scheme(cs, swatchwidth=450) translate(0, 25) end finish() preview() ```

(I would use Plots.jl if I were a Plots.jl user. :))

I think seeing them in action -in a plot - is a good idea. But don't forget Dark Mode (like often happens)!

BeastyBlacksmith commented 1 month ago

ColorSchemes.jl is very minimalist - the SVG swatches in the docs

Thats not what I meant. On their homepage they have sequential continuous palettes, discrete palettes and categorial palettes. But in ColorSchemes.jl I can only find the first two.

isentropic commented 1 month ago

lajola looks great and inline with notion of heatmap (as in heat). tol_bright and lajola are a good candidate for the new default. Maybe we should see about this batlow and the categorical variant of it too

cormullion commented 1 month ago

@BeastyBlacksmith Ah, I’m with you now.

ColorSchemes.jl is mostly Crameri-v5.0 (ca 2020), with minor corrections. Incorporating the complete Crameri-v8.0 set wouldn’t be too much work - could be done by next week.

Version 3.26 includes the -S scientific schemes now - eg batlowS.

isentropic commented 1 month ago

batlowS looks weird in that the primary color isnt bright blue

image

https://juliagraphics.github.io/ColorSchemes.jl/stable/catalogue/#Color-Vision-Deficient-friendly-schemes :tol_bright looks good I like :tol_bright and :lajolla colors. I would also go one step further and recommend :managua usage for diverging colorschemes.

image

I also like :seaborn_colorblind as it resembles matplotlib default and would be more famliar to most users.

image

They also have other variants including gradients that look good. Link here too.

Overall seaborn colors and :tol_bright + scientific gradients both look good to me. I wouldn't mind having either of those. I'm slightly leaning toward seaborn as the look a little more conventional (close to matplotlib).

BeastyBlacksmith commented 1 month ago

I'm slightly leaning toward seaborn as the look a little more conventional (close to matplotlib).

I think, being distinct is a good thing.

I made some more examples for palettes using the gradients identified before:

tol_bright ![tol_bright_devon_black](https://github.com/user-attachments/assets/77fc4f78-beb7-477e-9c59-6cdb670263e7) ![tol_bright_devon_white](https://github.com/user-attachments/assets/1da2cec2-da44-4e97-a0f7-6d4afcfcf804) ![tol_bright_lajolla_black](https://github.com/user-attachments/assets/fa7f71f2-e6fc-4b11-a896-e5f0cdfe00b8) ![tol_bright_lajolla_white](https://github.com/user-attachments/assets/b09bf35c-6f79-4803-a7c6-c32411269b70) ![tol_bright_lipari_black](https://github.com/user-attachments/assets/c7c46e22-a8b8-4e77-8688-a067e302b161) ![tol_bright_lipari_white](https://github.com/user-attachments/assets/d1969e02-2685-4278-9417-679f17873085) ![tol_bright_navia_black](https://github.com/user-attachments/assets/ad61f8d2-1179-48e1-b962-1a01ec920df0) ![tol_bright_navia_white](https://github.com/user-attachments/assets/2338ff7b-6ef3-4ab0-94d2-38109f2d76ca)
tol_light ![tol_light_devon_black](https://github.com/user-attachments/assets/d747f7a5-e166-4aad-850c-7141f404b629) ![tol_light_devon_white](https://github.com/user-attachments/assets/9c86f80d-4295-4cb5-b96c-6ee34df076df) ![tol_light_lajolla_black](https://github.com/user-attachments/assets/f590b4bb-ff54-49aa-9846-5a41ec11c990) ![tol_light_lajolla_white](https://github.com/user-attachments/assets/817677c1-920c-4470-b6b4-677d0497c607) ![tol_light_lipari_black](https://github.com/user-attachments/assets/f2dc5202-038a-40bc-9445-17e528afe734) ![tol_light_lipari_white](https://github.com/user-attachments/assets/d0022556-abc4-4525-93a8-0fe304e28890) ![tol_light_navia_black](https://github.com/user-attachments/assets/50c90c23-5a0f-475c-9ed8-4187773fab5c) ![tol_light_navia_white](https://github.com/user-attachments/assets/2fdc63fd-e2cd-4eb1-973c-e90858a64072)
seaborn_colorblind ![seaborn_colorblind_devon_black](https://github.com/user-attachments/assets/bf20a700-4f0c-4501-b3be-6f14d41b4d05) ![seaborn_colorblind_devon_white](https://github.com/user-attachments/assets/3efadd9b-1494-4cc1-aea4-19a286a6fdab) ![seaborn_colorblind_lajolla_black](https://github.com/user-attachments/assets/a693062e-a852-4972-9d77-952ab307a332) ![seaborn_colorblind_lajolla_white](https://github.com/user-attachments/assets/cb5aee72-4965-407f-b827-a94966c207b0) ![seaborn_colorblind_lipari_black](https://github.com/user-attachments/assets/d236e0f7-d02e-4087-953b-81dc4911f8fb) ![seaborn_colorblind_lipari_white](https://github.com/user-attachments/assets/4292f558-085b-4651-bb6c-4d0728e3c42d) ![seaborn_colorblind_navia_black](https://github.com/user-attachments/assets/1a508b66-7d1a-41b0-a3ad-e29c0612c900) ![seaborn_colorblind_navia_white](https://github.com/user-attachments/assets/7408ef5b-9f0b-4ea3-9024-7ab0d1820eec)

There is something neat about having the same colors in gradient and palette, but this would possibly only work with batlow:

batlow ![batlowS_batlow_black](https://github.com/user-attachments/assets/7386809d-eb4c-4915-b345-1fd2ce92bd55) ![batlowS_batlowK_black](https://github.com/user-attachments/assets/515d0316-3365-47c8-9670-1a9412693b39) ![batlowS_batlowK_white](https://github.com/user-attachments/assets/2cae6922-f2f3-457d-99ec-866ae0f50b3b) ![batlowS_batlow_white](https://github.com/user-attachments/assets/b8f27acf-b835-495c-aef1-e17f3c0f7a62)
code ```julia using StatsPlots @userplot BackendPlot @recipe function f(bp::BackendPlot; n = 4, colorgradient = :inferno) t = range(0, 3π, length = 100) d = rand(3, 3) plot_title := "p = $(plotattributes[:color_palette]), cg = $colorgradient" layout := n @series begin subplot := 1 f = s -> -cos(s) * log(s) g = t -> sin(t) * log(t) f1 = s -> -cos(s) * log(s) + 5 g1 = t -> sin(t) * log(t) + 5 f2 = s -> -cos(s) * log(s) + 10 g2 = t -> sin(t) * log(t) + 10 linewidth --> 3 [f g f1 g1 f2 g2] end @series begin subplot := 2 + (n > 2) RecipesBase.recipetype(:groupedbar, d) end if n > 2 @series begin subplot := 2 line_z := t label := false seriestype := surface seriescolor := colorgradient t, t, (x, y) -> x * sin(x) - y * cos(y) end @series begin subplot := 4 seriestype := contourf seriescolor := colorgradient t, t, (x, y) -> x * sin(x) - y * cos(y) end end end schemes = [:lipari, :navia, :devon, :lajolla, :batlow, :batlowK] # mkdir("plots_colors") for (scheme, palette, background) in Iterators.product(schemes, [:tol_bright, :tol_light, :seaborn_colorblind, :batlowS], [:white, :black]) savefig(backendplot(colorgradient = scheme, palette = palette, bg = background), joinpath("plots_colors", "$(palette)_$(scheme)_$(background).png")) end ```
BeastyBlacksmith commented 1 month ago

but I think we narrowed the options enough, that I could make a poll on discourse