# Beautiful Makie Gallery

**URL:** <https://discourse.julialang.org/t/beautiful-makie-gallery/62523>\
**Category:** Package Announcements\
**Created:** [June 7, 2021, 2:29pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523 "2021-06-07T14:29:56Z")\
**Posts on this page:** 18\
**Page:** 5

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 13, 2021, 9:12pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/81 "2021-06-13T21:12:48Z")

</div>

There are some plots I don’t know how to make. A ridge plot is kind of 3D.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/9/5/9543fda164909faf7eea0d782af021d42fa53f1a.png)

[https://edav.info/ridgeline.html](https://edav.info/ridgeline.html)

---

<div class="post-metadata">

**Author:** ![lazarusA](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lazarusa/32/6571_2.png) [@lazarusA](https://discourse.julialang.org/u/lazarusA)\
**Post date:** [June 13, 2021, 9:22pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/82 "2021-06-13T21:22:16Z")

</div>

here in the documentation of makie, [http://makie.juliaplots.org/stable/plotting\_functions/density.html#Gradients](http://makie.juliaplots.org/stable/plotting_functions/density.html#Gradients)

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [June 13, 2021, 11:17pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/83 "2021-06-13T23:17:33Z")

</div>

Ternary plots in Makie would **so useful** for a class I am giving next quarter. If someone has the skills to implement it, that would be awesome.

---

<div class="post-metadata">

**Author:** ![EvoArt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evoart/32/25357_2.png) [@EvoArt](https://discourse.julialang.org/u/EvoArt)\
**Post date:** [June 14, 2021, 6:30am UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/84 "2021-06-14T06:30:34Z")

</div>

What type of ternary plots? Scatter and quiver plots are pretty easy to code up a function for to fit your own purposes. I have no idea how making proper axes works, so i don’t know about heatmaps and stuff that normally fills a rectangle. I’ve put together a 3d surface plot, to plot the density of (the proportions of) 3 random variables. But it’s a bit clunky e.g. axis ticks will need to be adjusted with any camera move.

 ![tern](https://global.discourse-cdn.com/julialang/original/3X/2/4/240f5892f6d605d1366d87a91195b7c68603ea8f.png)

```julia
using CairoMakie,KernelDensity, Distributions

#helper functions
tern_it(x,y)= [x + 0.5 * y,sqrt(0.75) * y]' # convert proportions to cartisian coords on a triangle
closest(a,b) = findmin(abs.(a .-b))[2]
set_dens(a,b,k) = k.density[closest(a,collect(k.x)),
     closest(b,collect(k.y))]

# generate data, convert it and get kernel density estimate
dat = rand(Dirichlet([2,1,0.5]),700)'
tern_dat =vcat(tern_it.(dat[:,1],dat[:,2])...)
ternKDE = kde(tern_dat)

# matrices f x and y points corresponding to triangle
myrange = collect(LinRange(-0.5,0.5,51))
fives = collect(LinRange(-0.5,0.5,51))
ys = hcat([collect(reverse(LinRange(0,1,51))) for i in 1:51]...) .* sqrt(0.75)
xs = vcat([myrange' .- fives' * i' for i in collect(reverse(LinRange(0,1,51)))]...) .+0.5
# z vales based on kernel density estimate
zs = set_dens.(xs,ys,fill(ternKDE,51,51))

# prep tick positions
uptick = [0.2,0.4,0.6,0.8] #.*sqrt(0.75)
sidetick = [0.2,0.4,0.6,0.8] .* 0.5 .- 0.1
lticks = Point.([(sidetick[i],uptick[i],-0.25) for i in 1:4])

# make the plot
f = Figure()
ax =Axis3(f[1,1])
# Draw axes
lines!(ax,[0,0.5,1,0],[0,sqrt(0.75),0,0],[0,0,0,0], color = :black)
#add ticks
annotations!(string.([0,0.2,0.4,0.6,0.8]), Point.([(0,-0.1,-0.25),
    (0.2,-0.1,-0.25),(0.4,-0.1,-0.25),(0.6,-0.1,-0.25),(0.8,-0.1,-0.25)]))
annotations!(string.([0.2,0.4,0.6,0.8]), lticks)
# plot the data
surface!(ax,(xs) ,ys , zs , color = zs, colormap = :jet)
wireframe!(ax,(xs ) ,ys , zs )
hidedecorations!(ax)
hidespines!(ax)
f

```

Incidentally, there are some white patches where I wouldn’t expect them given the elevation. Not sure if it’s a problem with my code or a lighting thing. Still new to Makie.

---

<div class="post-metadata">

**Author:** ![feanor12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/feanor12/32/8212_2.png) [@feanor12](https://discourse.julialang.org/u/feanor12)\
**Post date:** [June 14, 2021, 9:03am UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/85 "2021-06-14T09:03:21Z")

</div>

Ternary plots are used for example for [phase diagrams](https://serc.carleton.edu/research_education/equilibria/ternary_diagrams.html).

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 14, 2021, 9:17am UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/86 "2021-06-14T09:17:00Z")

</div>

Soil composition too

![image](https://global.discourse-cdn.com/julialang/original/3X/d/a/da1b3dcb300ff3b8af91781534249da427bc3e98.jpeg)

> **[REP-L.Santos%20Pereira-Geoderma-14.pdf](https://www.repository.utl.pt/bitstream/10400.5/13609/1/REP-L.Santos%20Pereira-Geoderma-14.pdf)**
>
> 2.88 MB

---

<div class="post-metadata">

**Author:** ![EvoArt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evoart/32/25357_2.png) [@EvoArt](https://discourse.julialang.org/u/EvoArt)\
**Post date:** [June 14, 2021, 9:59am UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/87 "2021-06-14T09:59:38Z")

</div>

Thanks both. I have my own uses as well, evolutionary game theory trajectories and density based visualisation of simulation results. I was just wondering what @juliohm specific use case is.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [June 14, 2021, 10:55am UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/88 "2021-06-14T10:55:13Z")

</div>

@EvoArt my use case is with compositional data: [GitHub - JuliaEarth/CoDa.jl: Compositional data analysis in Julia](https://github.com/JuliaEarth/CoDa.jl)

We need to plot contours of compositions, scatters and heatmaps basically.

---

<div class="post-metadata">

**Author:** ![feanor12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/feanor12/32/8212_2.png) [@feanor12](https://discourse.julialang.org/u/feanor12)\
**Post date:** [June 14, 2021, 3:20pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/89 "2021-06-14T15:20:11Z")

</div>

Maybe a line plot using a symlog scale would also be good to include.  
[https://matplotlib.org/stable/gallery/scales/symlog\_demo.html](https://matplotlib.org/stable/gallery/scales/symlog_demo.html)

---

<div class="post-metadata">

**Author:** ![EvoArt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evoart/32/25357_2.png) [@EvoArt](https://discourse.julialang.org/u/EvoArt)\
**Post date:** [June 14, 2021, 4:15pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/90 "2021-06-14T16:15:15Z")

</div>

Seems like there’s a fair bit of interest in ternary plots in Makie. Where’s the best place to discuss an implementation?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 14, 2021, 6:38pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/91 "2021-06-14T18:38:55Z")

</div>

you can add ideas to this [[Feature request] Ternary plots · Issue #906 · JuliaPlots/Makie.jl · GitHub](https://github.com/JuliaPlots/Makie.jl/issues/906)

---

<div class="post-metadata">

**Author:** ![lazarusA](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lazarusa/32/6571_2.png) [@lazarusA](https://discourse.julialang.org/u/lazarusA)\
**Post date:** [June 16, 2021, 4:36pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/92 "2021-06-16T16:36:27Z")

</div>

For those enthusiastic users, here a small challenge. The following was done with [Gnuplot.jl](https://github.com/gcalderone/Gnuplot.jl) (~ 10 lines of code). Could Makie do it? more or less with the same amount of lines. All the data is self contained in the image.

 ![astronautas3](https://global.discourse-cdn.com/julialang/original/3X/4/c/4c80d13862d6e5e907bdb9f25b0c04ee01bcae39.png)

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [June 16, 2021, 5:10pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/93 "2021-06-16T17:10:01Z")

</div>

Where is the Gnuplot.jl code for this one? (I think the figure only includes the data processing code).

---

<div class="post-metadata">

**Author:** ![lazarusA](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lazarusa/32/6571_2.png) [@lazarusA](https://discourse.julialang.org/u/lazarusA)\
**Post date:** [June 16, 2021, 5:13pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/94 "2021-06-16T17:13:45Z")

</div>

Indeed, I didn’t include the code for the figure. That will be too easy. Nevertheless, I will do it later. Now, I’m out, so no access to my laptop.

Ok. No, I was too generous with Gnuplot, is more than 10 lines (plus some auxiliary functions for the correct position of the text). Either way, here is the code (update version).

```julia
using Gnuplot, HTTP, CSV, Images, Suppressor
using Statistics, Colors, ColorSchemes
using DataFrames, DataFramesMeta
using Lazy: @>
import Gnuplot: PlotElement, DatasetText

data_url = "https://bit.ly/3kmlGn2"
@suppress begin
    global astronauts
    astronauts = CSV.File(HTTP.download(data_url)) |> DataFrame
end

offhr, rPts, α = 3.5, 40, 35
astro = @> begin
    astronauts
    @orderby(:year_of_mission)
    @where(:total_eva_hrs .> 0.0)
    @transform(ntotEVA = :total_eva_hrs/ maximum(:total_eva_hrs))
    @transform(θ = LinRange(0, 2π - 2π/length(:name), length(:name)))
    @transform(evaM = log10.((60 * :eva_hrs_mission/median(60 * :eva_hrs_mission)) .+ offhr))
    @transform(xM = rPts * :evaM .* cos.(:θ), yM = rPts * :evaM .* sin.(:θ))
    @transform(xMnm = rPts * (:evaM .- :total_number_of_missions .* :evaM./α) .* cos.(:θ))
    @transform(yMnm = rPts * (:evaM .- :total_number_of_missions .* :evaM./α) .* sin.(:θ));
end

tierra = "https://climate.nasa.gov/system/internal_resources/details/original/309_ImageWall5_768px-60.jpg"
@suppress begin
    global imgEarth
    tierra = HTTP.download(tierra)
    imgEarth = load(tierra);
end
x, y = astro.xM, astro.yM # end points
xs, ys = astro.xMnm, astro.yMnm # short lines starts
xo = yo = zeros(length(x)) # origin
xnb, ynb = 95 * cos.(astro.θ), 95 * sin.(astro.θ)
xne, yne = 110 * cos.(astro.θ), 110 * sin.(astro.θ)
ps, cp = 0.5 .+ 3astro.ntotEVA, astro.total_eva_hrs # point size, color palette
gridLines = LinRange(log10(offhr), maximum(astro.evaM), 6)
horas = (10 .^ gridLines .- offhr)*median(60*astro.eva_hrs_mission)/60
xg = [rPts * gl .* cos.(astro.θ) for gl in gridLines]
yg = [rPts * gl .* sin.(astro.θ) for gl in gridLines]
labM = "Duration of extravehicular activities during the mission in hours"
labT = "Total duration of all extravehicular activities in hours"

# Auxiliary functions
function segments(xs, xf, ys, yf, cp, ps; αc = "00", pal = :rainbow1)
    out = Vector{Gnuplot.PlotElement}()
    cpal = get(colorschemes[pal], cp, :extrema)
    for k in 1:length(xs)
        push!(out, PlotElement(data=DatasetText([xs[k], xf[k]], [ys[k], yf[k]]),
                               plot="w l not lc '#$(αc)$(hex(cpal[k]))' lw $(ps[k]) "))
    end
    out
end
function orot_text(θ; sdeg = 180) # θ in radians
    if (θ*sdeg/π) > (sdeg/2) && θ*(sdeg/π) < (sdeg/2 + sdeg)
        rot_θ = θ*sdeg/π - sdeg
        right_left = "right"
    else
        rot_θ = θ*sdeg/π
        right_left = "left"
    end
    rot_θ, right_left
end
function richtext(intext, r, θ; c = "#DFE6FF", fs = 10)
    x, y = r * cos.(θ), r *sin.(θ)
    tmp, current_text = "", " "
    for i in 1:length(intext)
        if current_text != intext[i]
            k = 1974 == intext[i] ? i-1 : i # due to a small overlap
            rot_θ, r_l = orot_text(θ[k])
            set_label = "set label '$(intext[i])' at $(x[k]), $(y[k])"
            frm_label = " font ',$(fs)' $(r_l) rot by $(rot_θ) front tc '$(c)'; " 
            tmp = tmp * set_label * frm_label
            current_text = intext[i]
        end
    end
    tmp
end
cmpal = :spring
bgrecta = "set obj rect from screen 0,0 to screen 1,1"
bgcolor = " behind fc 'black' fs solid noborder"
bgcolor = bgrecta * bgcolor
# the actual plot
@gp xrange = (-3.5rPts ,3.5rPts ) yrange = (-3.5rPts ,3.5rPts ) :- 
@gp :- "set size square" :-
@gp :- "set colorbox horiz user origin .65,.13 size .28,.01 " :-
@gp :- "set border lw 2 lc 'white'" "set tics font ',35' tc 'white'" :-
@gp :- "set cblabel '$(labT)' offset 0.0,-2 font ',45' tc 'white'"
@gp :- "unset border" "unset ytics" "unset xtics" :-
@gp :- recipe(RGBA.(imgEarth), "flipy rot=0deg center=(0,0) dx = 0.05 dy =0.05") :-
@gp :- x y ps cp "w p not pt 7 ps var lc palette" palette(cmpal) :-
@gp :- segments(xs, x, ys, y, cp, ps/2; αc = "00", pal = cmpal) :-
@gp :- segments(xo, xs, yo, ys, cp, ps/2; αc = "CC", pal = cmpal) :-
@gp :- segments(xnb, xne, ynb, yne, cp, ps/3; αc = "4D", pal = cmpal) :-
@gp :- richtext(astro.year_of_mission, 60, astro.θ; fs = 30) :-
@gp :- richtext(astro.mission_title, 75, astro.θ; fs = 13)
@gp :- richtext(astro.name, 95, astro.θ; fs = 14)
for (indx, gl) in enumerate(gridLines)
    xg, yg = rPts * gl .* cos.(astro.θ), rPts * gl .* sin.(astro.θ)
    hrs = Int64(round(horas[indx], digits = 0))
    set_hr = "set label '$(hrs)' at $(xg[1] + 0.5), $(y[1]+2) "
    frm_hr = " font ',32' front tc '#FFDD33'"
    @gp :- xg yg "w l lw 0.5 dt '._' lc 'white' not" :- 
    @gp :- set_hr * frm_hr :- 
end
@gp :- [21.76272, rPts + 17] [0,0] "w l lw 2 dt '._' lc '#FFDD33' not"
@gp :- "set label 'evaM' at 47,-2 font ',45' tc '#FFDD33'" :-
@gp :- "set label 'evaM = $(labM)' at graph 0.715,0.16 font ',45' tc '#FFDD33'" :-
@gp :- """set label "ASTRONAUTS' EXTRAVEHICULAR ACTIVITIES" at graph 0.3,0.9 font ',75' front tc '#DFE6FF' """ :- 
@gp :- """set label " Visualization by " at graph -0.18,0.1 font ',50' tc "white" """ :-
@gp :- """set label ' \\@LazarusAlon' at graph -0.18,0.1 font ',50' tc "#61AFEF" """ :-
@gp :- """set label " Data - Astronaut Database - Mariya Stavnichuk and Tatsuya Corlett" at graph -0.18,0.09 font ',30' tc "white" """ :-
@gp :- bgcolor
Gnuplot.save(term = "pngcairo enhanced size 7016,4960", output = "astronautas_alon_spring.png") # 4960 x 7016
# The font size apperance depends on the output size, which is not good (CairoMakie is better at doing that). 
# For pdf outputs is more stable but the file is bigger. 

```

```julia
Status `~/Documents/FunArt/astro/Project.toml`
  [336ed68f] CSV v0.8.4
  [35d6a980] ColorSchemes v3.11.0
  [5ae59095] Colors v0.12.6
  [a93c6f00] DataFrames v0.22.7
  [1313f7d8] DataFramesMeta v0.6.0
  [cd3eb016] HTTP v0.9.5
  [916415d5] Images v0.23.3
  [50d2b5c4] Lazy v0.15.1
  [fd094767] Suppressor v0.2.0
  [10745b16] Statistics

```

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 16, 2021, 9:25pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/95 "2021-06-16T21:25:34Z")

</div>

I was only motivated for half of it, but that’s how you could start:

```julia
# i added these at the top
@transform(align = tuple.(ifelse.(pi/2 .< :θ .< 3pi/2, ^(:right), ^(:left)), ^(:center)))
@transform(texttheta = ifelse.(pi/2 .< :θ .< 3pi/2, :θ .+ pi, :θ))

with_theme(theme_black()) do
    f = Figure(resolution = (1000, 1000))
    ax = Makie.Axis(f[1, 1],
        title = "ASTRONAUTS' EXTRAVEHICULAR ACTIVITIES",
        autolimitaspect = 1)
    hidespines!(ax)
    hidedecorations!(ax)

    image!(-20..20, -20..20, rotr90(imgEarth))

    n = nrow(astro)
    text!(astro.name, position = @.(Point(cos(astro.θ), sin(astro.θ)) * 80),
        rotation = astro.texttheta, textsize = 4, align = astro.align)

    vehicles = @chain astro begin
        @where([true; :ascend_shuttle[2:end] .!= :ascend_shuttle[1:end-1]])
    end

    text!(vehicles.ascend_shuttle, position = @.(Point(cos(vehicles.θ), sin(vehicles.θ)) * 50),
        rotation = vehicles.texttheta, textsize = 4, align = vehicles.align)

    limits!(ax, -100, 100, -100, 100)

    save("earth.png", f, px_per_unit = 4)
end

```

 ![earth](https://global.discourse-cdn.com/julialang/original/3X/f/b/fbdba1453d81c4c7ae1edbe681d8043e4bac85b3.jpeg)

---

<div class="post-metadata">

**Author:** ![lazarusA](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lazarusa/32/6571_2.png) [@lazarusA](https://discourse.julialang.org/u/lazarusA)\
**Post date:** [June 16, 2021, 9:30pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/96 "2021-06-16T21:30:22Z")

</div>

that’s actually all that I was missing… haha… the rest is the usual stuff. Nice :D. Here, my final Makie version. [https://lazarusa.github.io/BeautifulMakie/withTheme/theme\_dark\_astronauts/](https://lazarusa.github.io/BeautifulMakie/withTheme/theme_dark_astronauts/)

 ![theme_dark_astronauts](https://global.discourse-cdn.com/julialang/original/3X/f/2/f280db3bc733cef4aa4bdd3cd9e184cd4db66d40.png)

---

<div class="post-metadata">

**Author:** ![ConnectedSystems](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/connectedsystems/32/16815_2.png) [@ConnectedSystems](https://discourse.julialang.org/u/ConnectedSystems)\
**Post date:** [September 11, 2022, 9:49am UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/97 "2022-09-11T09:49:30Z")

</div>

Thanks, this was very helpful.

Here’s my initial attempt for the latest version of GLMakie.

Only a single color at the moment, and need to show upper/lower values too, but it’s a start.

```julia
"""
Parallel Coordinate Plot

# Arguments
- disp : Axis
- data : Matrix
- names : Vector or Tuple of names (for x-axis)
"""
function pcp!(disp, data, names)
    k, n = size(data)
    limits = extrema.(eachcol(data))

    scaled = hcat([(d .- mi) ./ (ma - mi) for (d, (mi, ma)) in zip(eachcol(data), limits)]...)

    vlines!(disp, 1:n; color=:black)
    for i in 1:k
        lines!(disp, scaled[i, :], color=(:blue, 0.1))
    end

    disp.xticks = (1:n, [string.(names)...])

    return disp
end

```

---

<div class="post-metadata">

**Author:** ![Edward\_Montague](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/edward_montague/32/28803_2.png) [@Edward\_Montague](https://discourse.julialang.org/u/Edward_Montague)\
**Post date:** [July 23, 2023, 9:36pm UTC](https://discourse.julialang.org/t/beautiful-makie-gallery/62523/98 "2023-07-23T21:36:21Z")

</div>

On Jun 2021 lazarusA posted code for a 3d plot, with perspective.  
At the Julia front page an animated 3d plot is apparent, is similar  
with perspective possible with Makie.

Might this be generated from data from an input device, like an analog  
to digital converter.  
With the use of a GPU maybe this could be refreshed at 60 fps or more.

[Previous page](https://discourse.julialang.org/t/beautiful-makie-gallery/62523.md?page=4)
