# Customizing Makie rectangle zoom mouse interaction and axis limits

**URL:** <https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448>\
**Category:** Visualization\
**Tags:** question, makie, interactivity, events, observables\
**Created:** [October 1, 2023, 2:43am UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448 "2023-10-01T02:43:55Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![oscarvdvelde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarvdvelde/32/202157_2.png) [@oscarvdvelde](https://discourse.julialang.org/u/oscarvdvelde)\
**Post date:** [October 1, 2023, 2:43am UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/1 "2023-10-01T02:43:55Z")

</div>

I am trying to create a Makie dashboard where several axes (e.g. x-y, t-z) with the same data points will update simultaneously based on the mouse selection of data in any of the axes.

I made an observable, `selection[]`, a Bool array of length(points) indicating which points to show. When this changes, it will again plot the data, in an animated (stepwise) manner, colored by time. This part works.

Now I would like to use the existing mouse rectangle zoom. As default, it only magnifies data by adjusting the axis limits - except that when I check ax.limits, they are the initial ones. Where can I find the actual shown limits or the result of the mouse rectangle, in data space (not pixels)?

I see the result of the mouse rectangle in interactions(ax):

```julia
  :rectanglezoom => (1, RectangleZoom(#1269, Observable(false), false, false, Float32[262.727, 14.6552], Float32[282.068, 0.0], Observable(HyperRec…

```

I am not sure how to retrieve it from this Dict or from some axis parameter. With these limits I want to return a new `selection[]` of the data within the rectangle limits and trigger the update in all axes.

What is the best way to do it?

---

<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:** [October 1, 2023, 5:33am UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/2 "2023-10-01T05:33:32Z")

</div>

`ax.finallimits` is the observable that holds the limits the axis actually shows at a given time

---

<div class="post-metadata">

**Author:** ![oscarvdvelde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarvdvelde/32/202157_2.png) [@oscarvdvelde](https://discourse.julialang.org/u/oscarvdvelde)\
**Post date:** [October 1, 2023, 11:45pm UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/3 "2023-10-01T23:45:01Z")

</div>

Thanks for pointing me to `ax.finallimits`, it appears not documented at all in the Makie documentation.

My current issue is that when I trigger on the `ax.finallimits` change, and update my `selection[]` observable, and `empty!` the axes (keeps finallimits)… it (1) does not actually clear the axes at all, and (2) resets the finallimits to `ax.limits` when I try to plot the new data:

```julia
on(ax0.finallimits) do lims
    x1 = Float64(minimum(lims)[1])
    x2 = Float64(maximum(lims)[1])
    println(x1)
    println(x2)
    empty!(ax0)
    empty!(ax1)
    poly!(ax1, countries; color=(:black,0.0), strokecolor = :black, strokewidth = 2.0, overdraw = true)
    selection[] = lma.qua .&& (x1 .< timv .<= x2)
    return selection
end

on(selection) do sel
    nrsteps = 100
    stepparam = timv[sel]
    stepsize = (maximum(stepparam) - minimum(stepparam)) / nrsteps
    binnr,bindex,bincount = discretize(stepparam, minimum(stepparam):stepsize:maximum(stepparam))
    for i in 1:nrsteps
        step = bindex[:,i]
        coloring = norm(stepparam)
        s0 = scatter!(ax0,tz[sel][step]; marker=:rect,markersize=10,strokewidth=0.01,color=coloring[step],colorrange=(0,1),colormap=:turbo)    
        s1 = scatter!(ax1,xy[sel][step]; marker=:rect,markersize=10,strokewidth=0.01,color=coloring[step],colorrange=(0,1),colormap=:turbo)    
        sleep(0.03) # controls animation speed
    end
end

```

Edit: It does empty the axes when I do not include the update to `selection[]`. It seems as if `selection[]` is actually updated before I empty the axes.

---

<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:** [October 2, 2023, 4:10am UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/4 "2023-10-02T04:10:16Z")

</div>

yeah `ax.finallimits` is currently internal, that’s why it’s not documented. to avoid the axis limits resizing when you plot something, you have to set `ax.limits` to something specific, like `(1, 2, 3, 4)`. Otherwise `reset_limits!`, which will be called when something is plotted into a currently visible axis, will reset to automatically determined limits. `ax.limits` is what changes as well when you use `xlims!` etc.

---

<div class="post-metadata">

**Author:** ![oscarvdvelde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarvdvelde/32/202157_2.png) [@oscarvdvelde](https://discourse.julialang.org/u/oscarvdvelde)\
**Post date:** [October 2, 2023, 10:48am UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/5 "2023-10-02T10:48:05Z")

</div>

Okay, I think I can work with `ax.limits` taking x1 and x2, but the issue remains that axes do not get emptied despite the `empty!` statements placed before `selection[] = ` . Perhaps I am not handling the observables well with the `on() do` statements?

---

<div class="post-metadata">

**Author:** ![oscarvdvelde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarvdvelde/32/202157_2.png) [@oscarvdvelde](https://discourse.julialang.org/u/oscarvdvelde)\
**Post date:** [October 6, 2023, 5:40am UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/6 "2023-10-06T05:40:04Z")

</div>

Continuing from 4 days ago. It now partially works:

```julia
on(ax0.finallimits) do lims
    x1 = Float64(minimum(lims)[1])
    x2 = Float64(maximum(lims)[1])
    empty!(ax0)
    empty!(ax1)
    xlims!(ax0,x1,x2)
    poly!(ax1, countries; color=(:black,0.0), strokecolor = :black, strokewidth = 2.0, overdraw = true)
    selection[] = lma.qua .&& (x1 .< timv .<= x2)
end

```

This works properly when I trigger ax0.finallimits by giving a manual `xlims!` command. It clears the axes and animates the plotting of points as intended.

But when I drag the mouse to cause an ax0.finallimits change, the plot stays frozen, with mouse selection gray mask visible, for the time the now invisible animation should take (6 seconds). Then, it reveals the new plot all at once. So it triggered, but it somehow is hiding the animation.

Any thoughts are very welcome!

---

<div class="post-metadata">

**Author:** ![oscarvdvelde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarvdvelde/32/202157_2.png) [@oscarvdvelde](https://discourse.julialang.org/u/oscarvdvelde)\
**Post date:** [October 8, 2023, 12:34am UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/7 "2023-10-08T00:34:40Z")

</div>

I solved it after watching a Youtube video on Makie interactivity.  
The animation now runs as intended by using `@async for i in 1:nrsteps`  
Apparently, `@async` has not made it into [docs.makie.org](https://docs.makie.org) yet.

---

<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:** [October 8, 2023, 8:34am UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/8 "2023-10-08T08:34:45Z")

</div>

Hm yes good point. Maybe because I don’t fully understand when you need it and when not. Like I would assume that sleep yields but it doesn’t seem to play well with the renderloop necessarily

---

<div class="post-metadata">

**Author:** ![oscarvdvelde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscarvdvelde/32/202157_2.png) [@oscarvdvelde](https://discourse.julialang.org/u/oscarvdvelde)\
**Post date:** [October 21, 2023, 3:47pm UTC](https://discourse.julialang.org/t/customizing-makie-rectangle-zoom-mouse-interaction-and-axis-limits/104448/9 "2023-10-21T15:47:52Z")

</div>

Just a small addition. Now I am using:

```julia
on(ax0.finallimits) do tlims
    if (now() - change[]) > Millisecond(2000)
        x1 = Float32(minimum(tlims)[1])
        x2 = Float32(maximum(tlims)[1])
        println([x1,x2])
        ax0.limits.val = ((x1,x2),ax0.limits.val[2])
        change[] = now()
        inside_timeinterval[] = (x1 .< tim .<= x2)
    end
end

```

instead of using xlims! or limits! I first replaced those functions by updating ax.limits.val directly. However, it still printed multiple times. For a similar function selecting a latitude-longitude area it updated like 8 times as apparently every of the 4 limits updates a tuple of 2 inside, and I also suspected the mouse action to cause more than one trigger. It was noticeably laggy. Also, inputting Float64 generated extra triggers from conversion to Float32, this is why I make them Float32 before.  
My solution was to create a `change = Observable(Dates.now())` to prevent the loop from executing more than once in 2 seconds. I hope this can be useful for someone else as well.
