How to make a quaternary plot

Hi all,

I have data that represents a 2X2 joint probability distribution. I would like to visualize it with a quaternary plot, similar to the second to last example here. I don’t have clusters, but I would like to color code one of the marginal probabilities. Here is a MWE of the data I have.

using Distributions 
x = rand(Dirichlet([5,1,1,5]), 100)
color_code = x[1,:] + x[3,:]

How can I do that in either Makie or Plots?
Thanks!

Something like this?

using GLMakie
using Makie.Distributions 
x = rand(Dirichlet([5,1,1,5]), 100)

s = Scene(camera = cam3d!)

p1 = Point3f(sqrt(8/9), 0, -1/3)
p2 = Point3f(-sqrt(2/9), sqrt(2/3), -1/3)
p3 = Point3f(-sqrt(2/9), -sqrt(2/3), -1/3)
p4 = Point3f(0, 0, 1.0)

frame = linesegments!(
    s,
    [
        (p1, p2),
        (p1, p3),
        (p1, p4),
        (p2, p3),
        (p2, p4),
        (p3, p4),
    ],
    color = :black,
)

text!(s, [p1, p2, p3, p4] .* 1.2, text = ["P1", "P2", "P3", "P4"], align = (:center, :center))

function to_quaternary(v1, v2, v3, v4, p1, p2, p3, p4)
    v1 * p1 + v2 * p2 + v3 * p3 + v4 * p4
end

scatter!(s, [to_quaternary(c[1], c[2], c[3], c[4], p1, p2, p3, p4) for c in eachcol(x)])

zoom!(s, 0.7)
s

1 Like

This is really awesome! Thank you for providing a worked example.

For future reference, I added the keyword color = color_code to scatter! to color the points according to the marginal distribution.

At this point, I don’t know enough with Makie to build upon your example, but I think it could form the basis of a useful PR.

One last related question if you don’t mind: How do I add a colorbar?

I tried Colorbar(s) but recieved the following error:

ERROR: Can only use scenes with PixelCamera as topscene

Based on other examples I found, Colorbar is used with Figure, but I am not sure how to incorporate that with scene, or whether that is possible.

Once you want to add other objects, it makes more sense to use a Figure (which is just a parent Scene with a layout basically) and place an LScene in there (that’s a Scene which can be placed in a layout) and then you can place a Colorbar next to that:

using Makie.Distributions 
x = rand(Dirichlet([5,1,1,5]), 100)

f = Figure()
s = LScene(f[1, 1], show_axis = false)

p1 = Point3f(sqrt(8/9), 0, -1/3)
p2 = Point3f(-sqrt(2/9), sqrt(2/3), -1/3)
p3 = Point3f(-sqrt(2/9), -sqrt(2/3), -1/3)
p4 = Point3f(0, 0, 1.0)

frame = linesegments!(
    s,
    [
        (p1, p2),
        (p1, p3),
        (p1, p4),
        (p2, p3),
        (p2, p4),
        (p3, p4),
    ],
    color = :black,
)

text!(s, [p1, p2, p3, p4] .* 1.2, text = ["P1", "P2", "P3", "P4"], align = (:center, :center))

function to_quaternary(v1, v2, v3, v4, p1, p2, p3, p4)
    v1 * p1 + v2 * p2 + v3 * p3 + v4 * p4
end

scat = scatter!(s,
    [to_quaternary(c[1], c[2], c[3], c[4], p1, p2, p3, p4) for c in eachcol(x)],
    color = 1:size(x, 2),
)

zoom!(s.scene, 0.7)

Colorbar(f[1, 2], scat)

f

1 Like

Thanks! I tried LScene, but I was not using it correctly with zoom!.

yeah as LScene is just a thin wrapper of Scene most functionality is not explicitly ported over, so you just do it with lscene.scene

1 Like