using Observables using AbstractPlotting scene3d = Scene() rs = LinRange.(0, (6, 4, 10), 150) slider_t = slider(LinRange(0.1, 3, 100)) # This actually needs to be pretty fast... Lucky for us, we use Julia :) function make_volume!(rs, val, result = zeros(Float32, length.(rs)), r = rand(Float32, size(result)) .* 0.1) @simd for idx in CartesianIndices(result) @inbounds begin x, y, z = getindex.(rs, Tuple(idx)) result[idx] = cos(x/val) * sin(y + r[idx]) + sqrt(z*val) end end return result, r end vol_tmp, r_tmp = make_volume!(rs, 0.4); volume = lift(Observables.async_latest(slider_t[end][:value])) do val v, r = make_volume!(rs, val, vol_tmp, r_tmp); return v end linesegments!(scene3d, FRect3D(minimum.(rs), maximum.(rs))) planes = (:yz, :xz, :xy) sliders = ntuple(3) do i idx_s = slider(1:size(volume[], i), start = size(volume[], i) รท 2) idx = idx_s[end][:value] plane = planes[i] indices = ntuple(3) do j planes[j] == plane ? 1 : (:) end ridx = Iterators.filter((1, 2, 3)) do j planes[j] != plane end heatm = heatmap!( scene3d, getindex.((rs,), ridx)..., volume[][indices...], interpolate = true, raw = true )[end] function transform_planes(idx, vol) transform!(heatm, (plane, rs[i][idx])) indices = ntuple(3) do j planes[j] == plane ? idx : (:) end if checkbounds(Bool, vol, indices...) heatm[3][] = view(vol, indices...) end end onany(transform_planes, idx, volume) transform_planes(idx[], volume[]) idx_s end center!(scene3d) scene = vbox( hbox(slider_t, sliders...), hbox( scene3d, contour(volume, alpha = 0.1, levels = 10) ) ) # Do not execute beyond this point! RecordEvents(scene, "output")