@@ -36,7 +36,8 @@ function apptheme()
36
36
linestyle = [:solid , :dot , :dash , :dashdot , :dashdotdot ],
37
37
),
38
38
Lines = (;
39
- cycle = Cycle ([:color , :linestyle ], covary= true )
39
+ cycle = Cycle ([:color , :linestyle ], covary= true ),
40
+ linewidth = 3 ,
40
41
)
41
42
)
42
43
end
@@ -518,19 +519,22 @@ function timeseries_card(app, key, session)
518
519
T= Symbol,
519
520
id= gendomid (" statesel" ))
520
521
521
- reset_button = Bonito. Button (" Reset Color" , style= Styles (" margin-left" => " 10px" ))
522
- on (reset_button . value) do _
522
+ reset_color_button = Bonito. Button (" Reset Color" , style= Styles (" margin-left" => " 10px" ))
523
+ on (reset_color_button . value) do _
523
524
empty! (color_cache)
524
525
empty! (linestyle_cache)
525
526
notify (tsplot. selcomp)
526
527
notify (tsplot. states)
527
528
end
528
529
530
+ reset_axis_button = Bonito. Button (" Reset Axis" , style= Styles (" margin-left" => " 10px" ))
531
+
529
532
rel_toggle = ToggleSwitch (value= tsplot. rel, label= " Rel to u0" )
530
533
531
534
comp_state_sel_dom = Grid (
532
- DOM. span (" Components" ), comp_sel, reset_button,
533
- DOM. span (" States" ), state_sel, rel_toggle;
535
+ DOM. span (" Components" ), comp_sel,
536
+ DOM. div (reset_color_button, reset_axis_button, rel_toggle; style= Styles (" grid-row" => " 1/3" , " grid-column" => " 3" )),
537
+ DOM. span (" States" ), state_sel;
534
538
columns = " min-content auto min-content" ,
535
539
align_items = " center" ,
536
540
class = " comp-state-sel-grid"
@@ -548,7 +552,7 @@ function timeseries_card(app, key, session)
548
552
# ###
549
553
COLORS = Makie. wong_colors ()
550
554
LINESTYLES = [:solid , :dot , :dash , :dashdot , :dashdotdot ]
551
- LINESTYLES = [" ─" , " ⋯" , " --" , " -⋅-" , " -⋅⋅" ]
555
+ LINESTYLES_STR = [" ─" , " ⋯" , " --" , " -⋅-" , " -⋅⋅" ]
552
556
color_cache = Dict {Union{EIndex{Int,Nothing},VIndex{Int,Nothing}}, Int} ()
553
557
linestyle_cache = Dict {Symbol,Int} ()
554
558
@@ -578,7 +582,7 @@ function timeseries_card(app, key, session)
578
582
i = _smallest_free (linestyle_cache)
579
583
linestyle_cache[new] = i
580
584
end
581
- lstylepairs[] = [(; title= repr (s), linestyle= getcycled (LINESTYLES , i))
585
+ lstylepairs[] = [(; title= repr (s), linestyle= getcycled (LINESTYLES_STR , i))
582
586
for (s,i) in linestyle_cache]
583
587
nothing
584
588
end
@@ -606,7 +610,7 @@ function timeseries_card(app, key, session)
606
610
styleContent += ` #$(comp_ms_id) +span li[title='${ title} ']::after {
607
611
content: 'xx';
608
612
display: inline-block;
609
- padding: 0px 4px ;
613
+ padding: 0px 1px ;
610
614
background-color: ${ color} !important;
611
615
color: ${ color} !important;
612
616
border-left: 1px solid #aaa;
@@ -644,7 +648,7 @@ function timeseries_card(app, key, session)
644
648
styleContent += ` #$(state_ms_id) +span li[title='${ title} ']::after {
645
649
content: '${ linestyle} ';
646
650
display: inline-block;
647
- padding: 0px 4px ;
651
+ padding: 0px 1px ;
648
652
color: inherit;
649
653
border-left: 1px solid #aaa;
650
654
font-size: smaller;
@@ -676,27 +680,18 @@ function timeseries_card(app, key, session)
676
680
nothing
677
681
end
678
682
679
- ts = Observable (range (app. sol[]. t[begin ], app. sol[]. t[end ], length= 1000 ))
680
- # last update of ts range
681
- lastupdate = Ref (time ())
682
- on (ax. finallimits) do lims
683
- lastupdate[] = time ()
683
+ ts = Observable (collect (range (app. sol[]. t[begin ], app. sol[]. t[end ], length= 1000 )))
684
+ refined_xlims = Ref ((NaN , NaN ))
685
+ onany_delayed (ax. finallimits; delay= 0.5 ) do axlims
686
+ sollims = (app. sol[]. t[begin ], app. sol[]. t[end ])
687
+ xlims = (axlims. origin[1 ], axlims. origin[1 ] + axlims. widths[1 ])
688
+ if xlims != refined_xlims[]
689
+ refined_xlims[] = xlims
690
+ refine_time_limits! (ts[], sollims, xlims)
691
+ notify (ts)
692
+ end
684
693
nothing
685
694
end
686
- # every 0.5 seconds trigger resampling
687
- # timer = Timer(.5; interval=.5) do _
688
- # if time() > lastupdate[] + 0.5
689
- # lims = ax.finallimits[]
690
- # tmin = max(app.sol[].t[begin], lims.origin[1])
691
- # tmax = min(app.sol[].t[end], tmin + lims.widths[1])
692
- # ts[] = range(tmin, tmax, length=1000)
693
- # lastupdate[] = Inf
694
- # end
695
- # end
696
- # on(session.on_close) do _
697
- # @info "Session closed, time to clean up"
698
- # # close(timer)
699
- # end
700
695
701
696
# collect all the states wie might want to plot
702
697
valid_idxs = Observable (
@@ -731,19 +726,29 @@ function timeseries_card(app, key, session)
731
726
notify (data)
732
727
end
733
728
729
+ replot = Observable {Nothing} (nothing )
730
+
731
+ # store the idxs for which the autolmits where last set
732
+ last_autolimits = Ref ((eltype (valid_idxs)(), tsplot. rel[]))
734
733
# plot the thing
735
- on (data; update = true ) do _dat
734
+ onany (data, replot ) do _dat, _
736
735
@async begin
737
736
try
738
737
empty! (ax)
739
- vlines! (ax, app. t; color= :black )
738
+ vlines! (ax. scene , app. t; color= :black )
740
739
for (idx, y) in zip (valid_idxs[], data[])
741
740
color = begin
742
741
key = idx isa VIndex ? VIndex (idx. compidx) : EIndex (idx. compidx)
743
- Cycled ( color_cache[key])
742
+ getcycled (COLORS, color_cache[key])
744
743
end
745
- linestyle = Cycled (linestyle_cache[idx. subidx])
746
- lines! (ax, ts[], y; label= string (idx), color, linestyle)
744
+ linestyle = getcycled (LINESTYLES, linestyle_cache[idx. subidx])
745
+ lines! (ax. scene, ts[], y; label= string (idx), color, linestyle)
746
+ # scatterlines!(ax, ts[], y; label=string(idx), color, linestyle)
747
+ end
748
+ # if last_autolimits[][1] != valid_idxs[] || last_autolimits[][2] != tsplot.rel[]
749
+ if last_autolimits[] != (valid_idxs[], tsplot. rel[])
750
+ autolimits! (ax)
751
+ last_autolimits[] = (copy (valid_idxs[]), tsplot. rel[])
747
752
end
748
753
catch e
749
754
@error " Plotting failed" e
@@ -752,6 +757,10 @@ function timeseries_card(app, key, session)
752
757
nothing
753
758
end
754
759
760
+ on (reset_axis_button. value) do _
761
+ autolimits! (ax)
762
+ end
763
+
755
764
# ###
756
765
# ### Click interaction to set time
757
766
# ###
@@ -780,8 +789,20 @@ function timeseries_card(app, key, session)
780
789
class= cardclass
781
790
)
782
791
792
+
793
+ # trigger plot on document ready
794
+ jqdocument = Bonito. JSString (raw " $(document)" )
795
+ trigger_plot = js """
796
+ $ (jqdocument).ready (function (){
797
+ console .log (" Document ready, trigger plot" );
798
+ // $(data).notify();
799
+ $ (replot).notify ();
800
+ });
801
+ """
802
+ Bonito. evaljs (session, trigger_plot)
803
+
783
804
# on click set active-tseries class
784
- click = js """
805
+ onload_js = js """
785
806
(card ) => {
786
807
card .addEventListener (" click" , function (event ) {
787
808
$ (app .active_tsplot ).notify ($ (key));
@@ -795,11 +816,46 @@ function timeseries_card(app, key, session)
795
816
}, { capture: true });
796
817
}
797
818
"""
798
- Bonito. onload (session, card, click )
819
+ Bonito. onload (session, card, onload_js )
799
820
800
821
return card
801
822
end
802
823
824
+ function refine_time_limits! (ts, sollims, axlims)
825
+ FOCUS = 900
826
+ UNFOCUS = 100
827
+ if length (ts) != = FOCUS + UNFOCUS
828
+ @warn " Resize ts, lenght $(length (ts)) != $(FOCUS + UNFOCUS) "
829
+ resize! (ts, FOCUS + UNFOCUS)
830
+ end
831
+ # never plot outside of solution
832
+ axlims = (max (axlims[1 ], sollims[1 ]), min (axlims[2 ], sollims[2 ]))
833
+
834
+ axrange = range (axlims[1 ], axlims[2 ], length= FOCUS)
835
+ outer_low = max (0 , axlims[1 ] - sollims[1 ])
836
+ outer_high = max (0 , sollims[2 ] - axlims[2 ])
837
+
838
+ if outer_low == 0
839
+ high_range = range (sollims[2 ], axlims[2 ], length= UNFOCUS+ 1 )[2 : end ]
840
+ ts[1 : FOCUS] .= axrange
841
+ ts[FOCUS+ 1 : end ] .= high_range
842
+ elseif outer_high == 0
843
+ low_range = range (axlims[1 ], sollims[1 ], length= UNFOCUS+ 1 )[1 : end - 1 ]
844
+ ts[1 : UNFOCUS] .= low_range
845
+ ts[UNFOCUS+ 1 : end ] .= axrange
846
+ else
847
+ N_LOW = round (Int, outer_low/ (outer_low + outer_high) * UNFOCUS)
848
+ N_HIGH = UNFOCUS - N_LOW
849
+ low_range = range (sollims[1 ], axlims[1 ], length= N_LOW+ 1 )[1 : end - 1 ]
850
+ high_range = range (axlims[2 ], sollims[2 ], length= N_HIGH+ 1 )[2 : end ]
851
+ ts[1 : N_LOW] .= low_range
852
+ ts[N_LOW+ 1 : N_LOW+ FOCUS] .= axrange
853
+ ts[N_LOW+ FOCUS+ 1 : end ] .= high_range
854
+ end
855
+ # ts .= range(axlims[1], axlims[2], length=1000)
856
+ nothing
857
+ end
858
+
803
859
function _sidx_to_str (s, app)
804
860
if s isa VIndex
805
861
" v$(s. compidx) "
0 commit comments