JuliaGizmos / Interact.jl

Interactive widgets to play with your Julia code
Other
521 stars 76 forks source link

Kernel dies when different widgets trigger off the same Observable? #269

Open ma-laforge opened 6 years ago

ma-laforge commented 6 years ago

Background

I am providing an Interact-ive notebook to design filters with plots.

I start by defining Observables directly bo make it easier to define variables, then I tie them to widgets for the user to control:

using Interact

#Practical/easier to read: define variables as pure Observables...
fmax = Observable(Float64(10)) #Maximum plot frequency
fz1 = Observable(Float64(fmax[])) #Zero frequency
fp1 = Observable(Float64(fmax[]/2)) #Pole frequency

#Want max frequency to change as "fmax" changes
function frequency_slider(sig::Observable, fmax::Observable; label::String="")
    _fmin = 1e-3
    #NOTE: Limit max value to 2_fmin to avoid issues:
    return map((_fmax)->slider(_fmin:1e-3:max(_fmax,2*_fmin), value=sig, label=label), fmax)
end

txt_fmax = textbox(value=fmax, label="max freq")
sld_fz1 = frequency_slider(fz1, fmax, label="zero #1")
sld_fp1 = frequency_slider(fp1, fmax, label="pole #1")
#Add more poles/zeros...

map(display, [fmax, txt_fmax, sld_fz1, sld_fp1])
nothing

Note that the maximum value of the frequency sliders are guarded to avoid invalid slider ranges.

Problem

Though I have not problem creating the two sliders (sld_fz1 & sld_fz1), My IJulia kernel dies if I also define txt_fmax (to control fmax directly).

Am I doing something wrong here? How should I fix this?.... Or is it simply a bug in Interact.jl?

NOTE: I want the user to have control over the maximum frequency... so they have adequate control in the kHz... or the THz range.

ma-laforge commented 6 years ago

Side comment

I would actually prefer just changing the range of sld_fz1 & sld_fp1 - instead of "spawning" new ones with the map() command every time fmax changes.

This used to be possible with Interact.jl on Julia 0.6.x... but I no longer seem to have access to Slider.range anymore.

If someone can tell me how to only update the range - instead spawning new sliders (at least that's what I believe is happening) - that would be greatly appreciated.

piever commented 6 years ago

Interact underwent a rather radical change. Instead of using ipywidgets (available only in the notebook) it now uses pure HTML5 widgets and uses WebIO to communicate data to them: as a result some of the API changed. In this case the crash is because textbox returns an observable of String: to get a number you need spinbox. I guess one could argue that if you pass a number to textbox it could maybe figure out automatically that you want a spinbox, we'll need to decide on that one, but for now you can use:

txt_fmax = spinbox(value=fmax, label="max freq")
sld_fz1 = frequency_slider(fz1, fmax, label="zero #1")
sld_fp1 = frequency_slider(fp1, fmax, label="pole #1")

There's updated documentation about the currently available widgets here.

Concerning the side comment, I completely agree. It's not ideal to respawn the slider every time you change fmax. I've been meaning to allow Interact sliders to take an Observable as range, but haven't found the time yet (see https://github.com/piever/InteractBase.jl/issues/48).

ma-laforge commented 6 years ago

Excellent, thanks! I was not thinking of using the spinbox. I thought that passing an Observable{Float64} meant that textbox had to output a Float64 - because I assumed (incorrectly) that the Observable did not mutate... only what it pointed to could change.

Also: Good to know about Issue 48. I will be looking out for future updates (but I can make it work for now).