Cairomakie inset plot at specific (x,y) coordinates

Hi Guys,

by using `BBox()` one can create an inset plot. The location is determined by the arguments, which are given as pixels.
This works mostly but for certain use cases, it would be nice to specify an absolute location, i.e. in terms of coordinates from the main plot.

maybe this example demonstrates what I mean:

``````using CairoMakie
let
x = -3:0.05:3
y = exp.(-x .^ 2)
fig = Figure(resolution = (600, 400))
ax1 = Axis(fig[1, 1])
lines!(ax1, x, y)
scatter!(ax1,[1.2],[0.6],label = "I want the inset centered at (x,y) = (1.2,0.6)")
axislegend()
# inset
ax2 = Axis(fig, bbox = BBox(140, 250, 200, 300), title = "inset  at (140, 250, 200, 300)")

lines!(ax2, x, y, color = :red)
display(fig)
end
``````

Is there a simple way of doing this?

Not necessarily “simple” but you can project the point you want whenever the axis scene projection or position in the scene changes:

``````let
x = -3:0.05:3
y = exp.(-x .^ 2)
fig = Figure(resolution = (600, 400))
ax1 = Axis(fig[1, 1])
lines!(ax1, x, y)
scatter!(ax1,[1.2],[0.6],label = "I want the inset centered at (x,y) = (1.2,0.6)")
axislegend()

bbox = lift(ax1.scene.camera.projectionview, ax1.scene.px_area) do _, pxa
p = Makie.project(ax1.scene, Point(1.2, 0.6))
c = p + pxa.origin
Rect2f(c .- Point2f(50, 50), (100, 100))
end

# inset
ax2 = Axis(fig, bbox = bbox, title = "inset centered on point", backgroundcolor = (:white, 0.9))
translate!(ax2.blockscene, 0, 0, 100)

lines!(ax2, x, y, color = :red)
fig
end
``````

If you translate the axis blockscene forward it correctly covers the other content.

Another option could be to specify a rectangle in data coordinates:

``````let
x = -3:0.05:3
y = exp.(-x .^ 2)
fig = Figure(resolution = (600, 400))
ax1 = Axis(fig[1, 1])
lines!(ax1, x, y)
scatter!(ax1,[1.2],[0.6],label = "I want the inset centered at (x,y) = (1.2,0.6)")
axislegend()

bbox = lift(ax1.scene.camera.projectionview, ax1.scene.px_area) do _, pxa
bl = Makie.project(ax1.scene, Point2f(0, 0)) + pxa.origin
tr = Makie.project(ax1.scene, Point2f(2, 0.5)) + pxa.origin
Rect2f(bl, tr - bl)
end

# inset
ax2 = Axis(fig, bbox = bbox, title = "inset on rect in data coords")
translate!(ax2.blockscene, 0, 0, 100)

lines!(ax2, x, y, color = :red)
fig
end
``````

2 Likes

Thanks jules,
looks like this does exactly what I want.
For whoever is interested in this: Using this solution I defined myself a small helper function that creates an inset axis centered at a point with specified size (for now in pixels).

``````using CairoMakie
function getbboxatPoint(ax,coords,extent = (30,30))
width,height = extent
bbox = lift(ax.scene.camera.projectionview, ax.scene.px_area) do _, pxa
p = Makie.project(ax.scene, Point(coords...))

c = p + pxa.origin
R = Rect2f(c .- Point2f(width, height),(2*width,2* height))
println(c)
R
end
return bbox
end

function insetAtPoint(fig,ax,Point,extent = (30,30); width = extent[1], height = extent[2],kwargs...)

bbox = getbboxatPoint(ax,Point,extent;width,)

ax2 = Axis(fig, bbox = bbox;kwargs...)
translate!(ax2.blockscene, 0, 0, 100)
return ax2
end

let
x = -3:0.05:3
y = exp.(-x .^ 2)
fig = Figure(resolution = (500, 600))
ax1 = Axis(fig[1, 1])
lines!(ax1, x, y)
insetCoords = (1,0.5)

scatter!(ax1,[insetCoords[1]],[insetCoords[2]],label = "I want the inset centered at (x,y) = \$(insetCoords)")
axislegend()

# inset
ax2 = insetAtPoint(fig,ax1, insetCoords,(80,50); title = "inset centered on point", backgroundcolor = (:white, 0.9))
translate!(ax2.blockscene, 0, 0, 100)

lines!(ax2, x, y, color = :red)
fig
end

``````

Cheers!