Struggling with layouting Makie plots

Apologies, this is a very similar question to one I asked yesterday, but a bit different. Apologies as well if the answer is in the docs, but I’m struggling to find it. I’ve been playing around with various combinations of properties/functions from the docs. I feel like this should be a simple problem that I’m somehow messing up.

Here is an example figure:

The left plot spans two rows. I’d like the axes in the second column to have the same width, which will involve the size of the rows changing. And I’d also like the height of the left axis to equal the height of the two right axes, which will involve the size of the columns changing.

I’ve been looking this this page: GridLayout · Makie
but really can’t get my head around what I need to be doing for my specific case…

Here is code that produces the figure:

using GLMakie

x,y,z = rand(100), rand(100), 3 .*rand(100)

function plot3d(f;kwargs...)
    
    ax = Axis3(f[1,1], protrusions = (0,0,0,0),aspect=:data;kwargs...)
    hidedecorations!(ax)
    scatter!(ax,x,y,z)
end

f = Figure(size=(500,500))

plot3d(f[1:2,1])
plot3d(f[1,2];elevation=0,azimuth=-pi/2,title="Side View")
plot3d(f[2,2],elevation=pi/2,azimuth=-pi/2,title="Top View")

f

Hm well you requested aspect = :data and the height of your data is three times the width, so it’s no surprise the upper right axis is narrow. With aspect constraints you usually don’t get perfectly fitting layouts (unless you handle the aspect constraints in the layout itself, via the Aspect column or row size).

In your case one could think that, ok if the data has three times the height than width, then the upper row should get three times the space. You can do that via Auto(3) which means, three times as much space as normal Auto() which is the default size for rows and columns.

As you can see that at least makes the two axes on the right the same width (but they still leave space on the sides which comes from the axis aspect constraint):

x,y,z = rand(100), rand(100), 3 .*rand(100)

function plot3d(f;kwargs...)
    
    ax = Axis3(f[1,1], protrusions = (0,0,0,20), aspect=:data; kwargs...)
    hidedecorations!(ax)
    scatter!(ax,x,y,z)
end

f = Figure(size=(500,500))

plot3d(f[1:2,1])
plot3d(f[1,2];elevation=0,azimuth=-pi/2,title="Side View")
plot3d(f[2,2],elevation=pi/2,azimuth=-pi/2,title="Top View")

rowsize!(f.layout, 1, Auto(3))

f

Thanks for your reply. In this case you’re right, it’s not too difficult to work out. Slightly more difficult question: if the camera angle isn’t perfectly 2D, like the top right axis in the image that follows, is there some axis property that tells me how wide and tall the axis box is? I guess now I’m looking for the aspect ratio of the rectangle that perfectly encapsulates the axis, which I can then pass to rowsize! using Auto(X), where X is that aspect ratio?

There’s no property, one can probably calculate it from azimuth, elevation and limits directly but I didn’t want to :smiley: The hacky solution was to see what the boundingbox of the axis frame lines in screen space is like. This uses some internals though so it’s bound to break at some point.

x,y,z = rand(100), rand(100), 3 .*rand(100)

function plot3d(f;kwargs...)
    
    ax = Axis3(f[1,1], protrusions = (0,0,0,20), aspect=:data; kwargs...)
    hidedecorations!(ax)
    scatter!(ax,x,y,z)
    return ax
end

f = Figure(size=(500,500))

ax1 = plot3d(f[1:2,1])
ax2 = plot3d(f[1,2];elevation=0.4,azimuth=-pi/3,title="Side View")
ax3 = plot3d(f[2,2],elevation=pi/2,azimuth=-pi/2,title="Top View")

function frame_rect_aspect(ax)
    all_frame_points = Iterators.flatmap(1:3) do i
        ax.blockscene.plots[i][1][]
    end
    frame_points_screen_space = Point2f.(Makie.project.(Ref(ax.blockscene), all_frame_points))
    bbox = Rect2f(frame_points_screen_space)
    return bbox.widths[2] / bbox.widths[1]
end

Makie.update_state_before_display!(f) # trigger limit calculations

aspect1 = frame_rect_aspect(ax2)
aspect2 = frame_rect_aspect(ax3)
rowsize!(f.layout, 1, Auto(aspect1))
rowsize!(f.layout, 2, Auto(aspect2))

f

Thanks very much, this is very useful!

Also interesting to see how some of the internals work