# Axis-relative positioning

**URL:** <https://discourse.julialang.org/t/axis-relative-positioning/117749>\
**Category:** Visualization\
**Tags:** makie\
**Created:** [August 2, 2024, 5:41am UTC](https://discourse.julialang.org/t/axis-relative-positioning/117749 "2024-08-02T05:41:52Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [August 2, 2024, 5:41am UTC](https://discourse.julialang.org/t/axis-relative-positioning/117749/1 "2024-08-02T05:41:52Z")

</div>

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?

```julia
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

```

 ![plot](https://global.discourse-cdn.com/julialang/original/3X/e/2/e2747296ca4e7625af290a38fdea74f37dde6134.jpeg)

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 2, 2024, 6:39am UTC](https://discourse.julialang.org/t/axis-relative-positioning/117749/2 "2024-08-02T06:39:52Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [August 2, 2024, 6:02pm UTC](https://discourse.julialang.org/t/axis-relative-positioning/117749/3 "2024-08-02T18:02:06Z")

</div>

I guess like this.

```julia
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

```

 ![fig](https://global.discourse-cdn.com/julialang/original/3X/a/a/aa2fe4cb6fd350dfa47ae8d873e701c8c35ba64b.png)

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

```julia
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](https://github.com/MakieOrg/Makie.jl/issues/422), or is `Axis` the wrong kind of thing so it couldn’t ever be a marker?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 3, 2024, 9:23am UTC](https://discourse.julialang.org/t/axis-relative-positioning/117749/4 "2024-08-03T09:23:06Z")

</div>

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.
