-
-
Notifications
You must be signed in to change notification settings - Fork 315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic PlotList
recipe which plots arbitrary arrays of PlotSpec
#2868
Conversation
This is functionally complete, but please try whatever you think might break it and let me know! I think we might also want to add eg palette support but that would need a refactor of the axis code. |
Compile Times benchmarkNote, that these numbers may fluctuate on the CI servers, so take them with a grain of salt. All benchmark results are based on the mean time and negative percent mean faster than the base branch. Note, that GLMakie + WGLMakie run on an emulated GPU, so the runtime benchmark is much slower. Results are from running: using_time = @ctime using Backend
# Compile time
create_time = @ctime fig = scatter(1:4; color=1:4, colormap=:turbo, markersize=20, visible=true)
display_time = @ctime Makie.colorbuffer(display(fig))
# Runtime
create_time = @benchmark fig = scatter(1:4; color=1:4, colormap=:turbo, markersize=20, visible=true)
display_time = @benchmark Makie.colorbuffer(display(fig))
|
I tried this some more, because I really need this functionality. First I tried to make it not a recipe, but got weird errors. Then I tried just using the recipe with explicit attributes, which "works" in that it doesn't error, but rather leaves dangling plot elements (that don't resolve themselves if you change back the Observed) so once you remove a plot it's just broken. It seems there was also an off-by-one error in My recipe is something like function Makie.plot!(plt::SignalPlot{<:Tuple{<:AbstractArray}})
Main.plt = plt
ms = plt[1]
specs = lift(ms, values(plt.attributes)...) do ms, attrs...
pairs = zip(keys(plt.attributes), attrs)
[PlotSpec{SignalPlot}(item; pairs...) for item in ms]
end
plotlist!(plt, specs)
end |
I tried re-working the fundamental machinery in here to use a function update_plot_with_plotspec!(cached_plot::AbstractPlot, spec::PlotSpec)
# Update args in cached `input_args` list
for arg_index in eachindex(spec.args)
cached_plot.input_args[arg_index].val = spec.args[arg_index]
end
# Update attributes
for (attribute, new_value) in pairs(spec.kwargs)
update_attributes_inplace!(cached_plot, attribute, new_value)
end
# notify all args, without broadcasting
map(notify, cached_plot.input_args)
# notify all accessed kwargs
map(_notify!, (getindex(cached_plot, attr) for attr in keys(spec.kwargs)))
end
function Makie.plot!(p::PlotList{<: Tuple{<: AbstractArray{<: PlotSpec}}})
# Cache plots here so that we aren't re-creating plots every time;
# if a plot still exists from last time, update it accordingly.
# If the plot is removed from `plotspecs`, we'll delete it from here
# and re-create it if it ever returns.
cached_plots = IdDict{Any,AbstractPlot}()
lift(p[1]) do plotspecs
Main.p = p
println()
println("----------------------------------------")
plots_to_delete = Base.IdSet()
push!.((plots_to_delete,), collect(keys(cached_plots))))
# First, scan through `plotspecs`, creating or updating all plots
# specified by `plotspecs`, marking previously-extant plots as not
# to be deleted via `plots_to_delete`
for plotspec in plotspecs
if !haskey(cached_plots, plotspec.args[1])
# Create new plot, store it into our `cached_plots` dictionary
cached_plots[plotspec] = plot!(p,
typeof(plotspec).parameters[1],
Attributes(plotspec.kwargs),
plotspec.args...,
)
else
update_plot_with_plotspec!(cached_plots[plotspec], plotspec)
end
# Because this plotspec appeared in `plotspecs`, it should not
# be deleted, so remove it from our deletion queue.
delete!(plots_to_delete, plotspec)
end
# Next, delete all plots still extant in in `plots_to_delete`
for plotspec in plots_to_delete
idx = findfirst(==(cached_plots[plotspec]), p.plots)
if idx !== nothing
deleteat!(p.plots, idx)
end
delete!(cached_plots, plotspec)
end
end
end But for some reason I can't figure out, updates don't flow through the system; my plots remain static. |
While reviewing & figuring out your approaches, I've rewritten the implementation. I also simplified the updating mechanism for now, removing nested attributes, which aren't that well supported within Makie yet anyways and shouldn't be needed for most plots. Anyways, I also played around with a simple API to make it a bit nicer to use: import Makie.PlotspecApi as P
plots[] = [
P.image(0 .. 1, 0 .. 1, Makie.peaks()),
P.poly(Rect2f(0.45, 0.45, 0.1, 0.1)),
P.lines(0 .. 1, sin.(0:0.01:1); linewidth=10, color=Makie.resample_cmap(:viridis, 101)),
] |
@pepijndevos not sure what to do about the cycling, since that needs the axis. |
Yes, I agree. The |
This isn't 100% ready, but since sd/beta-20 had some problems with the PlotSpec implementation which are cleaned up in here, I'm going to merge this and polish the rest in sd/beta-20. |
PlotList
recipe which plots arbitrary arrays of PlotSpecPlotList
recipe which plots arbitrary arrays of PlotSpec
Continues #2831 ! Still needs to check, if I rebased correctly and didn't incorrectly apply some of the changes! ## Merged PRs - #2598 - #2746 - #2346 - #2544 - #3082 - #2868 - #3062 - #3106 - #3281 - #3246 ## TODOS - [x] fix flaky test `@test GLMakie.window_size(screen.glscreen) == scaled(screen, (W, H))` - [x] Merge axis type inferences from #2220 - [x] Test on different resolution screens, IJulia, Pluto, VSCode, Windowed - [x] rebase to only have merge commits from the PRs - [x] investigate unexpected speed ups - [x] reset camera settings from tests - [ ] check doc image generation - [x] rethink default near/far in Camera3D (compatability with OIT) - [x] merge #3246 - [x] fix WGLMakie issues/tests: - [x] fix line depth issues (see tests: ~~hexbin colorrange~~ (not new), LaTeXStrings in Axis3, Axis3 axis reversal) - [x] fix lighting of surface with nan points (fixed in #3246) - ~~volume/3D contour artifacts (see 3D Contour with 2D contour slices)~~ not new - ~~artifacting in "colorscale (lines)"~~ not new - [x] GLMakie: - [x] slight outline in "scatter image markers" test - ~~clipping/z-fighting in "volume translated"~~ not new - [x] CairoMakie: - ~~Artfiacting in `colorscale (lines)"~~ not new - ~~markersize in "scatter rotations" changed?~~ not new - ~~color change in "colorscale (poly)"~~ not new - ~~transparency/render order of "OldAxis + Surface"~~ not new - ~~render order in "Merged color mesh"~~ not new - ~~render order of "Surface + wireframe + contour"~~ not new - [x] Check "SpecApi in convert_arguments" (colors swapped?) ## Fixes the following errors - fixes #2721 via #2746 - fixes #1600 via #2746 - fixes #1236 via #2746 - fixes MakieOrg/GeoMakie.jl#133 via #2598 - closes #2522 - closes #3239 via #3246 - fixes #3238 via #3246 - fixes #2985 via #3246 - fixes #3307 via #3281
Description
As discussed in MakieCon 2023 Day 1...will add an example in a bit.
This currently takes the form of a recipe, but we could make it a normal function which is just passed an Observable list of PlotSpec.
Type of change
Delete options that do not apply:
Checklist