# Cairomakie inset plot at specific (x,y) coordinates

**URL:** <https://discourse.julialang.org/t/cairomakie-inset-plot-at-specific-x-y-coordinates/84797>\
**Category:** Visualization\
**Tags:** package, plotting, makie\
**Created:** [July 26, 2022, 6:45am UTC](https://discourse.julialang.org/t/cairomakie-inset-plot-at-specific-x-y-coordinates/84797 "2022-07-26T06:45:48Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Salmon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/salmon/32/22968_2.png) [@Salmon](https://discourse.julialang.org/u/Salmon)\
**Post date:** [July 26, 2022, 6:45am UTC](https://discourse.julialang.org/t/cairomakie-inset-plot-at-specific-x-y-coordinates/84797/1 "2022-07-26T06:45:49Z")

</div>

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:

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

```

![grafik](https://global.discourse-cdn.com/julialang/original/3X/2/5/257e195d5029fe6a629c6f26cd72f42bb0571de3.png)

Is there a simple way of doing this?

---

<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:** [July 26, 2022, 5:22pm UTC](https://discourse.julialang.org/t/cairomakie-inset-plot-at-specific-x-y-coordinates/84797/2 "2022-07-26T17:22:45Z")

</div>

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

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

 ![grafik](https://global.discourse-cdn.com/julialang/original/3X/d/4/d43082562d45b3d2e772499a72d664928ca478cb.png)

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

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

```

 ![grafik](https://global.discourse-cdn.com/julialang/original/3X/d/3/d3f405c94fad45908506f80350b25b4224db391c.png)

---

<div class="post-metadata">

**Author:** ![Salmon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/salmon/32/22968_2.png) [@Salmon](https://discourse.julialang.org/u/Salmon)\
**Post date:** [July 27, 2022, 8:31am UTC](https://discourse.julialang.org/t/cairomakie-inset-plot-at-specific-x-y-coordinates/84797/3 "2022-07-27T08:31:53Z")

</div>

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).

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

---

<div class="post-metadata">

**Author:** ![gapato](https://avatars.discourse-cdn.com/v4/letter/g/439d5e/32.png) [@gapato](https://discourse.julialang.org/u/gapato)\
**Post date:** [April 11, 2024, 12:15pm UTC](https://discourse.julialang.org/t/cairomakie-inset-plot-at-specific-x-y-coordinates/84797/4 "2024-04-11T12:15:54Z")

</div>

Thank you @jules, @Salmon, this has been very useful for me. I updated @Salmon’s code to honor the `xscale` and `yscale` parameters of the parent axis. I also changed `px_area` to `viewport` (following a deprecation warning).

```julia
import CairoMakie

function getbboxatPoint(ax, coords, extent=(30, 30))
  width, height = extent
  xscale, yscale = ax.xscale[], ax.yscale[]
  bbox = CairoMakie.lift(ax.scene.camera.projectionview, ax.scene.viewport) do _, pxa
    p = CairoMakie.Makie.project(ax.scene, MM.Point(xscale(coords[1]), yscale(coords[2])))

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

function insetAtPoint(fig, ax, Point, extent=(30, 30); kwargs...)

  bbox = getbboxatPoint(ax, Point, extent)

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

```
