Skip to content

Commit

Permalink
several improvements: NetView has Current button to get current net d…
Browse files Browse the repository at this point in the history
…ata; ViewUpdt has SkipInvis flag -- default is to record data when invisible - not that much slower; Log records counters from higher levels by default; looper has SkipToMax for variable timing.
  • Loading branch information
Randall C. O'Reilly committed Feb 20, 2023
1 parent 8872da9 commit 17e2f92
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 25 deletions.
11 changes: 9 additions & 2 deletions elog/stditems.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,26 @@ import (
// AddCounterItems adds given Int counters from Stats,
// typically by recording looper counter values to Stats.
func (lg *Logs) AddCounterItems(ctrs ...etime.Times) {
for _, ctr := range ctrs {
for ci, ctr := range ctrs {
ctrName := ctr.String() // closure
tm := etime.AllTimes
if ctr < etime.Epoch {
tm = ctr
}
lg.AddItem(&Item{
itm := lg.AddItem(&Item{
Name: ctrName,
Type: etensor.INT64,
Write: WriteMap{
etime.Scope(etime.AllModes, tm): func(ctx *Context) {
ctx.SetStatInt(ctrName)
}}})
if ctr < etime.Epoch {
for ti := ci + 1; ti < len(ctrs); ti++ {
itm.Write[etime.Scope(etime.AllModes, ctrs[ti])] = func(ctx *Context) {
ctx.SetStatInt(ctrName)
}
}
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions looper/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ func (ct *Ctr) Incr() {
ct.Cur++
}

// SkipToMax sets the counter to its Max value -- for skipping over rest of loop
func (ct *Ctr) SkipToMax() {
ct.Cur = ct.Max
}

// IsOverMax returns true if counter is at or over Max (only if Max > 0)
func (ct *Ctr) IsOverMax() bool {
return ct.Max > 0 && ct.Cur >= ct.Max
Expand Down
18 changes: 12 additions & 6 deletions looper/loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,31 @@ type Loop struct {
}

// AddEvents to the list of events.
func (loops *Loop) AddEvents(events ...*Event) {
func (lp *Loop) AddEvents(events ...*Event) {
for _, event := range events {
loops.Events = append(loops.Events, event)
lp.Events = append(lp.Events, event)
}
}

// AddNewEvent to the list.
func (loops *Loop) AddNewEvent(name string, atCtr int, fun func()) *Event {
func (lp *Loop) AddNewEvent(name string, atCtr int, fun func()) *Event {
ev := NewEvent(name, atCtr, fun)
loops.Events = append(loops.Events, ev)
lp.Events = append(lp.Events, ev)
return ev
}

// EventByName returns event by name, false if not found
func (loops *Loop) EventByName(name string) (*Event, bool) {
for _, ev := range loops.Events {
func (lp *Loop) EventByName(name string) (*Event, bool) {
for _, ev := range lp.Events {
if ev.Name == name {
return ev, true
}
}
return nil, false
}

// SkipToMax sets the counter to its Max value for this level.
// for skipping over rest of loop
func (lp *Loop) SkipToMax() {
lp.Counter.SkipToMax()
}
18 changes: 17 additions & 1 deletion netview/netview.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ func (nv *NetView) HasLayers() bool {
return true
}

// RecordCounters saves the counters, so they are available for a Current update
func (nv *NetView) RecordCounters(counters string) {
nv.DataMu.Lock()
defer nv.DataMu.Unlock()
if counters != "" {
nv.LastCtrs = counters
}
}

// Record records the current state of the network, along with provided counters
// string, which is displayed at the bottom of the view to show the current
// state of the counters. The rastCtr is the raster counter value used for
Expand Down Expand Up @@ -845,13 +854,20 @@ func (nv *NetView) ToolbarConfig() {
return
}
tbar.SetStretchMaxWidth()
tbar.AddAction(gi.ActOpts{Label: "Init", Icon: "update", Tooltip: "fully redraw display"}, nv.This(),
tbar.AddAction(gi.ActOpts{Label: "Init", Icon: "update", Tooltip: "fully reconfigure and redraw the display -- does not record any new data from the network (see Current button) -- should not be needed in general"}, nv.This(),
func(recv, send ki.Ki, sig int64, data interface{}) {
nvv := recv.Embed(KiT_NetView).(*NetView)
nvv.Config()
nvv.Update()
nvv.VarsUpdate()
})
tbar.AddAction(gi.ActOpts{Label: "Current", Icon: "update", Tooltip: "grab the current state of the network, including synaptic values, and display it -- use this when switching to NetView tab after network has been running, because network state not recored then."}, nv.This(),
func(recv, send ki.Ki, sig int64, data interface{}) {
nvv := recv.Embed(KiT_NetView).(*NetView)
nvv.Record("", -1)
nvv.RecordSyns()
nvv.Update()
})
tbar.AddAction(gi.ActOpts{Label: "Config", Icon: "gear", Tooltip: "set parameters that control display (font size etc)"}, nv.This(),
func(recv, send ki.Ki, sig int64, data interface{}) {
nvv := recv.Embed(KiT_NetView).(*NetView)
Expand Down
56 changes: 40 additions & 16 deletions netview/viewupdt.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import (

// ViewUpdt manages time scales for updating the NetView
type ViewUpdt struct {
View *NetView `view:"-" desc:"the network view"`
Testing bool `view:"-" desc:"whether in testing mode -- can be set in advance to drive appropriate updating"`
Text string `view:"-" desc:"text to display at the bottom of the view"`
On bool `desc:"toggles update of display on"`
Train etime.Times `desc:"at what time scale to update the display during training?"`
Test etime.Times `desc:"at what time scale to update the display during testing?"`
View *NetView `view:"-" desc:"the network view"`
Testing bool `view:"-" desc:"whether in testing mode -- can be set in advance to drive appropriate updating"`
Text string `view:"-" desc:"text to display at the bottom of the view"`
On bool `desc:"toggles update of display on"`
SkipInvis bool `desc:"if true, do not record network data when the NetView is invisible -- this speeds up running when not visible, but the NetView display will not show the current state when switching back to it"`
Train etime.Times `desc:"at what time scale to update the display during training?"`
Test etime.Times `desc:"at what time scale to update the display during testing?"`
}

// Config configures for given NetView and default train, test times
Expand All @@ -39,31 +40,43 @@ func (vu *ViewUpdt) UpdtTime(testing bool) etime.Times {
// Update does an update if view is On, visible and active,
// including recording new data and driving update of display
func (vu *ViewUpdt) Update() {
if !vu.On || vu.View == nil || !vu.View.IsVisible() {
if !vu.On || vu.View == nil {
return
}
if !vu.View.IsVisible() && vu.SkipInvis {
vu.View.RecordCounters(vu.Text)
return
}
vu.View.Record(vu.Text, -1) // -1 = use a dummy counter
// note: essential to use Go version of update when called from another goroutine
vu.View.GoUpdate()
if vu.View.IsVisible() {
vu.View.GoUpdate()
}
}

// UpdateWhenStopped does an update when the network updating was stopped
// either via stepping or hitting the stop button -- this has different
// logic for the raster view vs. regular.
func (vu *ViewUpdt) UpdateWhenStopped() {
if !vu.On || vu.View == nil || !vu.View.IsVisible() {
if !vu.On || vu.View == nil {
return
}
if !vu.View.IsVisible() && vu.SkipInvis {
vu.View.RecordCounters(vu.Text)
return
}
if !vu.View.Params.Raster.On { // always record when not in raster mode
vu.View.Record(vu.Text, -1) // -1 = use a dummy counter
}
// note: essential to use Go version of update when called from another goroutine
vu.View.GoUpdate()
if vu.View.IsVisible() {
vu.View.GoUpdate()
}
}

// UpdateTime triggers an update at given timescale.
func (vu *ViewUpdt) UpdateTime(time etime.Times) {
if !vu.On || vu.View == nil || !vu.View.IsVisible() {
if !vu.On || vu.View == nil {
return
}
viewUpdt := vu.UpdtTime(vu.Testing)
Expand All @@ -73,7 +86,9 @@ func (vu *ViewUpdt) UpdateTime(time etime.Times) {
if viewUpdt < etime.Trial && time == etime.Trial {
if vu.View.Params.Raster.On { // no extra rec here
vu.View.Data.RecordLastCtrs(vu.Text)
vu.View.GoUpdate()
if vu.View.IsVisible() {
vu.View.GoUpdate()
}
} else {
vu.Update()
}
Expand All @@ -84,7 +99,7 @@ func (vu *ViewUpdt) UpdateTime(time etime.Times) {
// IsCycleUpdating returns true if the view is updating at a cycle level,
// either from raster or literal cycle level.
func (vu *ViewUpdt) IsCycleUpdating() bool {
if !vu.On || vu.View == nil || !vu.View.IsVisible() {
if !vu.On || vu.View == nil || !(vu.View.IsVisible() || !vu.SkipInvis) {
return false
}
viewUpdt := vu.UpdtTime(vu.Testing)
Expand All @@ -102,7 +117,7 @@ func (vu *ViewUpdt) IsCycleUpdating() bool {

// IsViewingSynapse returns true if netview is actively viewing synapses.
func (vu *ViewUpdt) IsViewingSynapse() bool {
if !vu.On || vu.View == nil || !vu.View.IsVisible() {
if !vu.On || vu.View == nil || !(vu.View.IsVisible() || !vu.SkipInvis) {
return false
}
vvar := vu.View.Var
Expand All @@ -115,7 +130,7 @@ func (vu *ViewUpdt) IsViewingSynapse() bool {
// UpdateCycle triggers an update at the Cycle (Millisecond) timescale,
// using given text to display at bottom of view
func (vu *ViewUpdt) UpdateCycle(cyc int) {
if !vu.On || vu.View == nil || !vu.View.IsVisible() {
if !vu.On || vu.View == nil {
return
}
viewUpdt := vu.UpdtTime(vu.Testing)
Expand Down Expand Up @@ -154,6 +169,10 @@ func (vu *ViewUpdt) UpdateCycle(cyc int) {

// UpdateCycleRaster raster version of Cycle update
func (vu *ViewUpdt) UpdateCycleRaster(cyc int) {
if !vu.View.IsVisible() && vu.SkipInvis {
vu.View.RecordCounters(vu.Text)
return
}
viewUpdt := vu.UpdtTime(vu.Testing)
vu.View.Record(vu.Text, cyc)
switch viewUpdt {
Expand Down Expand Up @@ -188,8 +207,13 @@ func (vu *ViewUpdt) UpdateCycleRaster(cyc int) {
// updating Wts and zeroing.
// NetView displays this recorded data when Update is next called.
func (vu *ViewUpdt) RecordSyns() {
if !vu.On || vu.View == nil || !vu.View.IsVisible() {
if !vu.On || vu.View == nil {
return
}
if !vu.View.IsVisible() {
if vu.SkipInvis || !vu.IsViewingSynapse() {
return
}
}
vu.View.RecordSyns()
}

0 comments on commit 17e2f92

Please sign in to comment.