I need to iteratively call a Makie recipe according to an observable value.
Lets say I write a recipe MyPlot and I want to iteratively call Scatter inside.
using Makie
@recipe(MyPlot, x) do scene
Theme(
repeat = 3
)
end
function Makie.plot!(myp::MyPlot)
obs = @lift [$(myp.x) .* i for i in 1:$(myp.repeat)]
hlines!(myp, 5, color=:red) # always plot a horizontal line
for valrow in obs[]
scatter!(myp, valrow) # depends on the attribute
end
myp
end
julia> p.repeat[] = 10 # doesn't update the figure
10
I know that theoretically I need to call the scatter recipe with an observable passed in, but I cannot wrap my head around it how to do it.
Any suggestions ?
Please keep in mind this is just a minimal example for a more complicated code, where the iteration is necessary. So please don’t suggest solutions that involve calling scatter only once with scatter!(myp, obs) or similar.
As far as I know, this is the solution to this problem. When I have had this come up in the past, I have used iteration to create an Observable{Point2f[]} that I then pass to scatter! once. In this simple example, that looks like
obs = @lift reduce(vcat, [Point2f.(i, $(myp.x) .* i) for i in 1:$(myp.repeat)])
Thanks for the answer but this solution involves calling scatter only once, which is circumventing the problem.
In reality I don’t call scatter but GraphMakie.EdgePlot with different transparent colors, so that in the end a mixture of transparencies and colors is drawn.
If there is really no way around to get it working iteratively, I guess I should focus to somehow transform my data as you suggested for my problem as well…
I believe the color= kwarg for edgeplot can be a vector, so I would try creating two observables, one the vector of edges and one the vector of colors and then calling edgeplot with those.
You cannot have the existence of a plot depend on an observable, so you cannot have x scatter plots where x changes dynamically. At least not how things currently work. You can always concatenate the data and work with a single plot as suggested above, not sure why you don’t want to / can’t do that.
PS: Actually you can do it but you’d have to write more complex logic that adds and deletes the plot objects, renews observable connections etc. Probably not worth it