Makie.jl: Limiting height of Colorbar to that of a nearby equal-aspect axis

Hi there,

I have the following code:

fig, abmstepper = abm_plot(model)
ax, hm = heatmap(fig[1,2], model.sugar_capacities; colormap=cgrad(:thermal))
ax.aspect = AxisAspect(1) # equal aspect ratio for heatmap
Colorbar(fig[1, 3], hm, width = 10, tellheight=false)
fig

whose internal details do not matter and the first line can be replaced by scatter(rand(50,2))

This code produces this image:

As you can see, the Colorbar is too high with respect to the other plots. I quickly realized that tellheight doesn’t help here, since of course the Colorbar’s height is decided by the figure available height, not the nearby axis.

How do I make it so that the Colorbar is as high as the axis to its left?

Setting the height of the row in the layout to your ax size seems to work (may be a bit hacky though)

using CairoMakie

begin
    fig = Figure(resolution=(400, 800))
    ax = Axis(fig[1, 1])
    hm = heatmap!(ax, rand(100, 100), tellheight=true)
    ax.aspect = DataAspect()
    cb = Colorbar(fig[1, 2], hm, width = 10, tellheight=true)
    rowsize!(fig.layout, 1, ax.scene.px_area[].widths[2])
    fig
end

1 Like

Aspects are always a bit tricky, because MakieLayout is not a constraint solver, but has an algorithm that tries to calculate row and column sizes given the information it can collect about the layouts and their entries. If the axes decide they are smaller than the space they get, that’s their prerogative but the layout doesn’t know.

My first instinct is this, although it’s not perfect as I would like the resulting row to be centered, which it isn’t because the layout algorithm can’t infer the row height:

You set the row-height to Aspect(2, 1), so aspect of 1 with column 2, where your axis is:

f = Figure()
Axis(f[1, 1])
Axis(f[1, 2])
Colorbar(f[1, 3], width = 30)
rowsize!(f.layout, 1, Aspect(2, 1))
f

I’ve made the background gray so you can see the problematic top alignment, I’ll think some more about this

Thanks guys. Although @Kolaru 's answer seems more complex coding-wise, it looks better than having everyting in the top

I always do height = Relative(2/4) or height = Relative(3/4). They usually work quite well, not perfectly, but good enough :smiley:

1 Like

Thinking about it, I think that it would be cool if setting ax.tellheight = true on the axis would coerce the row to its size, the same way setting it for Label does.

The problem is that the axis size in that case depends on the layout cell it is provided, tellheight only works if the object knows its size before a cell is provided. Otherwise you have circular logic :slight_smile: A constraint solver could maybe deal with this better, but I tried using one in the beginning and it was just very hard to debug whenever something weird happened with the layout.