@@ -44,37 +44,46 @@ function timeseries_col(app, session)
4444end
4545
4646function timeseries_cards (app, session)
47- # we store the cards based on objid of TSPlot, otherwise overwrite with same key
48- # leads to problems
49- cards = OrderedDict {UInt, Bonito.Hyperscript.Node{Bonito.Hyperscript.HTMLSVG}} ()
50- observables = OrderedDict {UInt, Vector{Observables.ObserverFunction}} ()
5147 container = Observable {Bonito.Hyperscript.Node{Bonito.Hyperscript.HTMLSVG}} ()
5248
49+ # update the timeseries-sstacke based on the tsplots in appstate
5350 on (app. tsplots; update= true ) do _tsplots
5451 @debug " TS: app.tsplots => update timeseries cards"
55- id_to_key = Dict (Base. objectid (val) => key for (key, val) in _tsplots)
56- newids = Base. objectid .(values (_tsplots)) # collect to preserv order on setdiff
57- knownids = keys (cards)
58-
59- for delid in setdiff (knownids, newids)
60- Observables. off .(observables[delid]) # deactivate allobservables from card
61- delete! (observables, delid)
62- delete! (cards, delid)
52+ # this cache contains all the card, the observer functions and the plotqueue
53+ cache = app. _tsplotscache
54+
55+ known_tsplots = collect (keys (cache))
56+ current_tsplots = collect (values (_tsplots))
57+
58+ # do nothing if the TSPlots objects themselve did not change
59+ Set (known_tsplots) == Set (current_tsplots) && return
60+
61+ # del_tsplots = setdiff(known_tsplots, current_tsplots)
62+ # new_tsplots = setdiff(current_tsplots, known_tsplots)
63+ # FIXME : it is not possible to redisplay the same tsplot, recreate all
64+ del_tsplots = known_tsplots
65+ new_tsplots = current_tsplots
66+
67+ for del in del_tsplots
68+ (; card, observerfunctions, plotqueue) = cache[del]
69+ close (plotqueue) # close plotqueue
70+ Observables. off .(observerfunctions) # disable all observer functions
71+ delete! (cache, del) # delete from cache
6372 end
64- for newid in setdiff (newids, knownids)
65- card, obsf = timeseries_card (app, id_to_key[newid], session)
66- cards[newid] = card
67- observables[newid] = obsf
68- end
69- if collect (keys (cards)) != newids
70- @warn " The keys do not match: $(keys (cards)) vs $(newids) "
73+ for new in new_tsplots
74+ key = only ([key for (key, value) in _tsplots if value == new])
75+ ntup = timeseries_card (app, key, session)
76+ cache[new] = ntup
7177 end
7278
73- container[] = DOM. div (values (cards)... ; class= " timeseries-stack" )
79+ cards = [cache[ts]. card for ts in values (_tsplots)]
80+ # update the display by notifying the content
81+ container[] = DOM. div (cards; class= " timeseries-stack" )
7482
7583 nothing
7684 end
7785
86+ # update the selected components in the graphplot when the active tsplot changes
7887 on (app. active_tsplot; update= true ) do active
7988 activesel = app. tsplots[][active]. selcomp[]
8089 app. graphplot. _selcomp[] = activesel
@@ -303,6 +312,7 @@ function timeseries_card(app, key, session)
303312 ts = Observable (collect (range (app. sol[]. t[begin ], app. sol[]. t[end ], length= 1000 )))
304313 refined_xlims = Ref ((NaN , NaN ))
305314 onany_delayed (ax. finallimits; delay= 0.5 ) do axlims
315+ @debug " $key : Adapt ts vector"
306316 sollims = (app. sol[]. t[begin ], app. sol[]. t[end ])
307317 xlims = (axlims. origin[1 ], axlims. origin[1 ] + axlims. widths[1 ])
308318 if xlims != refined_xlims[]
@@ -354,34 +364,37 @@ function timeseries_card(app, key, session)
354364
355365 replot = Observable {Nothing} (nothing )
356366
367+ # create queue for async plot updates
368+ plotqueue = _plot_queue (key)
369+
357370 # store the idxs for which the autolmits where last set
358371 last_autolimits = Ref ((eltype (valid_idxs)(), tsplot. rel[]))
359372 # plot the thing
360373 onany (data, replot; update= true ) do _dat, _
361- task = @async begin
374+ task = @task begin
375+ @debug " $key : Launch plot for valid_idxs[]"
362376 try
363377 empty! (ax)
364378 vlines! (ax. scene, app. t; color= :black )
365379 for (idx, y) in zip (valid_idxs[], data[])
366380 color = begin
367- key = idx isa VIndex ? VIndex (idx. compidx) : EIndex (idx. compidx)
368- getcycled (COLORS, color_cache[key ])
381+ idxkey = idx isa VIndex ? VIndex (idx. compidx) : EIndex (idx. compidx)
382+ getcycled (COLORS, color_cache[idxkey ])
369383 end
370384 linestyle = getcycled (LINESTYLES, linestyle_cache[idx. subidx])
371385 lines! (ax. scene, ts[], y; label= string (idx), color, linestyle)
372386 # scatterlines!(ax, ts[], y; label=string(idx), color, linestyle)
373387 end
374- # if last_autolimits[][1] != valid_idxs[] || last_autolimits[][2] != tsplot.rel[]
375388 if last_autolimits[] != (valid_idxs[], tsplot. rel[])
376389 autolimits! (ax)
377390 xlims! (ax, (app. tmin[], app. tmax[]))
378391 last_autolimits[] = (copy (valid_idxs[]), tsplot. rel[])
379392 end
380393 catch e
381- @error " Plotting failed" e
394+ @error " $key : Plotting failed for idx $(valid_idxs[]) " e
382395 end
383396 end
384- push! (app . _plotqueue , task)
397+ put! (plotqueue , task)
385398 nothing
386399 end |> track_obsf
387400
@@ -432,8 +445,31 @@ function timeseries_card(app, key, session)
432445 id= key
433446 )
434447
435- return card, obsf
448+ return (card, observerfunctions= obsf, plotqueue)
449+ end
450+ function _plot_queue (key)
451+ ch = Channel {Task} (Inf ; spawn= true ) do ch
452+ while isopen (ch)
453+ t = try
454+ fetch (ch)
455+ catch e
456+ if ! e isa InvalidStateException && e. msg == " Channel is closed."
457+ @error " $key : Error while waiting for Task: $e "
458+ end
459+ break
460+ end
461+ try
462+ wait (schedule (t))
463+ catch e
464+ @warn " $key : Error in task: $e "
465+ end
466+ rmt = take! (ch) # remove the executed task
467+ @assert istaskdone (rmt)
468+ end
469+ @info " Plot queue for $key closed"
470+ end
436471end
472+
437473function closebutton (app, key)
438474 button = Bonito. Button (" ×" , class= " close-button" )
439475 on (button. value) do _
0 commit comments