Is it possible to access point coordinates from Plots using the box and lasso select from Plotly(JS)

Hi! When performing a scatter plot using the Plotly or PlotlyJS backends of Plots, it is possible to use the box and lasso select tools. How can I access the coordinates of the selected points from Julia? Best,

1 Like

Have you found any solution for this? If not Plotly(JS), is there any other plotting package in Julia’s ecosystem that can achieve this purpose?

Also interested in this, any solutions found perhaps?

The plotting ecosystem in active development nowadays is Makie.jl, they provide interactive utilities like this one you guys are after.

It seems that the Makie page on “interraction” doesn’t directly offer any advice on selecting data from a plot (unless I’m missing something).

Would you please be able to offer any advice on creating something like this example?

Pinging @sdanisch @jules as they know better the current features.

1 Like

Bumping this post just in case we got any updates.

I had a look at makie, and it seems we could select some points in the plot, and use inequalities to define a convex region between them, but I can’t seem to figure out how to select a non-convex region (something like using the lasso tool in plotlyJS).

Any help would be greatly appreciated.

Not nonconvex regions, but the Pluto notebook here might be of interest:

Perhaps you could use Makie to graphically define an arbitrary polygon, then use this array of points and PolygonOps.jl function inpolygon to determine which points are inside it.

1 Like

Thank you for your input @jd-foster!

It seems that what does the job in this example is the add_plotly_listener!() function. I assume there could be a chance of using something similar to obtain data from Plotly’s “lasso select”??

The syntax for the aforementioned function looks a bit arcane to me. Is it exclusively a Pluto thing, or could it also be implemented on vscode/repl?

Selecting some data from a plot shouldn’t be that hard, but it seems that there’s no obvious solution out there (using only Julia).

@rafael.guerra, I was actually looking for something like “inpolygon” as I had the same strategy in mind, thanks a lot for pointing it out!

For anyone interested, here’s a rough example of something that does the job in Makie.

Click here for code
using PolygonOps
using GLMakie

# Make a 2D gaussian distribution
μ = [0.0, 0.0]  # Mean
Σ = [0.5 0.0; 0.0 0.2]  # Covariance matrix
x = range(-3, stop=3, length=100)
y = range(-3, stop=3, length=100)
z = [exp(-0.5 * ([i, j] .- μ)' * inv(Σ) * ([i, j] .- μ)) for i in x, j in y]

#Create a matrix for all the discrete points in the space
points = [[i, j] for i in x, j in y]
mask = Observable(zeros(size(points)))

# Number of selected points
nsp = @lift(sum($mask))

GLMakie.activate!(float=true) # Keep plot window on top
f = Figure()
ax = Axis(f[1, 1], aspect=1)
Makie.deactivate_interaction!(ax, :rectanglezoom) # Disable zoom

# Plot the gaussian as points
a = scatter!(ax, Tuple.(vec(points)), color=vec(z), marker=:rect, colormap=:tempo, alpha=0.5)

# Initialise Selection vector
selection = Observable(Point{2,Float32}[])
polygon = Observable(Point{2,Float32}[])

# Plot the points in the selection vector
sc = scatter!(ax, selection)
li = lines!(ax, polygon)

# Pick points by clicking the plot
spoint = select_point(ax.scene, marker=:circle)

# Update selection Observable by pushing the selected point to it
on(spoint) do _
    push!(selection[], spoint[])
    selection[] = selection[] # Update explicitly so that the plots are updated automatically
    
    if size(selection[], 1) > 2
        polygon[] = vcat(selection[], [selection[][1]])
        mask[] = [inpolygon(p, polygon[]; in=1, on=1, out=0) for p in points]
        display("You have selected $(nsp[]) points")
    end

end

# Reset Selection button
resetb = Button(f[2, 1][1, 1]; label="Reset Selection", tellwidth=false)

on(resetb.clicks) do _
    # delete!(ax, lp)
    selection[] = Point{2,Float32}[]
    polygon[] = Point{2,Float32}[]
end

f

In this case, “mask” is a matrix with 1’s in the selected region and 0’s outside of it.

First time using Makie, so I’m sure there will be some other flaws as well, please do point them out.

Edit: Tweaked it a little bit to remove some errors.