# Zoomed inset using Makie?

**URL:** <https://discourse.julialang.org/t/zoomed-inset-using-makie/110717>\
**Category:** Visualization\
**Tags:** question, makie\
**Created:** [February 25, 2024, 12:23am UTC](https://discourse.julialang.org/t/zoomed-inset-using-makie/110717 "2024-02-25T00:23:53Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![rongcuid](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rongcuid/32/42911_2.png) [@rongcuid](https://discourse.julialang.org/u/rongcuid)\
**Post date:** [February 25, 2024, 12:23am UTC](https://discourse.julialang.org/t/zoomed-inset-using-makie/110717/1 "2024-02-25T00:23:53Z")

</div>

Is it possible to achieve zooming in a portion of an (already drawn) axis and display it as another axis, or as an inset?

Something like this in matplotlib:

> <https://stackoverflow.com/questions/13583153/how-to-zoomed-a-portion-of-image-and-insert-in-the-same-plot-in-matplotlib>

---

<div class="post-metadata">

**Author:** ![astra\_kawa](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/astra_kawa/32/204424_2.png) [@astra\_kawa](https://discourse.julialang.org/u/astra_kawa)\
**Post date:** [February 25, 2024, 12:57am UTC](https://discourse.julialang.org/t/zoomed-inset-using-makie/110717/2 "2024-02-25T00:57:10Z")

</div>

Yup this is possible, specifically using the [BBox](https://docs.makie.org/stable/explanations/blocks/#specifying_a_boundingbox_directly) function (which specifies the bounding box of the `Axis`). Here’s a small example:

```julia
using CairoMakie
CairoMakie.activate!(type = "svg")

x = 0.0 : 0.1 : 10.0
y = exp.(-x)

begin
    fig = Figure(size=(800,800))
    ax1 = Axis(
        fig[1,1]; 
        xgridvisible=false, ygridvisible=false
    )

    lines!(ax1, x, y)
    bracket!(5, 0.01, 10, 0.01; offset=5, style=:square, orientation=:up)

    ax2 = Axis(
        fig; 
        yscale=log10,
        bbox=BBox(400, 750, 200, 600)
    )
    lines!(ax2, x[50:end], y[50:end])

    fig
end

```

This produces:

 ![test](https://global.discourse-cdn.com/julialang/original/3X/0/f/0f3e5ee9828587022bc399f12cdb6308e06f362b.png)

Hope this helps!

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [February 25, 2024, 1:01am UTC](https://discourse.julialang.org/t/zoomed-inset-using-makie/110717/3 "2024-02-25T01:01:58Z")

</div>

This here worked on `GLMakie v0.8.11` (includes update of rectangle-zoom for interactivity). The idea is to turn this into something like an `insetaxis` method, but I haven’t found time for that yet.

```julia
using GLMakie
import GLMakie.Makie.GeometryBasics: coordinates
GLMakie.activate!()

x = collect(1:100)
y = randn(length(x))

fig = Figure()
ax = Axis(fig[1,1])
inset = Axis(fig[1,1]; width=Relative(0.8), height=Relative(0.2),
             halign=0.9, valign=0.1, backgroundcolor=(:white,1.0))

scatterlines!(ax, x, y)
subx, suby = x[30:40], y[30:40]
scatterlines!(inset, subx, suby)

poly!(ax, inset.finallimits, color=(:black,0), strokewidth=1, strokecolor=:black)

translate!(inset.blockscene, 0, 0, 1000)

shifted_bbox = lift(ax.scene.px_area, inset.layoutobservables.computedbbox,
                    ax.scene.camera.projectionview) do px_area, bbox, _
  Rect2f(bbox.origin .- px_area.origin, bbox.widths)
end

scatter!(ax, shifted_bbox, color=:red, space=:pixel)

vert_edges = [Observable{Any}() for _ = 1:4]
onany(inset.finallimits, shifted_bbox) do bbox1, bbox2
  for (i,(c1, c2)) in enumerate(zip(coordinates(bbox1), coordinates(bbox2)))
    cc1 = Makie.project(ax.scene, Point2f(c1))
    vert_edges[i][] = [cc1, Point2f(c2)]
  end
end
notify(inset.finallimits)
for vs in vert_edges
  lines!(ax, vs, color=:grey, space=:pixel)
end

display(fig)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/2/c/2c9217befa43050138e56c9fa4c34ce4847659b6.png)

---

<div class="post-metadata">

**Author:** ![rongcuid](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rongcuid/32/42911_2.png) [@rongcuid](https://discourse.julialang.org/u/rongcuid)\
**Post date:** [February 25, 2024, 1:11am UTC](https://discourse.julialang.org/t/zoomed-inset-using-makie/110717/4 "2024-02-25T01:11:51Z")

</div>

I don’t _think_ this is what I need, because this example actually draws the data twice (which is what I am doing right now). It’s easy enough for a simple line plot, but if I have multiple layers, or even dynamically drawn axis, I would prefer to just use the data already in axis one.

---

<div class="post-metadata">

**Author:** ![rongcuid](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rongcuid/32/42911_2.png) [@rongcuid](https://discourse.julialang.org/u/rongcuid)\
**Post date:** [February 25, 2024, 1:13am UTC](https://discourse.julialang.org/t/zoomed-inset-using-makie/110717/5 "2024-02-25T01:13:58Z")

</div>

This also draws the data twice, so not exactly what I am looking for.

---

<div class="post-metadata">

**Author:** ![SpuriousEigenstate](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/spuriouseigenstate/32/208390_2.png) [@SpuriousEigenstate](https://discourse.julialang.org/u/SpuriousEigenstate)\
**Post date:** [November 28, 2024, 3:50pm UTC](https://discourse.julialang.org/t/zoomed-inset-using-makie/110717/6 "2024-11-28T15:50:00Z")

</div>

> [@fatteneder](#):
>
> This here worked on `GLMakie v0.8.11` (includes update of rectangle-zoom for interactivity). The idea is to turn this into something like an `insetaxis` method, but I haven’t found time for that yet.

I had been looking for something like this for a while; essentially the equivalent of matplotlib’s `indicate_inset_zoom`. I wrote it into a function which also selectively draws the lines which don’t cross the rectangle (similar to what matplotlib does by default). I’m posting here, because there might be others looking for something like this.

```julia
function draw_inset!(ax, inset)

	poly!(ax, inset.finallimits, color=(:black,0), strokewidth=1, strokecolor=:black)
	
	shifted_bbox = lift(ax.scene.viewport, inset.layoutobservables.computedbbox,
						ax.scene.camera.projectionview) do px_area, bbox, _
		Rect2f(bbox.origin .- px_area.origin, bbox.widths)
	end

	# scatter!(ax, shifted_bbox, color=:red, space=:pixel)

	vert_edges = [Observable{Any}() for _ in 1:4]
	connect = [Observable{Bool}() for _ in 1:4] 
	onany(inset.finallimits, shifted_bbox) do bbox1, bbox2
		for (i,(c1, c2)) in enumerate(zip(Makie.GeometryBasics.coordinates(bbox1), Makie.GeometryBasics.coordinates(bbox2)))
		cc1 = Makie.project(ax.scene, Point2f(c1))
		vert_edges[i][] = [cc1, Point2f(c2)]
		end

        rectlims = vcat(Makie.project(ax.scene, Point2f(inset.finallimits[].origin))..., 
            Makie.project(ax.scene, Point2f(inset.finallimits[].origin.+inset.finallimits[].widths))...) # x0 y0 x1 y1

        x0 = shifted_bbox[].origin[1] > rectlims[1]
        x1 = shifted_bbox[].origin[1] + shifted_bbox[].widths[1] > rectlims[3]
        y0 = shifted_bbox[].origin[2] > rectlims[2]
        y1 = shifted_bbox[].origin[2] + shifted_bbox[].widths[2] > rectlims[4]
        connect[1][] = xor(x0, y0)
        connect[2][] = x1==y0
        connect[3][] = x0==y1
        connect[4][] = xor(x1, y1) 
	end

	notify(inset.finallimits)

	for (c, vs) in zip(connect,vert_edges)
		lines!(ax, vs, color=:grey, space=:pixel, visible=c)
	end
end

```

The result looks like this:

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

The only bug I can’t be bothered to fix right now is that if no xlims or ylims are set, it will set them to (0,10). Calling `xlims!()` or `ylims!()` with empty argument fixes it though. Thanks @fatteneder !

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [November 29, 2024, 7:07pm UTC](https://discourse.julialang.org/t/zoomed-inset-using-makie/110717/7 "2024-11-29T19:07:39Z")

</div>

For this kind of functionality, see `zoom_lines!(ax, inset)` in [MakieExtra.jl](https://discourse.julialang.org/t/ann-makieextra-jl-more-recipes-and-tools-for-makie-plots/118618):

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/b/1be500d6c27180e82fe58ef02716ce36250c33ee.png)
