Makie: row 2 colorbar without affecting row 1

I’m plotting two equal-sized graphs on the first row (fig[1,1] and fig[1,2]) and a single contour plot on the second row (fig[2,1]). My question is, how do you plot the colorbar for the contour plot? What is the standard solution?

All tutorials I’ve found so far uses a separate column for the colorbar. (I’m linking a relevant example at the end of this message.) That column is fig[2,2] for my case. So, as soon as I add the colorbar, it changes the size of the graph above the colorbar (fig[1,2]).

Below is a sample program that illustrates the problem.

using CairoMakie

func(x,y) = cos(x)*sin(y)

fig = Figure()
ax11 = Axis(fig[1,1])
ax12 = Axis(fig[1,2])
ax21 = Axis(fig[2,1]; aspect=1)

xs = -pi:(pi/16):pi
ys = xs

lines!(ax11, xs, sin.(xs))
lines!(ax12, xs, cos.(xs))
co = contourf!(ax21, xs, ys, func.(xs, reshape(ys,1,:)) )
Colorbar(fig[2,2], co) # <- messes up the layout

save("tmp.pdf", fig)

https://docs.makie.org/stable/tutorials/aspect-tutorial/

Have you seen the layout tutorial? I think it shows a better way using “sublayouts”.

If you really want to use fig[2,2] for your colorbar, try adding tellwidth=false and halign=:left in the Colorbar call.

1 Like
func(x,y) = cos(x)*sin(y)

fig = Figure()
ax11 = Axis(fig[1,1])
ax12 = Axis(fig[1,2])
gl = GridLayout(fig[2, 1:2])
ax21 = Axis(gl[1,1])

xs = -pi:(pi/16):pi
ys = xs

lines!(ax11, xs, sin.(xs))
lines!(ax12, xs, cos.(xs))
co = contourf!(ax21, xs, ys, func.(xs, reshape(ys,1,:)) )
Colorbar(gl[1, 2], co) # <- messes up the layout
colsize!(gl, 1, Aspect(1, 1))

fig

Alternatively use halign on gl to pull the assembly with the colorbar :left or :right

1 Like

First of all, thank you for your help!

Yes I had seen it before my initial message, but I had dismissed it, too hastily in hindsight, because in all the examples, the widths of the row-1 boxes are the same as those of the row-2 boxes. What I need is best addressed if the widths of row-2 boxes can be dissociated from those of row-1 boxes.

But, prompted by your comment, I looked at the tutorial page once again and this time I spotted panel (b) of the first example, which indeed has a colorbar within the fig[2,1] box.

I can see that this is one solution, but it’s highly restrictive because the width of the contour plot + colorbar is limited to the width of the box above (fig[1,1]).

The other solution you offer also works if you move the contour plot to the rightmost position of its box (fig[2,1]) so that it comes right next to the colorbar. It’s also highly restrictive because the contour plot fig[2,1] really needs to come below the upper left graph (fig[1,1]). I’ve modified my initial example as you advise and I paste it at the end of this message.

All this seems to indicate that Makie doesn’t allow for freer layout. It has only gridded layout. Is that right?

It would be nice if it allowed for a non-gridded layout, just to arrange arbitrary boxes more freely in the scene. (I guess this feature has already been requested in the repository?)

In the meanwhile, I’ll plot row 1 and row 2 separately as two PDF files and combine them in my LaTeX document. In that way, I can get whatever layout I like.

using CairoMakie

func(x,y) = cos(x)*sin(y)

fig = Figure()
ax11 = Axis(fig[1,1])
ax12 = Axis(fig[1,2])
ax21 = Axis(fig[2,1]; aspect=1)

xs = -pi:(pi/16):pi
ys = xs

lines!(ax11, xs, sin.(xs))
lines!(ax12, xs, cos.(xs))
co = contourf!(ax21, xs, ys, func.(xs, reshape(ys,1,:)) )
Colorbar(fig[2,2], co; tellwidth=false, halign=:left)

save("tmp.pdf", fig)

Do you mean something like in the answer from @jules above? Otherwise could you show a picture of the result you would like?

As I showed in my example, you can do this with nested grids. You can do most layouts I can think of with that, the only thing that Makie never does is wrapping elements into the next row like CSS does. But that’s a decision, because I don’t think that’s very useful in the context of scientific plotting, and I wanted more control over grids than CSS has.

So whenever you don’t want two things in separate rows to share their columns, they should live in different GridLayouts and you’re good.

What I need is best addressed if the widths of row-2 boxes can be dissociated from those of row-1 boxes.

Just to drive the point home, three rows with three different column numbers

f = Figure()
for i in 1:3
    gl = GridLayout(f[i, 1])
    for j in 1:i+1
        Axis(gl[1, j])
    end
end
f

3 Likes

@jules Thank you for your kind help! I now understand your point very well and I’m sorry for the confusion. The problem was that while you were writing your first answer, I was writing my response to @sijo and you pressed the submit button before I did.

The net result was that my 2nd message looked as if I ignored your answer!

In any case, I know understand

gl = GridLayout(fig[2, 1:2])

is key, which I had missed when I was examining the layout tutorial. In hindsight, I should have noticed the “Panel B” section of the layout tutorial.