In Makie, when should a function accept `fig[1,1]` as input, vs an `Axis`?

I don’t really when to use an Axis vs indexing like fig[1,1] . If I’m writing a function to make part of a plot, should I be passing it fig[1,1] or an axis? should the function be making the axis and returning it?

From @jules:

fig[1, 1] just refers to the position in the figure. You pass this to functions that create layoutables and your input argument decides where. For example, if you have a function that creates an axis and a colorbar and a legend, you can pass any nested position in the figure, for example make_objects(f[1:2, 3][2, 3]).
You pass the axis if your plotting function just “plots”, so handles only functions like scatter! etc

My followup question:

I have some code that looks like this:

using AbstractPlotting, CairoMakie
function make_heatmap!(ax)
    x = range(0,1; length=100)
    y = 1:100
    heatmap!(ax, x, y, rand(100,100))
end
function make_colorbar!(fig)
    Colorbar(fig, width = 25)
end
function make_plot_below!(ax)
    ax.height = 25
    hidespines!(ax)
    hideydecorations!(ax)
    hidexdecorations!(ax; ticklabels=false, ticks=false, label=false)
    on = sort!(rand(10))
    off = [on[1:end-1] .+ diff(on) ./ 2; last(on)]
    xs = Float32[]
    for i in eachindex(on)
        push!(xs, on[i])
        push!(xs, off[i])
        push!(xs, NaN)
    end
    ys = fill(0, length(xs))
    lines!(ax, xs, ys)
end
function outer()
    fig = Figure()
    ax1 = Axis(fig[1,1])
    make_heatmap!(ax1)
    make_colorbar!(fig[1,2])
    ax2 = Axis(fig[2, 1])
    make_plot_below!(ax2)
    linkxaxes!(ax1, ax2)
    hidexdecorations!(ax1)
    return fig
end
save("test.png", outer())

But I’d like to combine make_heatmap! and make_colorbar! into a single function. However, I’m not really sure how to do that, because it’s important that make_plot_below! is directly below the heatmap, and not below, say, the heatmap and colorbar together. How do I do this?

Answer with lots of help from @jules on Slack

(transferred to Discourse for posterity)

You can pass fig[1,1] to make_heatmap_with_colorbar! and fig[1,1][2,1] to make_plot_below!. To continue the example:

function make_heatmap_with_colorbar!(fig)
    ax = Axis(fig[1,1])
    make_heatmap!(ax)
    make_colorbar!(fig[1,2])
    return ax
end
function outer2()
    fig = Figure()
    ax1 = make_heatmap_with_colorbar!(fig[1,1])
    ax2 = Axis(fig[1,1][2, 1])
    make_plot_below!(ax2)
    linkxaxes!(ax1, ax2)
    hidexdecorations!(ax1)
    return fig
end

This can also be written as

function mk_heatmap_with_colorbar()
    fig = Figure()
    make_heatmap_with_colorbar!(fig[1,1])
    return fig
end
function annotate!(fig)
    ax1 = content(fig[1,1][1,1])
    ax2 = Axis(fig[1,1][2,1])
    make_plot_below!(ax2)
    linkxaxes!(ax1, ax2)
    hidexdecorations!(ax1)
end
fig = mk_heatmap_with_colorbar()
annotate!(fig)

The reason I am interested is that I want to decouple mk_heatmap_with_colorbar and annotate!, and even allow them to be in two separate packages. Luckily the layouting is very versatile and can accomodate this to some extent. Though annotate! here still depends on the internal layout chosen by mk_heatmap_with_colorbar.