How to do "reactive conditional plotting" in Makie recipes?

I want to show a plot in the recipe if any condition is true and do something else otherwise, maybe another plot, or do nothing in the case of my MWE.

How can I do this in Makie recipes?

MWE:

using Makie
using GLMakie

@recipe(RectPlot, a, b) do scene
  Attributes(
    color=:skyblue,
    showsegs=false,
    segcolor=:black,
    segwidth=3
  )
end

function Makie.plot!(plot::RectPlot)
  a = @lift Vec($(plot.a))
  b = @lift Vec($(plot.b))
  rect = @lift Rect($a, $b)
  poly!(plot, rect, color=plot.color)

  # how to make this code reactive?
  if plot.showsegs[]
    segs = @lift segments($a, $b)
    linesegments!(plot, segs, color=plot.segcolor, linewidth=plot.segwidth)
  end
end

function segments(a::Vec2, b::Vec2)
  a1, a2 = a
  b1, b2 = b
  p1 = Point2(a1, a2)
  p2 = Point2(b1, a2)
  p3 = Point2(b1, b2)
  p4 = Point2(a1, b2)
  [(p1, p2), (p2, p3), (p3, p4), (p4, p1)]
end

# works
rectplot((0, 0), (1, 1), showsegs=true)

# testing with observable
showsegs = Observable(false)

rectplot((0, 0), (1, 1); showsegs)

# doesn't update the plot
showsegs[] = true
1 Like

Set the plot’s visible attribute to false to hide it.

1 Like

Thank you! This is the solution:

function Makie.plot!(plot::RectPlot)
  a = @lift Vec($(plot.a))
  b = @lift Vec($(plot.b))
  rect = @lift Rect($a, $b)
  poly!(plot, rect, color=plot.color)

  segs = @lift segments($a, $b)
  segplot = linesegments!(plot, segs, color=plot.segcolor, linewidth=plot.segwidth)

  on(plot.showsegs, update=true) do show
    segplot.visible[] = show
  end
end
1 Like

Just do visible = plot.showsegs

1 Like

Thanks Julius!
The code:

function Makie.plot!(plot::RectPlot)
  a = @lift Vec($(plot.a))
  b = @lift Vec($(plot.b))
  rect = @lift Rect($a, $b)
  poly!(plot, rect, color=plot.color)

  segs = @lift segments($a, $b)
  segplot = linesegments!(plot, segs, color=plot.segcolor, linewidth=plot.segwidth)
  segplot.visible = plot.showsegs
end

There is a problem with this solution though: the plot is still performed before it gets hidden. It means that extra computation is done and thrown away.

Is there any alternative solution to this that doesn’t involve dispatching the code to hide later?

Probably using the spec api, plot an observable vector of plot specs with either one or zero elements.