# Axis-relative positioning

I want to say `Axis(ax[1,1]; bbox = BBox(x,x+100,y,y+50))` with the `x` and `y` being on the scale of `ax`’s axes – i.e. in data space. But `ax[1,1]` doesn’t work so I use `Axis(fig`, and so `x` and `y` are relative to `fig`’s coordinates, not `ax`’s. Can it be done?

``````using GLMakie
let fig = Figure()
ax = Axis(fig[1,1])
m = 40
n = 20
xs = 2000rand(m)
ys = 1000rand(m)
axs = map(xs, ys) do x,y
a = Axis(fig, bbox = BBox(x,x+100,y,y+50))
scatter!(a, rand(n), rand(n))
end
fig
end
``````

You can compute the positions using `ax.scene.viewport` and `ax.finallimits` observables

1 Like

I guess like this.

``````let fig = Figure()
xmax = 4(2π)
sxs = (0:.1:xmax)
f(x) = x^2
ax = Axis(fig[1,1])
scatter!(ax, sxs, f)
n = 5
xs = sxs[ceil.(Int, range(firstindex(sxs), lastindex(sxs); length=5))] .+ 3
ys = f.(xs) .+ 85
axs = map(xs, ys) do x,y
bbox = lift(ax.scene.viewport, ax.finallimits) do vp, axlims
((vp_xo, vp_yo), (vp_xw, vp_yw)) = vp.origin, vp.widths
((ax_xo, ax_yo), (ax_xw, ax_yw)) = axlims.origin, axlims.widths
axspace_to_vpspace(x,y) = let scale = [vp_xw / ax_xw, vp_yw / ax_yw]
scale .* ([x, y] + [ax_xo, ax_yo]) + [vp_xo, vp_yo]
end
vp_l, vp_b = axspace_to_vpspace(x,y)
vp_r, vp_t = axspace_to_vpspace(x+ax_xw/10,y+ax_yw/10)
BBox(vp_l, vp_r, vp_b, vp_t)
end
a = Axis(fig; bbox)
scatter!(a, rand(n), rand(n))
end
display(fig)
fig
end
``````

This was pretty tricky though, and might go wrong with unitful or logarithmic axes. Would it be theoretically possible to just do like this?

``````xs = 1:5:30
ys = xs .^ 2
scatter(xs, ys; marker=[scatter(rand(50), rand(50)).axis for _ in xs])
``````

Perhaps with custom marker shape · Issue #422 · MakieOrg/Makie.jl · GitHub, or is `Axis` the wrong kind of thing so it couldn’t ever be a marker?

Axis isn’t a compatible object for markers, but one could make the placement function more robust, so it works with log axes as well. That means also lifting on the underlying axis’ transformation function.

1 Like