diff --git a/examples/deep_fsa/config.go b/examples/deep_fsa/config.go index 9ef362685..45e045f67 100644 --- a/examples/deep_fsa/config.go +++ b/examples/deep_fsa/config.go @@ -7,7 +7,7 @@ package main // EnvConfig has config params for environment // note: only adding fields for key Env params that matter for both Network and Env // other params are set via the Env map data mechanism. -type EnvConfig struct { //gti:add +type EnvConfig struct { // env parameters -- can set any field/subfield on Env struct, using standard TOML formatting Env map[string]any @@ -34,7 +34,7 @@ func (cfg *EnvConfig) InitNameMap() { } // ParamConfig has config parameters related to sim params -type ParamConfig struct { //gti:add +type ParamConfig struct { // network parameters Network map[string]any @@ -59,7 +59,7 @@ type ParamConfig struct { //gti:add } // RunConfig has config parameters related to running the sim -type RunConfig struct { //gti:add +type RunConfig struct { // use the GPU for computation -- generally faster even for small models if NData ~16 GPU bool `def:"true"` diff --git a/examples/deep_fsa/deep_fsa.go b/examples/deep_fsa/deep_fsa.go index ceea39a02..99dd90f27 100644 --- a/examples/deep_fsa/deep_fsa.go +++ b/examples/deep_fsa/deep_fsa.go @@ -6,7 +6,7 @@ // finite state automaton problem. package main -//go:generate goki generate +//go:generate goki generate -add-types import ( "log" @@ -52,7 +52,7 @@ func main() { // state information organized and available without having to pass everything around // as arguments to methods, and provides the core GUI interface (note the view tags // for the fields which provide hints to how things should be displayed). -type Sim struct { //gti:add +type Sim struct { // simulation configuration parameters -- set by .toml config file and / or args Config Config @@ -611,7 +611,7 @@ func (ss *Sim) ConfigNetView(nv *netview.NetView) { } // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Body { +func (ss *Sim) ConfigGUI() { title := "DeepAxon Finite State Automaton" ss.GUI.MakeBody(ss, "DeepFSA", title, `This demonstrates a basic DeepAxon model on the Finite State Automaton problem (e.g., the Reber grammar). See emergent on GitHub.

`) ss.GUI.CycleUpdateInterval = 10 @@ -674,13 +674,12 @@ func (ss *Sim) ConfigGUI() *gi.Body { ss.Net.GPU.Destroy() }) } - return ss.GUI.Body } func (ss *Sim) RunGUI() { ss.Init() - b := ss.ConfigGUI() - b.NewWindow().Run().Wait() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/deep_fsa/gtigen.go b/examples/deep_fsa/gtigen.go new file mode 100644 index 000000000..954b91d4c --- /dev/null +++ b/examples/deep_fsa/gtigen.go @@ -0,0 +1,156 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package main + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "main.EnvConfig", + ShortName: "main.EnvConfig", + IDName: "env-config", + Doc: "EnvConfig has config params for environment\nnote: only adding fields for key Env params that matter for both Network and Env\nother params are set via the Env map data mechanism.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Env", >i.Field{Name: "Env", Type: "map[string]any", LocalType: "map[string]any", Doc: "env parameters -- can set any field/subfield on Env struct, using standard TOML formatting", Directives: gti.Directives{}, Tag: ""}}, + {"UnitsPer", >i.Field{Name: "UnitsPer", Type: "int", LocalType: "int", Doc: "number of units per localist output unit -- 1 works better than 5 here", Directives: gti.Directives{}, Tag: "def:\"1\""}}, + {"InputNames", >i.Field{Name: "InputNames", Type: "[]string", LocalType: "[]string", Doc: "] names of input letters", Directives: gti.Directives{}, Tag: "def:\"['B','T','S','X','V','P','E']\""}}, + {"InputNameMap", >i.Field{Name: "InputNameMap", Type: "map[string]int", LocalType: "map[string]int", Doc: "map of input names -- initialized during Configenv", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- generally faster even for small models if NData ~16", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"NData", >i.Field{Name: "NData", Type: "int", LocalType: "int", Doc: "number of data-parallel items to process in parallel per trial -- works (and is significantly faster) for both CPU and GPU. Results in an effective mini-batch of learning. 16 learns just as well as 1 -- no diffs.", Directives: gti.Directives{}, Tag: "def:\"16\" min:\"1\""}}, + {"NThreads", >i.Field{Name: "NThreads", Type: "int", LocalType: "int", Doc: "number of parallel threads for CPU computation -- 0 = use default", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"Run", >i.Field{Name: "Run", Type: "int", LocalType: "int", Doc: "starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"NRuns", >i.Field{Name: "NRuns", Type: "int", LocalType: "int", Doc: "total number of runs to do when running Train", Directives: gti.Directives{}, Tag: "def:\"5\" min:\"1\""}}, + {"NEpochs", >i.Field{Name: "NEpochs", Type: "int", LocalType: "int", Doc: "total number of epochs per run", Directives: gti.Directives{}, Tag: "def:\"100\""}}, + {"NTrials", >i.Field{Name: "NTrials", Type: "int", LocalType: "int", Doc: "total number of trials per epoch. Should be an even multiple of NData.", Directives: gti.Directives{}, Tag: "def:\"196\""}}, + {"PCAInterval", >i.Field{Name: "PCAInterval", Type: "int", LocalType: "int", Doc: "how frequently (in epochs) to compute PCA on hidden representations to measure variance?", Directives: gti.Directives{}, Tag: "def:\"5\""}}, + {"TestInterval", >i.Field{Name: "TestInterval", Type: "int", LocalType: "int", Doc: "how often to run through all the test patterns, in terms of training epochs -- can use 0 or -1 for no testing", Directives: gti.Directives{}, Tag: "def:\"-1\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"SaveWts", >i.Field{Name: "SaveWts", Type: "bool", LocalType: "bool", Doc: "if true, save final weights after each run", Directives: gti.Directives{}, Tag: ""}}, + {"Epoch", >i.Field{Name: "Epoch", Type: "bool", LocalType: "bool", Doc: "if true, save train epoch log to file, as .epc.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Run", >i.Field{Name: "Run", Type: "bool", LocalType: "bool", Doc: "if true, save run log to file, as .run.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "bool", LocalType: "bool", Doc: "if true, save train trial log to file, as .trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestEpoch", >i.Field{Name: "TestEpoch", Type: "bool", LocalType: "bool", Doc: "if true, save testing epoch log to file, as .tst_epc.tsv typically. In general it is better to copy testing items over to the training epoch log and record there.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestTrial", >i.Field{Name: "TestTrial", Type: "bool", LocalType: "bool", Doc: "if true, save testing trial log to file, as .tst_trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Env", >i.Field{Name: "Env", Type: "github.com/emer/axon/examples/deep_fsa.EnvConfig", LocalType: "EnvConfig", Doc: "environment configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/deep_fsa.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/deep_fsa.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/deep_fsa.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/deep_fsa.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "all parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Loops", >i.Field{Name: "Loops", Type: "*github.com/emer/emergent/v2/looper.Manager", LocalType: "*looper.Manager", Doc: "contains looper control loops for running sim", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "Contains all the logs and information about the logs.'", Directives: gti.Directives{}, Tag: ""}}, + {"Envs", >i.Field{Name: "Envs", Type: "github.com/emer/emergent/v2/env.Envs", LocalType: "env.Envs", Doc: "Environments", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeeds", >i.Field{Name: "RndSeeds", Type: "github.com/emer/emergent/v2/erand.Seeds", LocalType: "erand.Seeds", Doc: "a list of random seeds to use for each run", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.FSAEnv", + ShortName: "main.FSAEnv", + IDName: "fsa-env", + Doc: "FSAEnv generates states in a finite state automaton (FSA) which is a\nsimple form of grammar for creating non-deterministic but still\noverall structured sequences.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Nm", >i.Field{Name: "Nm", Type: "string", LocalType: "string", Doc: "name of this environment", Directives: gti.Directives{}, Tag: ""}}, + {"Dsc", >i.Field{Name: "Dsc", Type: "string", LocalType: "string", Doc: "description of this environment", Directives: gti.Directives{}, Tag: ""}}, + {"TMat", >i.Field{Name: "TMat", Type: "goki.dev/etable/v2/etensor.Float64", LocalType: "etensor.Float64", Doc: "transition matrix, which is a square NxN tensor with outer dim being current state and inner dim having probability of transitioning to that state", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Labels", >i.Field{Name: "Labels", Type: "goki.dev/etable/v2/etensor.String", LocalType: "etensor.String", Doc: "transition labels, one for each transition cell in TMat matrix", Directives: gti.Directives{}, Tag: ""}}, + {"AState", >i.Field{Name: "AState", Type: "github.com/emer/emergent/v2/env.CurPrvInt", LocalType: "env.CurPrvInt", Doc: "automaton state within FSA that we're in", Directives: gti.Directives{}, Tag: ""}}, + {"NNext", >i.Field{Name: "NNext", Type: "goki.dev/etable/v2/etensor.Int", LocalType: "etensor.Int", Doc: "number of next states in current state output (scalar)", Directives: gti.Directives{}, Tag: ""}}, + {"NextStates", >i.Field{Name: "NextStates", Type: "goki.dev/etable/v2/etensor.Int", LocalType: "etensor.Int", Doc: "next states that have non-zero probability, with actual randomly chosen next state at start", Directives: gti.Directives{}, Tag: ""}}, + {"NextLabels", >i.Field{Name: "NextLabels", Type: "goki.dev/etable/v2/etensor.String", LocalType: "etensor.String", Doc: "transition labels for next states that have non-zero probability, with actual randomly chosen one for next state at start", Directives: gti.Directives{}, Tag: ""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "current run of model as provided during Init", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Epoch", >i.Field{Name: "Epoch", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "number of times through Seq.Max number of sequences", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Seq", >i.Field{Name: "Seq", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "sequence counter within epoch", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Tick", >i.Field{Name: "Tick", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "tick counter within sequence", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "trial is the step counter within sequence - how many steps taken within current sequence -- it resets to 0 at start of each sequence", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Rand", >i.Field{Name: "Rand", Type: "github.com/emer/emergent/v2/erand.SysRand", LocalType: "erand.SysRand", Doc: "random number generator for the env -- all random calls must use this -- set seed here for weight initialization values", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeed", >i.Field{Name: "RndSeed", Type: "int64", LocalType: "int64", Doc: "random seed", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/deep_move/deep_move.go b/examples/deep_move/deep_move.go index 896788ec8..b87eb0553 100644 --- a/examples/deep_move/deep_move.go +++ b/examples/deep_move/deep_move.go @@ -6,6 +6,8 @@ // on visual inputs. package main +//go:generate goki generate -add-types + import ( "os" @@ -49,7 +51,7 @@ func main() { // state information organized and available without having to pass everything around // as arguments to methods, and provides the core GUI interface (note the view tags // for the fields which provide hints to how things should be displayed). -type Sim struct { //gti:add +type Sim struct { // simulation configuration parameters -- set by .toml config file and / or args Config Config @@ -604,7 +606,7 @@ func (ss *Sim) ConfigNetView(nv *netview.NetView) { } // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Body { +func (ss *Sim) ConfigGUI() { title := "DeepAxon Move Prediction" ss.GUI.MakeBody(ss, "DeepMove", title, `This demonstrates a basic DeepAxon model on move prediction. See emergent on GitHub.

`) ss.GUI.CycleUpdateInterval = 10 @@ -675,13 +677,12 @@ func (ss *Sim) ConfigGUI() *gi.Body { ss.Net.GPU.Destroy() }) } - return ss.GUI.Body } func (ss *Sim) RunGUI() { ss.Init() - b := ss.ConfigGUI() - b.NewWindow().Run().Wait() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/deep_move/gtigen.go b/examples/deep_move/gtigen.go new file mode 100644 index 000000000..432b2adf4 --- /dev/null +++ b/examples/deep_move/gtigen.go @@ -0,0 +1,173 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package main + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "main.EnvConfig", + ShortName: "main.EnvConfig", + IDName: "env-config", + Doc: "EnvConfig has config params for environment\nnote: only adding fields for key Env params that matter for both Network and Env\nother params are set via the Env map data mechanism.", + Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Env", >i.Field{Name: "Env", Type: "map[string]any", LocalType: "map[string]any", Doc: "env parameters -- can set any field/subfield on Env struct, using standard TOML formatting", Directives: gti.Directives{}, Tag: ""}}, + {"UnitsPer", >i.Field{Name: "UnitsPer", Type: "int", LocalType: "int", Doc: "number of units per localist output unit", Directives: gti.Directives{}, Tag: "def:\"4\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Hid2", >i.Field{Name: "Hid2", Type: "bool", LocalType: "bool", Doc: "use a second hidden layer that predicts the first -- is not beneficial for this simple markovian task", Directives: gti.Directives{}, Tag: ""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- generally faster even for small models if NData ~16", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"NData", >i.Field{Name: "NData", Type: "int", LocalType: "int", Doc: "number of data-parallel items to process in parallel per trial -- works (and is significantly faster) for both CPU and GPU. Results in an effective mini-batch of learning.", Directives: gti.Directives{}, Tag: "def:\"16\" min:\"1\""}}, + {"NThreads", >i.Field{Name: "NThreads", Type: "int", LocalType: "int", Doc: "number of parallel threads for CPU computation -- 0 = use default", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"Run", >i.Field{Name: "Run", Type: "int", LocalType: "int", Doc: "starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"NRuns", >i.Field{Name: "NRuns", Type: "int", LocalType: "int", Doc: "total number of runs to do when running Train", Directives: gti.Directives{}, Tag: "def:\"5\" min:\"1\""}}, + {"NEpochs", >i.Field{Name: "NEpochs", Type: "int", LocalType: "int", Doc: "total number of epochs per run", Directives: gti.Directives{}, Tag: "def:\"100\""}}, + {"NTrials", >i.Field{Name: "NTrials", Type: "int", LocalType: "int", Doc: "total number of trials per epoch. Should be an even multiple of NData.", Directives: gti.Directives{}, Tag: "def:\"196\""}}, + {"PCAInterval", >i.Field{Name: "PCAInterval", Type: "int", LocalType: "int", Doc: "how frequently (in epochs) to compute PCA on hidden representations to measure variance?", Directives: gti.Directives{}, Tag: "def:\"5\""}}, + {"TestInterval", >i.Field{Name: "TestInterval", Type: "int", LocalType: "int", Doc: "how often to run through all the test patterns, in terms of training epochs -- can use 0 or -1 for no testing", Directives: gti.Directives{}, Tag: "def:\"-1\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"SaveWts", >i.Field{Name: "SaveWts", Type: "bool", LocalType: "bool", Doc: "if true, save final weights after each run", Directives: gti.Directives{}, Tag: ""}}, + {"Epoch", >i.Field{Name: "Epoch", Type: "bool", LocalType: "bool", Doc: "if true, save train epoch log to file, as .epc.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Run", >i.Field{Name: "Run", Type: "bool", LocalType: "bool", Doc: "if true, save run log to file, as .run.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "bool", LocalType: "bool", Doc: "if true, save train trial log to file, as .trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestEpoch", >i.Field{Name: "TestEpoch", Type: "bool", LocalType: "bool", Doc: "if true, save testing epoch log to file, as .tst_epc.tsv typically. In general it is better to copy testing items over to the training epoch log and record there.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestTrial", >i.Field{Name: "TestTrial", Type: "bool", LocalType: "bool", Doc: "if true, save testing trial log to file, as .tst_trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Env", >i.Field{Name: "Env", Type: "github.com/emer/axon/examples/deep_move.EnvConfig", LocalType: "EnvConfig", Doc: "environment configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/deep_move.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/deep_move.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/deep_move.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/deep_move.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "all parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Loops", >i.Field{Name: "Loops", Type: "*github.com/emer/emergent/v2/looper.Manager", LocalType: "*looper.Manager", Doc: "contains looper control loops for running sim", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "Contains all the logs and information about the logs.'", Directives: gti.Directives{}, Tag: ""}}, + {"Envs", >i.Field{Name: "Envs", Type: "github.com/emer/emergent/v2/env.Envs", LocalType: "env.Envs", Doc: "Environments", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeeds", >i.Field{Name: "RndSeeds", Type: "github.com/emer/emergent/v2/erand.Seeds", LocalType: "erand.Seeds", Doc: "a list of random seeds to use for each run", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.MoveEnv", + ShortName: "main.MoveEnv", + IDName: "move-env", + Doc: "MoveEnv is a flat-world grid-based environment", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Nm", >i.Field{Name: "Nm", Type: "string", LocalType: "string", Doc: "name of this environment", Directives: gti.Directives{}, Tag: ""}}, + {"Disp", >i.Field{Name: "Disp", Type: "bool", LocalType: "bool", Doc: "update display -- turn off to make it faster", Directives: gti.Directives{}, Tag: ""}}, + {"Size", >i.Field{Name: "Size", Type: "github.com/emer/emergent/v2/evec.Vec2i", LocalType: "evec.Vec2i", Doc: "size of 2D world", Directives: gti.Directives{}, Tag: ""}}, + {"World", >i.Field{Name: "World", Type: "*goki.dev/etable/v2/etensor.Int", LocalType: "*etensor.Int", Doc: "2D grid world, each cell is a material (mat)", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Acts", >i.Field{Name: "Acts", Type: "[]string", LocalType: "[]string", Doc: "list of actions: starts with: Stay, Left, Right, Forward, Back, then extensible", Directives: gti.Directives{}, Tag: ""}}, + {"ActMap", >i.Field{Name: "ActMap", Type: "map[string]int", LocalType: "map[string]int", Doc: "action map of action names to indexes", Directives: gti.Directives{}, Tag: ""}}, + {"FOV", >i.Field{Name: "FOV", Type: "int", LocalType: "int", Doc: "field of view in degrees, e.g., 180, must be even multiple of AngInc", Directives: gti.Directives{}, Tag: ""}}, + {"AngInc", >i.Field{Name: "AngInc", Type: "int", LocalType: "int", Doc: "angle increment for rotation, in degrees -- defaults to 15", Directives: gti.Directives{}, Tag: ""}}, + {"NRotAngles", >i.Field{Name: "NRotAngles", Type: "int", LocalType: "int", Doc: "total number of rotation angles in a circle", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"NFOVRays", >i.Field{Name: "NFOVRays", Type: "int", LocalType: "int", Doc: "total number of FOV rays that are traced", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"DepthSize", >i.Field{Name: "DepthSize", Type: "int", LocalType: "int", Doc: "number of units in depth population codes", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"DepthCode", >i.Field{Name: "DepthCode", Type: "github.com/emer/emergent/v2/popcode.OneD", LocalType: "popcode.OneD", Doc: "population code for depth, in normalized units", Directives: gti.Directives{}, Tag: ""}}, + {"AngCode", >i.Field{Name: "AngCode", Type: "github.com/emer/emergent/v2/popcode.Ring", LocalType: "popcode.Ring", Doc: "angle population code values, in normalized units", Directives: gti.Directives{}, Tag: ""}}, + {"UnitsPer", >i.Field{Name: "UnitsPer", Type: "int", LocalType: "int", Doc: "number of units per localist value", Directives: gti.Directives{}, Tag: ""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "print debug messages", Directives: gti.Directives{}, Tag: ""}}, + {"PctBlank", >i.Field{Name: "PctBlank", Type: "float32", LocalType: "float32", Doc: "proportion of times that a blank input is generated -- for testing pulvinar behavior with blank inputs", Directives: gti.Directives{}, Tag: ""}}, + {"PosF", >i.Field{Name: "PosF", Type: "goki.dev/mat32/v2.Vec2", LocalType: "mat32.Vec2", Doc: "current location of agent, floating point", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"PosI", >i.Field{Name: "PosI", Type: "github.com/emer/emergent/v2/evec.Vec2i", LocalType: "evec.Vec2i", Doc: "current location of agent, integer", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"Angle", >i.Field{Name: "Angle", Type: "int", LocalType: "int", Doc: "current angle, in degrees", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"RotAng", >i.Field{Name: "RotAng", Type: "int", LocalType: "int", Doc: "angle that we just rotated -- drives vestibular", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"Act", >i.Field{Name: "Act", Type: "int", LocalType: "int", Doc: "last action taken", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"Depths", >i.Field{Name: "Depths", Type: "[]float32", LocalType: "[]float32", Doc: "depth for each angle (NFOVRays), raw", Directives: gti.Directives{}, Tag: ""}}, + {"DepthLogs", >i.Field{Name: "DepthLogs", Type: "[]float32", LocalType: "[]float32", Doc: "depth for each angle (NFOVRays), normalized log", Directives: gti.Directives{}, Tag: ""}}, + {"CurStates", >i.Field{Name: "CurStates", Type: "map[string]*goki.dev/etable/v2/etensor.Float32", LocalType: "map[string]*etensor.Float32", Doc: "current rendered state tensors -- extensible map", Directives: gti.Directives{}, Tag: ""}}, + {"NextStates", >i.Field{Name: "NextStates", Type: "map[string]*goki.dev/etable/v2/etensor.Float32", LocalType: "map[string]*etensor.Float32", Doc: "next rendered state tensors -- updated from actions", Directives: gti.Directives{}, Tag: ""}}, + {"Rand", >i.Field{Name: "Rand", Type: "github.com/emer/emergent/v2/erand.SysRand", LocalType: "erand.SysRand", Doc: "random number generator for the env -- all random calls must use this -- set seed here for weight initialization values", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeed", >i.Field{Name: "RndSeed", Type: "int64", LocalType: "int64", Doc: "random seed", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/deep_music/deep_music.go b/examples/deep_music/deep_music.go index 6d432e011..2d3051fe5 100644 --- a/examples/deep_music/deep_music.go +++ b/examples/deep_music/deep_music.go @@ -6,6 +6,8 @@ // in a musical sequence of notes. package main +//go:generate goki generate -add-types + import ( "fmt" "os" @@ -38,7 +40,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(sim.RunGUI) + gimain.Run(sim.RunGUI) } else { sim.RunNoGUI() } @@ -596,9 +598,9 @@ func (ss *Sim) ConfigNetView(nv *netview.NetView) { } // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { +func (ss *Sim) ConfigGUI() { title := "DeepAxon Music Prediction" - ss.GUI.MakeWindow(ss, "DeepMusic", title, `This demonstrates a basic DeepAxon model on music prediction. See emergent on GitHub.

`) + ss.GUI.MakeBody(ss, "DeepMusic", title, `This demonstrates a basic DeepAxon model on music prediction. See emergent on GitHub.

`) ss.GUI.CycleUpdateInterval = 10 nv := ss.GUI.AddNetView("NetView") @@ -610,54 +612,57 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.GUI.AddPlots(title, &ss.Logs) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", - Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", - Active: egui.ActiveStopped, - Func: func() { - ss.Init() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddLooperCtrl(ss.Loops, []etime.Modes{etime.Train, etime.Test}) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Test Init", - Icon: "reset", - Tooltip: "restart testing", - Active: egui.ActiveAlways, - Func: func() { - ss.Loops.ResetCountersByMode(etime.Test) - }, - }) + ss.GUI.AddLooperCtrl(tb, ss.Loops, []etime.Modes{etime.Train, etime.Test}) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Test Init", + Icon: "reset", + Tooltip: "restart testing", + Active: egui.ActiveAlways, + Func: func() { + ss.Loops.ResetCountersByMode(etime.Test) + }, + }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"log") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", - Icon: "reset", - Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", - Active: egui.ActiveAlways, - Func: func() { - ss.Logs.ResetLog(etime.Train, etime.Run) - ss.GUI.UpdatePlot(etime.Train, etime.Run) - }, - }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"misc") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", - Icon: "new", - Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", - Active: egui.ActiveAlways, - Func: func() { - ss.RndSeeds.NewSeeds() - }, - }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", - Icon: "file-markdown", - Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", - Active: egui.ActiveAlways, - Func: func() { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/deep_music/README.md") - }, + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", + Icon: "reset", + Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", + Active: egui.ActiveAlways, + Func: func() { + ss.Logs.ResetLog(etime.Train, etime.Run) + ss.GUI.UpdatePlot(etime.Train, etime.Run) + }, + }) + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", + Icon: "new", + Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", + Active: egui.ActiveAlways, + Func: func() { + ss.RndSeeds.NewSeeds() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/deep_music/README.md") + }, + }) }) + ss.GUI.FinalizeGUI(false) if ss.Config.Run.GPU { ss.Net.ConfigGPUwithGUI(&ss.Context) @@ -665,13 +670,12 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.Net.GPU.Destroy() }) } - return ss.GUI.Win } func (ss *Sim) RunGUI() { ss.Init() - win := ss.ConfigGUI() - win.StartEventLoop() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/deep_music/gtigen.go b/examples/deep_music/gtigen.go new file mode 100644 index 000000000..cbb136520 --- /dev/null +++ b/examples/deep_music/gtigen.go @@ -0,0 +1,156 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package main + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "main.EnvConfig", + ShortName: "main.EnvConfig", + IDName: "env-config", + Doc: "EnvConfig has config params for environment\nnote: only adding fields for key Env params that matter for both Network and Env\nother params are set via the Env map data mechanism.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Env", >i.Field{Name: "Env", Type: "map[string]any", LocalType: "map[string]any", Doc: "env parameters -- can set any field/subfield on Env struct, using standard TOML formatting", Directives: gti.Directives{}, Tag: ""}}, + {"UnitsPer", >i.Field{Name: "UnitsPer", Type: "int", LocalType: "int", Doc: "number of units per localist output unit", Directives: gti.Directives{}, Tag: "def:\"4\""}}, + {"FullSong", >i.Field{Name: "FullSong", Type: "bool", LocalType: "bool", Doc: "train the full song -- else 30 notes", Directives: gti.Directives{}, Tag: ""}}, + {"PlayTarg", >i.Field{Name: "PlayTarg", Type: "bool", LocalType: "bool", Doc: "during testing, play the target note instead of the actual network output", Directives: gti.Directives{}, Tag: ""}}, + {"TestClamp", >i.Field{Name: "TestClamp", Type: "bool", LocalType: "bool", Doc: "drive inputs from the training sequence during testing -- otherwise use network's own output", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Hid2", >i.Field{Name: "Hid2", Type: "bool", LocalType: "bool", Doc: "use a second hidden layer that predicts the first -- is not beneficia", Directives: gti.Directives{}, Tag: ""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- generally faster even for small models if NData ~16", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"NData", >i.Field{Name: "NData", Type: "int", LocalType: "int", Doc: "number of data-parallel items to process in parallel per trial -- works (and is significantly faster) for both CPU and GPU. Results in an effective mini-batch of learning. is noisy above 4 for 30 note case.", Directives: gti.Directives{}, Tag: "def:\"4\" min:\"1\""}}, + {"NThreads", >i.Field{Name: "NThreads", Type: "int", LocalType: "int", Doc: "number of parallel threads for CPU computation -- 0 = use default", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"Run", >i.Field{Name: "Run", Type: "int", LocalType: "int", Doc: "starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"NRuns", >i.Field{Name: "NRuns", Type: "int", LocalType: "int", Doc: "total number of runs to do when running Train", Directives: gti.Directives{}, Tag: "def:\"5\" min:\"1\""}}, + {"NEpochs", >i.Field{Name: "NEpochs", Type: "int", LocalType: "int", Doc: "total number of epochs per run", Directives: gti.Directives{}, Tag: "def:\"100\""}}, + {"NTrials", >i.Field{Name: "NTrials", Type: "int", LocalType: "int", Doc: "total number of trials per epoch. Should be an even multiple of NData.", Directives: gti.Directives{}, Tag: "def:\"128\""}}, + {"PCAInterval", >i.Field{Name: "PCAInterval", Type: "int", LocalType: "int", Doc: "how frequently (in epochs) to compute PCA on hidden representations to measure variance?", Directives: gti.Directives{}, Tag: "def:\"5\""}}, + {"TestInterval", >i.Field{Name: "TestInterval", Type: "int", LocalType: "int", Doc: "how often to run through all the test patterns, in terms of training epochs -- can use 0 or -1 for no testing", Directives: gti.Directives{}, Tag: "def:\"-1\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"SaveWts", >i.Field{Name: "SaveWts", Type: "bool", LocalType: "bool", Doc: "if true, save final weights after each run", Directives: gti.Directives{}, Tag: ""}}, + {"Epoch", >i.Field{Name: "Epoch", Type: "bool", LocalType: "bool", Doc: "if true, save train epoch log to file, as .epc.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Run", >i.Field{Name: "Run", Type: "bool", LocalType: "bool", Doc: "if true, save run log to file, as .run.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "bool", LocalType: "bool", Doc: "if true, save train trial log to file, as .trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestEpoch", >i.Field{Name: "TestEpoch", Type: "bool", LocalType: "bool", Doc: "if true, save testing epoch log to file, as .tst_epc.tsv typically. In general it is better to copy testing items over to the training epoch log and record there.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestTrial", >i.Field{Name: "TestTrial", Type: "bool", LocalType: "bool", Doc: "if true, save testing trial log to file, as .tst_trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Env", >i.Field{Name: "Env", Type: "github.com/emer/axon/examples/deep_music.EnvConfig", LocalType: "EnvConfig", Doc: "environment configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/deep_music.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/deep_music.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/deep_music.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/deep_music.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "all parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Loops", >i.Field{Name: "Loops", Type: "*github.com/emer/emergent/v2/looper.Manager", LocalType: "*looper.Manager", Doc: "contains looper control loops for running sim", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "Contains all the logs and information about the logs.'", Directives: gti.Directives{}, Tag: ""}}, + {"Envs", >i.Field{Name: "Envs", Type: "github.com/emer/emergent/v2/env.Envs", LocalType: "env.Envs", Doc: "Environments", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeeds", >i.Field{Name: "RndSeeds", Type: "github.com/emer/emergent/v2/erand.Seeds", LocalType: "erand.Seeds", Doc: "a list of random seeds to use for each run", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.MusicEnv", + ShortName: "main.MusicEnv", + IDName: "music-env", + Doc: "MusicEnv reads in a midi SMF file and presents it as a sequence of notes.\nSongs with one note at a time per track are currently supported.\nRenders note to a tensor with localist note coding with duplicate units for spiking.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Nm", >i.Field{Name: "Nm", Type: "string", LocalType: "string", Doc: "name of this environment", Directives: gti.Directives{}, Tag: ""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "emit debugging messages about the music file", Directives: gti.Directives{}, Tag: ""}}, + {"WrapNotes", >i.Field{Name: "WrapNotes", Type: "bool", LocalType: "bool", Doc: "use only 1 octave of 12 notes for everything -- keeps it consistent", Directives: gti.Directives{}, Tag: ""}}, + {"TicksPer", >i.Field{Name: "TicksPer", Type: "int", LocalType: "int", Doc: "number of time ticks per row in table -- note transitions that are faster than this will be lost", Directives: gti.Directives{}, Tag: "def:\"120\""}}, + {"Track", >i.Field{Name: "Track", Type: "int", LocalType: "int", Doc: "which track to process", Directives: gti.Directives{}, Tag: ""}}, + {"Play", >i.Field{Name: "Play", Type: "bool", LocalType: "bool", Doc: "play output as it steps", Directives: gti.Directives{}, Tag: ""}}, + {"MaxSteps", >i.Field{Name: "MaxSteps", Type: "int", LocalType: "int", Doc: "limit song length to given number of steps, if > 0", Directives: gti.Directives{}, Tag: ""}}, + {"DiOffset", >i.Field{Name: "DiOffset", Type: "int", LocalType: "int", Doc: "time offset for data parallel = Song.Rows / (NData+1)", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"UnitsPer", >i.Field{Name: "UnitsPer", Type: "int", LocalType: "int", Doc: "number of units per localist note value", Directives: gti.Directives{}, Tag: ""}}, + {"NoteRange", >i.Field{Name: "NoteRange", Type: "goki.dev/etable/v2/minmax.Int", LocalType: "minmax.Int", Doc: "range of notes in given track", Directives: gti.Directives{}, Tag: ""}}, + {"NNotes", >i.Field{Name: "NNotes", Type: "int", LocalType: "int", Doc: "number of notes", Directives: gti.Directives{}, Tag: ""}}, + {"Song", >i.Field{Name: "Song", Type: "goki.dev/etable/v2/etable.Table", LocalType: "etable.Table", Doc: "the song encoded into 200 msec increments, with columns as tracks", Directives: gti.Directives{}, Tag: ""}}, + {"Time", >i.Field{Name: "Time", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "current time step", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Note", >i.Field{Name: "Note", Type: "goki.dev/etable/v2/etensor.Float32", LocalType: "etensor.Float32", Doc: "current note, rendered as a 4D tensor with shape:", Directives: gti.Directives{}, Tag: ""}}, + {"NoteIdx", >i.Field{Name: "NoteIdx", Type: "int", LocalType: "int", Doc: "current note index", Directives: gti.Directives{}, Tag: ""}}, + {"Player", >i.Field{Name: "Player", Type: "func(msg gitlab.com/gomidi/midi/v2.Message) error", LocalType: "func(msg midi.Message) error", Doc: "the function for playing midi", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"LastNotePlayed", >i.Field{Name: "LastNotePlayed", Type: "int", LocalType: "int", Doc: "for playing notes", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/deep_music/params_good/config.toml b/examples/deep_music/params_good/config.toml index dca7baabe..4f25bce15 100644 --- a/examples/deep_music/params_good/config.toml +++ b/examples/deep_music/params_good/config.toml @@ -1,5 +1,5 @@ Includes = ["30notes.toml"] -GUI = false +GUI = true Debug = false [Env] diff --git a/examples/deep_music/params_good/params_all.txt b/examples/deep_music/params_good/params_all.txt index 97aebb529..ef759c35b 100644 --- a/examples/deep_music/params_good/params_all.txt +++ b/examples/deep_music/params_good/params_all.txt @@ -37,7 +37,7 @@ Learn: { TrgAvgAct: { On: true GiBaseInit: 0 ErrLRate: 0.02 SynScaleRate: 0.005 SubMean: 1 Permute: true Pool: true TrgRange: { Min: 0.5 Max: 2 } } RLRate: { On: true SigmoidMin: 0.05 Diff: true SpkThr: 0.1 DiffThr: 0.02 Min: 0.001 } - NeuroMod: { DAMod: 0 Valence: 0 DAModGain: 0.5 DALRateSign: false DALRateMod: 0 AChLRateMod: 0 AChDisInhib: 0 BurstGain: 1 DipGain: 1 } + NeuroMod: { DAMod: NoDAMod Valence: Positive DAModGain: 0.5 DALRateSign: false DALRateMod: 0 AChLRateMod: 0 AChDisInhib: 0 BurstGain: 1 DipGain: 1 } } ///////////////////////////////////////////////// Layer: InputP @@ -78,7 +78,7 @@ Learn: { TrgAvgAct: { On: true GiBaseInit: 0 ErrLRate: 0.02 SynScaleRate: 0.005 SubMean: 1 Permute: true Pool: true TrgRange: { Min: 0.5 Max: 2 } } RLRate: { On: true SigmoidMin: 1 Diff: true SpkThr: 0.1 DiffThr: 0.02 Min: 0.001 } - NeuroMod: { DAMod: 0 Valence: 0 DAModGain: 0.5 DALRateSign: false DALRateMod: 0 AChLRateMod: 0 AChDisInhib: 0 BurstGain: 1 DipGain: 1 } + NeuroMod: { DAMod: NoDAMod Valence: Positive DAModGain: 0.5 DALRateSign: false DALRateMod: 0 AChLRateMod: 0 AChDisInhib: 0 BurstGain: 1 DipGain: 1 } } Pulv: { DriveScale: 0.1 FullDriveAct: 0.6 DriveLayIdx: 0 @@ -142,7 +142,7 @@ Learn: { TrgAvgAct: { On: true GiBaseInit: 0 ErrLRate: 0.02 SynScaleRate: 0.005 SubMean: 1 Permute: true Pool: true TrgRange: { Min: 0.5 Max: 2 } } RLRate: { On: true SigmoidMin: 0.05 Diff: true SpkThr: 0.1 DiffThr: 0.02 Min: 0.001 } - NeuroMod: { DAMod: 0 Valence: 0 DAModGain: 0.5 DALRateSign: false DALRateMod: 0 AChLRateMod: 0 AChDisInhib: 0 BurstGain: 1 DipGain: 1 } + NeuroMod: { DAMod: NoDAMod Valence: Positive DAModGain: 0.5 DALRateSign: false DALRateMod: 0 AChLRateMod: 0 AChDisInhib: 0 BurstGain: 1 DipGain: 1 } } Burst: { ThrRel: 0.1 ThrAbs: 0.1 @@ -226,7 +226,7 @@ Learn: { TrgAvgAct: { On: true GiBaseInit: 0 ErrLRate: 0.02 SynScaleRate: 0.005 SubMean: 1 Permute: true Pool: true TrgRange: { Min: 0.5 Max: 2 } } RLRate: { On: true SigmoidMin: 0.05 Diff: true SpkThr: 0.1 DiffThr: 0.02 Min: 0.001 } - NeuroMod: { DAMod: 0 Valence: 0 DAModGain: 0.5 DALRateSign: false DALRateMod: 0 AChLRateMod: 0 AChDisInhib: 0 BurstGain: 1 DipGain: 1 } + NeuroMod: { DAMod: NoDAMod Valence: Positive DAModGain: 0.5 DALRateSign: false DALRateMod: 0 AChLRateMod: 0 AChDisInhib: 0 BurstGain: 1 DipGain: 1 } } CT: { GeGain: 1 DecayTau: 50 diff --git a/examples/deep_music/params_good/params_layers.txt b/examples/deep_music/params_good/params_layers.txt index 369ede77b..0f0eb780e 100644 --- a/examples/deep_music/params_good/params_layers.txt +++ b/examples/deep_music/params_good/params_layers.txt @@ -1,12 +1,12 @@ Input Nominal: 0.05 Params: 30Notes:.InLay: 0.05 | .InLay: 0.025 | Layer: 0.1 Layer.Gi: 0.90 Params: Layer: 0.9 - InputP Nominal: 0.05 Params: 30Notes:.InLay: 0.05 | .InLay: 0.025 | Base:Layer: 0.1 + InputP Nominal: 0.05 Params: 30Notes:.InLay: 0.05 | .InLay: 0.025 | Layer: 0.1 Layer.Gi: 1.00 Params: .PulvinarLayer: 1.0 | Layer: 0.9 Hidden Nominal: 0.10 Params: .SuperLayer: 0.1 | Layer: 0.1 - Layer.Gi: 0.90 Params: Layer: 0.9 + Layer.Gi: 0.90 Params: Base:Layer: 0.9 - HiddenCT Nominal: 0.12 Params: .CTLayer: 0.12 | Layer: 0.1 + HiddenCT Nominal: 0.12 Params: .CTLayer: 0.12 | Base:Layer: 0.1 Layer.Gi: 2.20 Params: .CTLayer: 2.2 | Layer: 0.9 diff --git a/examples/hip/gtigen.go b/examples/hip/gtigen.go new file mode 100644 index 000000000..c427f50af --- /dev/null +++ b/examples/hip/gtigen.go @@ -0,0 +1,152 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package main + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"StopMem", >i.Field{Name: "StopMem", Type: "float32", LocalType: "float32", Doc: "mem % correct level (proportion) above which training on current list stops (switch from AB to AC or stop on AC)", Directives: gti.Directives{}, Tag: "def:\"0.9\""}}, + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- generally faster even for small models if NData ~16", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"NThreads", >i.Field{Name: "NThreads", Type: "int", LocalType: "int", Doc: "number of parallel threads for CPU computation -- 0 = use default", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"Run", >i.Field{Name: "Run", Type: "int", LocalType: "int", Doc: "starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"Runs", >i.Field{Name: "Runs", Type: "int", LocalType: "int", Doc: "total number of runs to do when running Train", Directives: gti.Directives{}, Tag: "def:\"5\" min:\"1\""}}, + {"Epochs", >i.Field{Name: "Epochs", Type: "int", LocalType: "int", Doc: "total number of epochs per run", Directives: gti.Directives{}, Tag: "def:\"100\""}}, + {"NTrials", >i.Field{Name: "NTrials", Type: "int", LocalType: "int", Doc: "total number of trials per epoch. Should be an even multiple of NData.", Directives: gti.Directives{}, Tag: "def:\"20\""}}, + {"NData", >i.Field{Name: "NData", Type: "int", LocalType: "int", Doc: "number of data-parallel items to process in parallel per trial -- works (and is significantly faster) for both CPU and GPU. Results in an effective mini-batch of learning.", Directives: gti.Directives{}, Tag: "def:\"10\" min:\"1\""}}, + {"TestInterval", >i.Field{Name: "TestInterval", Type: "int", LocalType: "int", Doc: "how often to run through all the test patterns, in terms of training epochs -- can use 0 or -1 for no testing", Directives: gti.Directives{}, Tag: "def:\"1\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"SaveWts", >i.Field{Name: "SaveWts", Type: "bool", LocalType: "bool", Doc: "if true, save final weights after each run", Directives: gti.Directives{}, Tag: ""}}, + {"Epoch", >i.Field{Name: "Epoch", Type: "bool", LocalType: "bool", Doc: "if true, save train epoch log to file, as .epc.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Run", >i.Field{Name: "Run", Type: "bool", LocalType: "bool", Doc: "if true, save run log to file, as .run.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "bool", LocalType: "bool", Doc: "if true, save train trial log to file, as .trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestEpoch", >i.Field{Name: "TestEpoch", Type: "bool", LocalType: "bool", Doc: "if true, save testing epoch log to file, as .tst_epc.tsv typically. In general it is better to copy testing items over to the training epoch log and record there.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestTrial", >i.Field{Name: "TestTrial", Type: "bool", LocalType: "bool", Doc: "if true, save testing trial log to file, as .tst_trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.PatConfig", + ShortName: "main.PatConfig", + IDName: "pat-config", + Doc: "PatConfig have the pattern parameters", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"MinDiffPct", >i.Field{Name: "MinDiffPct", Type: "float32", LocalType: "float32", Doc: "minimum difference between item random patterns, as a proportion (0-1) of total active", Directives: gti.Directives{}, Tag: ""}}, + {"DriftCtxt", >i.Field{Name: "DriftCtxt", Type: "bool", LocalType: "bool", Doc: "use drifting context representations -- otherwise does bit flips from prototype", Directives: gti.Directives{}, Tag: ""}}, + {"CtxtFlipPct", >i.Field{Name: "CtxtFlipPct", Type: "float32", LocalType: "float32", Doc: "proportion (0-1) of active bits to flip for each context pattern, relative to a prototype, for non-drifting", Directives: gti.Directives{}, Tag: ""}}, + {"DriftPct", >i.Field{Name: "DriftPct", Type: "float32", LocalType: "float32", Doc: "percentage of active bits that drift, per step, for drifting context", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.ModConfig", + ShortName: "main.ModConfig", + IDName: "mod-config", + Doc: "", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"InToEc2PCon", >i.Field{Name: "InToEc2PCon", Type: "float32", LocalType: "float32", Doc: "percent connectivity from Input to EC2", Directives: gti.Directives{}, Tag: ""}}, + {"ECPctAct", >i.Field{Name: "ECPctAct", Type: "float32", LocalType: "float32", Doc: "percent activation in EC pool, used in patgen for input generation\npercent activation in EC pool, used in patgen for input generation", Directives: gti.Directives{}, Tag: ""}}, + {"MemThr", >i.Field{Name: "MemThr", Type: "float64", LocalType: "float64", Doc: "memory threshold", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Mod", >i.Field{Name: "Mod", Type: "github.com/emer/axon/examples/hip.ModConfig", LocalType: "ModConfig", Doc: "misc model parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Hip", >i.Field{Name: "Hip", Type: "github.com/emer/axon/axon.HipConfig", LocalType: "axon.HipConfig", Doc: "Hippocampus sizing parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Pat", >i.Field{Name: "Pat", Type: "github.com/emer/axon/examples/hip.PatConfig", LocalType: "PatConfig", Doc: "parameters for the input patterns", Directives: gti.Directives{}, Tag: ""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/hip.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/hip.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/hip.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/hip.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "all parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Loops", >i.Field{Name: "Loops", Type: "*github.com/emer/emergent/v2/looper.Manager", LocalType: "*looper.Manager", Doc: "contains looper control loops for running sim", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "Contains all the logs and information about the logs.'", Directives: gti.Directives{}, Tag: ""}}, + {"PretrainMode", >i.Field{Name: "PretrainMode", Type: "bool", LocalType: "bool", Doc: "if true, run in pretrain mode", Directives: gti.Directives{}, Tag: ""}}, + {"PoolVocab", >i.Field{Name: "PoolVocab", Type: "github.com/emer/emergent/v2/patgen.Vocab", LocalType: "patgen.Vocab", Doc: "pool patterns vocabulary", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"TrainAB", >i.Field{Name: "TrainAB", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "AB training patterns to use", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"TrainAC", >i.Field{Name: "TrainAC", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "AC training patterns to use", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"TestAB", >i.Field{Name: "TestAB", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "AB testing patterns to use", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"TestAC", >i.Field{Name: "TestAC", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "AC testing patterns to use", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"PreTrainLure", >i.Field{Name: "PreTrainLure", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "Lure pretrain patterns to use", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"TestLure", >i.Field{Name: "TestLure", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "Lure testing patterns to use", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"TrainAll", >i.Field{Name: "TrainAll", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "all training patterns -- for pretrain", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"TestABAC", >i.Field{Name: "TestABAC", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "TestAB + TestAC", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Envs", >i.Field{Name: "Envs", Type: "github.com/emer/emergent/v2/env.Envs", LocalType: "env.Envs", Doc: "Environments", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeeds", >i.Field{Name: "RndSeeds", Type: "github.com/emer/emergent/v2/erand.Seeds", LocalType: "erand.Seeds", Doc: "a list of random seeds to use for each run", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/hip/hip.go b/examples/hip/hip.go index 2e6e45ffe..f2f0d97a1 100644 --- a/examples/hip/hip.go +++ b/examples/hip/hip.go @@ -5,6 +5,8 @@ // hip runs a hippocampus model for testing parameters and new learning ideas package main +//go:generate goki generate -add-types + import ( "fmt" "log" @@ -33,7 +35,7 @@ import ( "goki.dev/etable/v2/metric" "goki.dev/gi/v2/gi" "goki.dev/gi/v2/gimain" - "goki.dev/glop/bools" + "goki.dev/glop/num" "goki.dev/mat32/v2" ) @@ -42,7 +44,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(func() { + gimain.Run(func() { sim.RunGUI() }) } else { @@ -656,9 +658,9 @@ func (ss *Sim) MemStats(mode etime.Modes, di int) { ss.Stats.SetInt("RecallItem", mostSimilar) if isAB { - ss.Stats.SetFloat("ABRecMem", bools.ToFloat64(mostSimilar == correctIdx)) + ss.Stats.SetFloat("ABRecMem", num.FromBool[float64](mostSimilar == correctIdx)) } else { - ss.Stats.SetFloat("ACRecMem", bools.ToFloat64(mostSimilar == correctIdx)) + ss.Stats.SetFloat("ACRecMem", num.FromBool[float64](mostSimilar == correctIdx)) } } @@ -777,9 +779,9 @@ func (ss *Sim) Log(mode etime.Modes, time etime.Times) { // Gui // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { +func (ss *Sim) ConfigGUI() { title := "Axon Hippocampus" - ss.GUI.MakeWindow(ss, "hip", title, `Benchmarking`) + ss.GUI.MakeBody(ss, "hip", title, `Benchmarking`) ss.GUI.CycleUpdateInterval = 10 nv := ss.GUI.AddNetView("NetView") @@ -793,54 +795,56 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.GUI.AddPlots(title, &ss.Logs) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", - Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", - Active: egui.ActiveStopped, - Func: func() { - ss.Init() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Test Init", Icon: "update", - Tooltip: "Call ResetCountersByMode with test mode and update GUI.", - Active: egui.ActiveStopped, - Func: func() { - ss.TestInit() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Test Init", Icon: "update", + Tooltip: "Call ResetCountersByMode with test mode and update GUI.", + Active: egui.ActiveStopped, + Func: func() { + ss.TestInit() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddLooperCtrl(ss.Loops, []etime.Modes{etime.Train, etime.Test}) - - //////////////////////////////////////////////// - gi.NewSeparator(tb)"log") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", - Icon: "reset", - Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", - Active: egui.ActiveAlways, - Func: func() { - ss.Logs.ResetLog(etime.Train, etime.Run) - ss.GUI.UpdatePlot(etime.Train, etime.Run) - }, - }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"misc") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", - Icon: "new", - Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", - Active: egui.ActiveAlways, - Func: func() { - ss.RndSeeds.NewSeeds() - }, - }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", - Icon: "file-markdown", - Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", - Active: egui.ActiveAlways, - Func: func() { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/hip/README.md") - }, + ss.GUI.AddLooperCtrl(tb, ss.Loops, []etime.Modes{etime.Train, etime.Test}) + + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", + Icon: "reset", + Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", + Active: egui.ActiveAlways, + Func: func() { + ss.Logs.ResetLog(etime.Train, etime.Run) + ss.GUI.UpdatePlot(etime.Train, etime.Run) + }, + }) + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", + Icon: "new", + Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", + Active: egui.ActiveAlways, + Func: func() { + ss.RndSeeds.NewSeeds() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/hip/README.md") + }, + }) }) ss.GUI.FinalizeGUI(false) if ss.Config.Run.GPU { @@ -850,13 +854,12 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.Net.GPU.Destroy() }) } - return ss.GUI.Win } func (ss *Sim) RunGUI() { ss.Init() - win := ss.ConfigGUI() - win.StartEventLoop() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/inhib/gtigen.go b/examples/inhib/gtigen.go new file mode 100644 index 000000000..2a0768e51 --- /dev/null +++ b/examples/inhib/gtigen.go @@ -0,0 +1,113 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package main + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "main.EnvConfig", + ShortName: "main.EnvConfig", + IDName: "env-config", + Doc: "EnvConfig has config params for environment\nnote: only adding fields for key Env params that matter for both Network and Env\nother params are set via the Env map data mechanism.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Env", >i.Field{Name: "Env", Type: "map[string]any", LocalType: "map[string]any", Doc: "env parameters -- can set any field/subfield on Env struct, using standard TOML formatting", Directives: gti.Directives{}, Tag: ""}}, + {"InputPct", >i.Field{Name: "InputPct", Type: "float32", LocalType: "float32", Doc: "percent of active units in input layer (literally number of active units, because input has 100 units total)", Directives: gti.Directives{}, Tag: "def:\"15\" min:\"5\" max:\"50\" step:\"1\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"NLayers", >i.Field{Name: "NLayers", Type: "int", LocalType: "int", Doc: "number of hidden layers to add", Directives: gti.Directives{}, Tag: "def:\"2\" min:\"1\""}}, + {"HidSize", >i.Field{Name: "HidSize", Type: "github.com/emer/emergent/v2/evec.Vec2i", LocalType: "evec.Vec2i", Doc: "size of hidden layers", Directives: gti.Directives{}, Tag: "def:\"{'X':10,'Y':10}\""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- generally faster even for small models if NData ~16", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Epoch", >i.Field{Name: "Epoch", Type: "bool", LocalType: "bool", Doc: "if true, save train epoch log to file, as .epc.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "bool", LocalType: "bool", Doc: "if true, save train trial log to file, as .trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Env", >i.Field{Name: "Env", Type: "github.com/emer/axon/examples/inhib.EnvConfig", LocalType: "EnvConfig", Doc: "environment configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/inhib.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/inhib.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/inhib.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/inhib.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "all parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Loops", >i.Field{Name: "Loops", Type: "*github.com/emer/emergent/v2/looper.Manager", LocalType: "*looper.Manager", Doc: "contains looper control loops for running sim", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "Contains all the logs and information about the logs.'", Directives: gti.Directives{}, Tag: ""}}, + {"Pats", >i.Field{Name: "Pats", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "the training patterns to use", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeeds", >i.Field{Name: "RndSeeds", Type: "github.com/emer/emergent/v2/erand.Seeds", LocalType: "erand.Seeds", Doc: "a list of random seeds to use for each run", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/inhib/inhib.go b/examples/inhib/inhib.go index b842d903e..6265fa89e 100644 --- a/examples/inhib/inhib.go +++ b/examples/inhib/inhib.go @@ -9,6 +9,8 @@ feedforward and feedback inhibition to excitatory pyramidal neurons. */ package main +//go:generate goki generate -add-types + import ( "fmt" "math/rand" @@ -41,7 +43,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(sim.RunGUI) + gimain.Run(sim.RunGUI) } else { sim.RunNoGUI() } @@ -345,10 +347,10 @@ func (ss *Sim) InitStats() { // StatCounters saves current counters to Stats, so they are available for logging etc // Also saves a string rep of them for ViewUpdt.Text func (ss *Sim) StatCounters() { - var mode etime.Modes - mode.FromString(ss.Context.Mode.String()) + ctx := &ss.Context + mode := ctx.Mode ss.Loops.Stacks[mode].CtrsToStats(&ss.Stats) - ss.Stats.SetInt("Cycle", int(ss.Context.Cycle)) + ss.Stats.SetInt("Cycle", int(ctx.Cycle)) } func (ss *Sim) NetViewCounters(tm etime.Times) { @@ -511,9 +513,9 @@ func (ss *Sim) Log(mode etime.Modes, time etime.Times) { // Gui // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { +func (ss *Sim) ConfigGUI() { title := "Axon Inhibition Test" - ss.GUI.MakeWindow(ss, "inhib", title, `This tests inhibition based on interneurons and inhibition functions. See emergent on GitHub.

`) + ss.GUI.MakeBody(ss, "inhib", title, `This tests inhibition based on interneurons and inhibition functions. See emergent on GitHub.

`) ss.GUI.CycleUpdateInterval = 10 nv := ss.GUI.AddNetView("NetView") @@ -527,54 +529,55 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.GUI.AddPlots(title, &ss.Logs) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", - Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", - Active: egui.ActiveStopped, - Func: func() { - ss.Init() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddLooperCtrl(ss.Loops, []etime.Modes{etime.Test}) - - //////////////////////////////////////////////// - gi.NewSeparator(tb)"log") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", - Icon: "reset", - Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", - Active: egui.ActiveAlways, - Func: func() { - ss.Logs.ResetLog(etime.Train, etime.Run) - ss.GUI.UpdatePlot(etime.Train, etime.Run) - }, - }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"misc") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", - Icon: "new", - Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", - Active: egui.ActiveAlways, - Func: func() { - ss.RndSeeds.NewSeeds() - }, - }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", - Icon: "file-markdown", - Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", - Active: egui.ActiveAlways, - Func: func() { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/inhib/README.md") - }, + ss.GUI.AddLooperCtrl(tb, ss.Loops, []etime.Modes{etime.Test}) + + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", + Icon: "reset", + Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", + Active: egui.ActiveAlways, + Func: func() { + ss.Logs.ResetLog(etime.Train, etime.Run) + ss.GUI.UpdatePlot(etime.Train, etime.Run) + }, + }) + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", + Icon: "new", + Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", + Active: egui.ActiveAlways, + Func: func() { + ss.RndSeeds.NewSeeds() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/inhib/README.md") + }, + }) }) ss.GUI.FinalizeGUI(false) - return ss.GUI.Win } func (ss *Sim) RunGUI() { ss.Init() - win := ss.ConfigGUI() - win.StartEventLoop() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/mpi/Makefile b/examples/mpi/Makefile index 234bf88c0..6e568f284 100644 --- a/examples/mpi/Makefile +++ b/examples/mpi/Makefile @@ -6,30 +6,30 @@ all: # CPU nompi_cpu_nd1: - ./mpi -nogui -ndata=1 -threads=4 -tag=nompi_cpu_nd1 & + ./mpi -nogui -ndata=1 -nthreads=4 -tag=nompi_cpu_nd1 & nompi_cpu_nd4: - ./mpi -nogui -ndata=4 -threads=4 -tag=nompi_cpu_nd4 & + ./mpi -nogui -ndata=4 -nthreads=4 -tag=nompi_cpu_nd4 & nompi_cpu_nd12: - ./mpi -nogui -ndata=12 -threads=4 -tag=nompi_cpu_nd12 & + ./mpi -nogui -ndata=12 -nthreads=4 -tag=nompi_cpu_nd12 & mpi_cpu2: - mpirun -np 2 ./mpi -nogui -mpi -ndata=4 -threads=4 -tag=mpi2_cpu_nd4 & + mpirun -np 2 ./mpi -nogui -mpi -ndata=4 -nthreads=4 -tag=mpi2_cpu_nd4 & mpi_cpu4: - mpirun -np 4 ./mpi -nogui -mpi -ndata=3 -threads=2 -tag=mpi4_cpu_nd3 & + mpirun -np 4 ./mpi -nogui -mpi -ndata=3 -nthreads=2 -tag=mpi4_cpu_nd3 & # this is the fastest config on macbookpro 8 cores mpi_cpu8_th1: - mpirun -np 8 ./mpi -nogui -mpi -ndata=1 -threads=1 -tag=mpi8_cpu_nd1_th1 & + mpirun -np 8 ./mpi -nogui -mpi -ndata=1 -nthreads=1 -tag=mpi8_cpu_nd1_th1 & # too many threads is deadly! mpi_cpu8_th2: - mpirun -np 8 ./mpi -nogui -mpi -ndata=1 -threads=2 -tag=mpi8_cpu_nd1_th2 & + mpirun -np 8 ./mpi -nogui -mpi -ndata=1 -nthreads=2 -tag=mpi8_cpu_nd1_th2 & mpi_cpu8_th4: - mpirun -np 8 ./mpi -nogui -mpi -ndata=1 -threads=4 -tag=mpi8_cpu_nd1_th4 & + mpirun -np 8 ./mpi -nogui -mpi -ndata=1 -nthreads=4 -tag=mpi8_cpu_nd1_th4 & # GPU diff --git a/examples/mpi/gtigen.go b/examples/mpi/gtigen.go new file mode 100644 index 000000000..61ddfbe68 --- /dev/null +++ b/examples/mpi/gtigen.go @@ -0,0 +1,115 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package main + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Hidden1Size", >i.Field{Name: "Hidden1Size", Type: "github.com/emer/emergent/v2/evec.Vec2i", LocalType: "evec.Vec2i", Doc: "size of hidden layer -- can use emer.LaySize for 4D layers", Directives: gti.Directives{}, Tag: "def:\"{'X':10,'Y':10}\" nest:\"+\""}}, + {"Hidden2Size", >i.Field{Name: "Hidden2Size", Type: "github.com/emer/emergent/v2/evec.Vec2i", LocalType: "evec.Vec2i", Doc: "size of hidden layer -- can use emer.LaySize for 4D layers", Directives: gti.Directives{}, Tag: "def:\"{'X':10,'Y':10}\" nest:\"+\""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"MPI", >i.Field{Name: "MPI", Type: "bool", LocalType: "bool", Doc: "use MPI message passing interface for data parallel computation between nodes running identical copies of the same sim, sharing DWt changes", Directives: gti.Directives{}, Tag: ""}}, + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- generally faster even for small models if NData ~16", Directives: gti.Directives{}, Tag: "def:\"false\""}}, + {"NData", >i.Field{Name: "NData", Type: "int", LocalType: "int", Doc: "number of data-parallel items to process in parallel per trial -- works (and is significantly faster) for both CPU and GPU. Results in an effective mini-batch of learning.", Directives: gti.Directives{}, Tag: "def:\"16\" min:\"1\""}}, + {"NThreads", >i.Field{Name: "NThreads", Type: "int", LocalType: "int", Doc: "number of parallel threads for CPU computation -- 0 = use default", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"Run", >i.Field{Name: "Run", Type: "int", LocalType: "int", Doc: "starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"NRuns", >i.Field{Name: "NRuns", Type: "int", LocalType: "int", Doc: "total number of runs to do when running Train", Directives: gti.Directives{}, Tag: "def:\"5\" min:\"1\""}}, + {"NEpochs", >i.Field{Name: "NEpochs", Type: "int", LocalType: "int", Doc: "total number of epochs per run", Directives: gti.Directives{}, Tag: "def:\"100\""}}, + {"NZero", >i.Field{Name: "NZero", Type: "int", LocalType: "int", Doc: "stop run after this number of perfect, zero-error epochs", Directives: gti.Directives{}, Tag: "def:\"2\""}}, + {"NTrials", >i.Field{Name: "NTrials", Type: "int", LocalType: "int", Doc: "total number of trials per epoch. Should be an even multiple of NData.", Directives: gti.Directives{}, Tag: "def:\"32\""}}, + {"TestInterval", >i.Field{Name: "TestInterval", Type: "int", LocalType: "int", Doc: "how often to run through all the test patterns, in terms of training epochs -- can use 0 or -1 for no testing", Directives: gti.Directives{}, Tag: "def:\"5\""}}, + {"PCAInterval", >i.Field{Name: "PCAInterval", Type: "int", LocalType: "int", Doc: "how frequently (in epochs) to compute PCA on hidden representations to measure variance?", Directives: gti.Directives{}, Tag: "def:\"5\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"SaveWts", >i.Field{Name: "SaveWts", Type: "bool", LocalType: "bool", Doc: "if true, save final weights after each run", Directives: gti.Directives{}, Tag: ""}}, + {"Epoch", >i.Field{Name: "Epoch", Type: "bool", LocalType: "bool", Doc: "if true, save train epoch log to file, as .epc.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Run", >i.Field{Name: "Run", Type: "bool", LocalType: "bool", Doc: "if true, save run log to file, as .run.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "bool", LocalType: "bool", Doc: "if true, save train trial log to file, as .trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestEpoch", >i.Field{Name: "TestEpoch", Type: "bool", LocalType: "bool", Doc: "if true, save testing epoch log to file, as .tst_epc.tsv typically. In general it is better to copy testing items over to the training epoch log and record there.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestTrial", >i.Field{Name: "TestTrial", Type: "bool", LocalType: "bool", Doc: "if true, save testing trial log to file, as .tst_trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/mpi.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/mpi.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/mpi.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/mpi.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "network parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Loops", >i.Field{Name: "Loops", Type: "*github.com/emer/emergent/v2/looper.Manager", LocalType: "*looper.Manager", Doc: "contains looper control loops for running sim", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "Contains all the logs and information about the logs.'", Directives: gti.Directives{}, Tag: ""}}, + {"Pats", >i.Field{Name: "Pats", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "the training patterns to use", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Envs", >i.Field{Name: "Envs", Type: "github.com/emer/emergent/v2/env.Envs", LocalType: "env.Envs", Doc: "Environments", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeeds", >i.Field{Name: "RndSeeds", Type: "github.com/emer/emergent/v2/erand.Seeds", LocalType: "erand.Seeds", Doc: "a list of random seeds to use for each run", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"Comm", >i.Field{Name: "Comm", Type: "*github.com/emer/empi/v2/mpi.Comm", LocalType: "*mpi.Comm", Doc: "mpi communicator", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"AllDWts", >i.Field{Name: "AllDWts", Type: "[]float32", LocalType: "[]float32", Doc: "buffer of all dwt weight changes -- for mpi sharing", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/mpi/ra25.go b/examples/mpi/ra25.go index aef7e2c04..93aa63928 100644 --- a/examples/mpi/ra25.go +++ b/examples/mpi/ra25.go @@ -6,6 +6,8 @@ // across multiple nodes, sharing DWt changes via MPI. package main +//go:generate goki generate -add-types + import ( "fmt" "log" @@ -39,7 +41,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(sim.RunGUI) + gimain.Run(sim.RunGUI) } else { sim.RunNoGUI() } @@ -697,9 +699,9 @@ func (ss *Sim) Log(mode etime.Modes, time etime.Times) { // Gui // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { +func (ss *Sim) ConfigGUI() { title := "Axon Random Associator" - ss.GUI.MakeWindow(ss, "ra25", title, `This demonstrates a basic Axon model. See emergent on GitHub.

`) + ss.GUI.MakeBody(ss, "ra25", title, `This demonstrates a basic Axon model. See emergent on GitHub.

`) ss.GUI.CycleUpdateInterval = 10 nv := ss.GUI.AddNetView("NetView") @@ -713,45 +715,47 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.GUI.AddPlots(title, &ss.Logs) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", - Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", - Active: egui.ActiveStopped, - Func: func() { - ss.Init() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddLooperCtrl(ss.Loops, []etime.Modes{etime.Train, etime.Test}) - - //////////////////////////////////////////////// - gi.NewSeparator(tb)"log") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", - Icon: "reset", - Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", - Active: egui.ActiveAlways, - Func: func() { - ss.Logs.ResetLog(etime.Train, etime.Run) - ss.GUI.UpdatePlot(etime.Train, etime.Run) - }, - }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"misc") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", - Icon: "new", - Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", - Active: egui.ActiveAlways, - Func: func() { - ss.RndSeeds.NewSeeds() - }, - }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", - Icon: "file-markdown", - Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", - Active: egui.ActiveAlways, - Func: func() { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/mpi/README.md") - }, + ss.GUI.AddLooperCtrl(tb, ss.Loops, []etime.Modes{etime.Train, etime.Test}) + + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", + Icon: "reset", + Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", + Active: egui.ActiveAlways, + Func: func() { + ss.Logs.ResetLog(etime.Train, etime.Run) + ss.GUI.UpdatePlot(etime.Train, etime.Run) + }, + }) + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", + Icon: "new", + Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", + Active: egui.ActiveAlways, + Func: func() { + ss.RndSeeds.NewSeeds() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/mpi/README.md") + }, + }) }) ss.GUI.FinalizeGUI(false) if ss.Config.Run.GPU { @@ -761,13 +765,12 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.Net.GPU.Destroy() }) } - return ss.GUI.Win } func (ss *Sim) RunGUI() { ss.Init() - win := ss.ConfigGUI() - win.StartEventLoop() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/neuron/gtigen.go b/examples/neuron/gtigen.go new file mode 100644 index 000000000..a31aae6d0 --- /dev/null +++ b/examples/neuron/gtigen.go @@ -0,0 +1,131 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package main + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- only for testing in this model -- not faster", Directives: gti.Directives{}, Tag: "def:\"false\""}}, + {"NThreads", >i.Field{Name: "NThreads", Type: "int", LocalType: "int", Doc: "number of parallel threads for CPU computation -- 0 = use default", Directives: gti.Directives{}, Tag: "def:\"2\""}}, + {"Run", >i.Field{Name: "Run", Type: "int", LocalType: "int", Doc: "starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"NRuns", >i.Field{Name: "NRuns", Type: "int", LocalType: "int", Doc: "total number of runs to do when running Train", Directives: gti.Directives{}, Tag: "def:\"1\" min:\"1\""}}, + {"NEpochs", >i.Field{Name: "NEpochs", Type: "int", LocalType: "int", Doc: "total number of epochs per run", Directives: gti.Directives{}, Tag: "def:\"1\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"SaveWts", >i.Field{Name: "SaveWts", Type: "bool", LocalType: "bool", Doc: "if true, save final weights after each run", Directives: gti.Directives{}, Tag: ""}}, + {"Cycle", >i.Field{Name: "Cycle", Type: "bool", LocalType: "bool", Doc: "if true, save cycle log to file, as .cyc.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"GeClamp", >i.Field{Name: "GeClamp", Type: "bool", LocalType: "bool", Doc: "clamp constant Ge value -- otherwise drive discrete spiking input", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"SpikeHz", >i.Field{Name: "SpikeHz", Type: "float32", LocalType: "float32", Doc: "frequency of input spiking for !GeClamp mode", Directives: gti.Directives{}, Tag: "def:\"50\""}}, + {"Ge", >i.Field{Name: "Ge", Type: "float32", LocalType: "float32", Doc: "Raw synaptic excitatory conductance", Directives: gti.Directives{}, Tag: "min:\"0\" step:\"0.01\" def:\"0.1\""}}, + {"Gi", >i.Field{Name: "Gi", Type: "float32", LocalType: "float32", Doc: "Inhibitory conductance", Directives: gti.Directives{}, Tag: "min:\"0\" step:\"0.01\" def:\"0.1\""}}, + {"ErevE", >i.Field{Name: "ErevE", Type: "float32", LocalType: "float32", Doc: "excitatory reversal (driving) potential -- determines where excitation pushes Vm up to", Directives: gti.Directives{}, Tag: "min:\"0\" max:\"1\" step:\"0.01\" def:\"1\""}}, + {"ErevI", >i.Field{Name: "ErevI", Type: "float32", LocalType: "float32", Doc: "leak reversal (driving) potential -- determines where excitation pulls Vm down to", Directives: gti.Directives{}, Tag: "min:\"0\" max:\"1\" step:\"0.01\" def:\"0.3\""}}, + {"Noise", >i.Field{Name: "Noise", Type: "float32", LocalType: "float32", Doc: "the variance parameter for Gaussian noise added to unit activations on every cycle", Directives: gti.Directives{}, Tag: "min:\"0\" step:\"0.01\""}}, + {"KNaAdapt", >i.Field{Name: "KNaAdapt", Type: "bool", LocalType: "bool", Doc: "apply sodium-gated potassium adaptation mechanisms that cause the neuron to reduce spiking over time", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"MahpGbar", >i.Field{Name: "MahpGbar", Type: "float32", LocalType: "float32", Doc: "strength of mAHP M-type channel -- used to be implemented by KNa but now using the more standard M-type channel mechanism", Directives: gti.Directives{}, Tag: "def:\"0.05\""}}, + {"NMDAGbar", >i.Field{Name: "NMDAGbar", Type: "float32", LocalType: "float32", Doc: "strength of NMDA current -- 0.006 default for posterior cortex", Directives: gti.Directives{}, Tag: "def:\"0.006\""}}, + {"GABABGbar", >i.Field{Name: "GABABGbar", Type: "float32", LocalType: "float32", Doc: "strength of GABAB current -- 0.015 default for posterior cortex", Directives: gti.Directives{}, Tag: "def:\"0.015\""}}, + {"VGCCGbar", >i.Field{Name: "VGCCGbar", Type: "float32", LocalType: "float32", Doc: "strength of VGCC voltage gated calcium current -- only activated during spikes -- this is now an essential part of Ca-driven learning to reflect recv spiking in the Ca signal -- but if too strong leads to runaway excitatory bursting.", Directives: gti.Directives{}, Tag: "def:\"0.02\""}}, + {"AKGbar", >i.Field{Name: "AKGbar", Type: "float32", LocalType: "float32", Doc: "strength of A-type potassium channel -- this is only active at high (depolarized) membrane potentials -- only during spikes -- useful to counteract VGCC's", Directives: gti.Directives{}, Tag: "def:\"0.1\""}}, + {"NCycles", >i.Field{Name: "NCycles", Type: "int", LocalType: "int", Doc: "total number of cycles to run", Directives: gti.Directives{}, Tag: "min:\"10\" def:\"200\""}}, + {"OnCycle", >i.Field{Name: "OnCycle", Type: "int", LocalType: "int", Doc: "when does excitatory input into neuron come on?", Directives: gti.Directives{}, Tag: "min:\"0\" def:\"10\""}}, + {"OffCycle", >i.Field{Name: "OffCycle", Type: "int", LocalType: "int", Doc: "when does excitatory input into neuron go off?", Directives: gti.Directives{}, Tag: "min:\"0\" def:\"160\""}}, + {"UpdtInterval", >i.Field{Name: "UpdtInterval", Type: "int", LocalType: "int", Doc: "how often to update display (in cycles)", Directives: gti.Directives{}, Tag: "min:\"1\" def:\"10\" "}}, + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/neuron.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/neuron.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/neuron.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.NeuronEx", + ShortName: "main.NeuronEx", + IDName: "neuron-ex", + Doc: "Extra state for neuron", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"InISI", >i.Field{Name: "InISI", Type: "float32", LocalType: "float32", Doc: "input ISI countdown for spiking mode -- counts up", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/neuron.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"NeuronEx", >i.Field{Name: "NeuronEx", Type: "github.com/emer/axon/examples/neuron.NeuronEx", LocalType: "NeuronEx", Doc: "extra neuron state for additional channels: VGCC, AK", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "logging", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "all parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Cycle", >i.Field{Name: "Cycle", Type: "int", LocalType: "int", Doc: "current cycle of updating", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"TstCycPlot", >i.Field{Name: "TstCycPlot", Type: "*goki.dev/etable/v2/eplot.Plot2D", LocalType: "*eplot.Plot2D", Doc: "the test-trial plot", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"ValMap", >i.Field{Name: "ValMap", Type: "map[string]float32", LocalType: "map[string]float32", Doc: "map of values for detailed debugging / testing", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/neuron/neuron.go b/examples/neuron/neuron.go index 86b5652a5..26bcdf94d 100644 --- a/examples/neuron/neuron.go +++ b/examples/neuron/neuron.go @@ -9,6 +9,8 @@ influences (including leak and synaptic inhibition). */ package main +//go:generate goki generate -add-types + import ( "fmt" "log" @@ -27,7 +29,6 @@ import ( "github.com/emer/emergent/v2/params" "github.com/emer/emergent/v2/prjn" "github.com/emer/empi/v2/mpi" - "github.com/goki/ki/ki" "goki.dev/etable/v2/eplot" "goki.dev/etable/v2/etable" "goki.dev/etable/v2/etensor" @@ -35,8 +36,6 @@ import ( "goki.dev/etable/v2/minmax" "goki.dev/gi/v2/gi" "goki.dev/gi/v2/gimain" - "goki.dev/gi/v2/giv" - "goki.dev/mat32/v2" ) func main() { @@ -44,7 +43,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(sim.RunGUI) + gimain.Run(sim.RunGUI) } else { sim.RunNoGUI() } @@ -117,26 +116,17 @@ type Sim struct { // current cycle of updating Cycle int `inactive:"+"` - // main GUI window - Win *gi.Window `view:"-"` - - // the network viewer - NetView *netview.NetView `view:"-"` + // netview update parameters + ViewUpdt netview.ViewUpdt `view:"inline"` - // the master toolbar - ToolBar *gi.ToolBar `view:"-"` + // manages all the gui elements + GUI egui.GUI `view:"-"` // the test-trial plot TstCycPlot *eplot.Plot2D `view:"-"` // map of values for detailed debugging / testing ValMap map[string]float32 `view:"-"` - - // true if sim is running - IsRunning bool `view:"-"` - - // flag to stop running - StopNow bool `view:"-"` } // New creates new blank elements and initializes defaults @@ -199,9 +189,8 @@ func (ss *Sim) Init() { ss.Context.Reset() ss.InitWts(ss.Net) ss.NeuronEx.Init() - ss.StopNow = false + ss.GUI.StopNow = false ss.SetParams("", false) // all sheets - ss.UpdateView() } // Counters returns a string of the current counter state @@ -213,11 +202,8 @@ func (ss *Sim) Counters() string { func (ss *Sim) UpdateView() { ss.TstCycPlot.UpdatePlot() - if ss.NetView != nil && ss.NetView.IsVisible() { - ss.NetView.Record(ss.Counters(), int(ss.Context.Cycle)) - // note: essential to use Go version of update when called from another goroutine - ss.NetView.GoUpdate() // note: using counters is significantly slower.. - } + ss.GUI.ViewUpdt.Text = ss.Counters() + ss.GUI.ViewUpdt.UpdateCycle(int(ss.Context.Cycle)) } //////////////////////////////////////////////////////////////////////////////// @@ -227,7 +213,7 @@ func (ss *Sim) UpdateView() { func (ss *Sim) RunCycles() { ctx := &ss.Context ss.Init() - ss.StopNow = false + ss.GUI.StopNow = false ss.Net.InitActs(ctx) ctx.NewState(etime.Train) ss.SetParams("", false) @@ -249,7 +235,7 @@ func (ss *Sim) RunCycles() { ss.UpdateView() } ss.Context.CycleInc() - if ss.StopNow { + if ss.GUI.StopNow { break } } @@ -314,7 +300,7 @@ func (ss *Sim) NeuronUpdt(nt *axon.Network, inputOn bool) { // Stop tells the sim to stop running func (ss *Sim) Stop() { - ss.StopNow = true + ss.GUI.StopNow = true } ///////////////////////////////////////////////////////////////////////// @@ -387,7 +373,7 @@ func (ss *Sim) ConfigLogItems() { func (ss *Sim) ResetTstCycPlot() { ss.Logs.ResetLog(etime.Test, etime.Cycle) - ss.TstCycPlot.Update() + ss.TstCycPlot.GoUpdatePlot() } //////////////////////////////////////////////////////////////////////////////////////////// @@ -398,115 +384,82 @@ func (ss *Sim) ConfigNetView(nv *netview.NetView) { } // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { - width := 1600 - height := 1200 - - gi.SetAppName("neuron") - gi.SetAppAbout(`This simulation illustrates the basic properties of neural spiking and -rate-code activation, reflecting a balance of excitatory and inhibitory -influences (including leak and synaptic inhibition). -See README.md on GitHub.

`) - - win := gi.NewMainWindow("neuron", "Neuron", width, height) - ss.Win = win +func (ss *Sim) ConfigGUI() { + title := "Neuron" + ss.GUI.MakeBody(ss, "neuron", title, `This simulation illustrates the basic properties of neural spiking and rate-code activation, reflecting a balance of excitatory and inhibitory influences (including leak and synaptic inhibition). See README.md on GitHub.

`) + ss.GUI.CycleUpdateInterval = 10 - vp := win.WinViewport2D() - updt := vp.UpdateStart() - - mfr := win.SetMainFrame() - - tbar := gi.AddNewToolBar(mfr, "tbar") - tbar.SetStretchMaxWidth() - ss.ToolBar = tbar - - split := gi.AddNewSplitView(mfr, "split") - split.Dim = mat32.X - split.SetStretchMaxWidth() - split.SetStretchMaxHeight() - - sv := giv.AddNewStructView(split, "sv") - sv.SetStruct(ss) - - tv := gi.AddNewTabView(split, "tv") - - nv := tv.AddNewTab(netview.KiT_NetView, "NetView").(*netview.NetView) + nv := ss.GUI.AddNetView("NetView") nv.Var = "Act" nv.SetNet(ss.Net) - ss.NetView = nv ss.ConfigNetView(nv) // add labels etc + ss.ViewUpdt.Config(nv, etime.AlphaCycle, etime.AlphaCycle) + ss.GUI.ViewUpdt = &ss.ViewUpdt - plt := tv.AddNewTab(eplot.KiT_Plot2D, "TstCycPlot").(*eplot.Plot2D) + plt := eplot.NewPlot2D(ss.GUI.Tabs.NewTab("TstCycPlot")) key := etime.Scope(etime.Test, etime.Cycle) plt.SetTable(ss.Logs.Table(etime.Test, etime.Cycle)) egui.ConfigPlotFromLog("Neuron", plt, &ss.Logs, key) ss.TstCycPlot = plt - split.SetSplits(.2, .8) - - tbar.AddAction(gi.ActOpts{Label: "Init", Icon: "update", Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", UpdateFunc: func(act *gi.Action) { - act.SetActiveStateUpdt(!ss.IsRunning) - }}, win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { - ss.Init() - vp.SetNeedsFullRender() - }) - - tbar.AddAction(gi.ActOpts{Label: "Stop", Icon: "stop", Tooltip: "Interrupts running. Hitting Train again will pick back up where it left off.", UpdateFunc: func(act *gi.Action) { - act.SetActiveStateUpdt(ss.IsRunning) - }}, win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { - ss.Stop() - }) - - tbar.AddAction(gi.ActOpts{Label: "Run Cycles", Icon: "step-fwd", Tooltip: "Runs neuron updating over NCycles.", UpdateFunc: func(act *gi.Action) { - act.SetActiveStateUpdt(!ss.IsRunning) - }}, win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { - if !ss.IsRunning { - ss.IsRunning = true - ss.RunCycles() - ss.IsRunning = false - vp.SetNeedsFullRender() - } - }) - - tbar.AddSeparator("run-sep") - - tbar.AddAction(gi.ActOpts{Label: "Reset Plot", Icon: "update", Tooltip: "Reset TstCycPlot.", UpdateFunc: func(act *gi.Action) { - act.SetActiveStateUpdt(!ss.IsRunning) - }}, win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { - if !ss.IsRunning { - ss.ResetTstCycPlot() - } - }) - - tbar.AddAction(gi.ActOpts{Label: "Defaults", Icon: "update", Tooltip: "Restore initial default parameters.", UpdateFunc: func(act *gi.Action) { - act.SetActiveStateUpdt(!ss.IsRunning) - }}, win.This(), func(recv, send ki.Ki, sig int64, data interface{}) { - ss.Defaults() - ss.Init() - vp.SetNeedsFullRender() - }) - - tbar.AddAction(gi.ActOpts{Label: "README", Icon: "file-markdown", Tooltip: "Opens your browser on the README file that contains instructions for how to run this model."}, win.This(), - func(recv, send ki.Ki, sig int64, data interface{}) { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/neuron/README.md") + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Stop", Icon: "stop", + Tooltip: "Stops running.", + Active: egui.ActiveRunning, + Func: func() { + ss.Stop() + ss.GUI.UpdateWindow() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Run Cycles", Icon: "step-fwd", + Tooltip: "Runs neuron updating over NCycles.", + Active: egui.ActiveStopped, + Func: func() { + if !ss.GUI.IsRunning { + ss.GUI.IsRunning = true + ss.RunCycles() + ss.GUI.IsRunning = false + ss.GUI.UpdateWindow() + } + }, + }) + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset Plot", Icon: "update", + Tooltip: "Reset TstCycPlot.", + Active: egui.ActiveStopped, + Func: func() { + ss.ResetTstCycPlot() + ss.GUI.UpdateWindow() + }, }) - vp.UpdateEndNoSig(updt) - - // main menu - appnm := gi.AppName() - mmen := win.MainMenu - mmen.ConfigMenus([]string{appnm, "File", "Edit", "Window"}) - - amen := win.MainMenu.ChildByName(appnm, 0).(*gi.Action) - amen.Menu.AddAppMenu(win) - - emen := win.MainMenu.ChildByName("Edit", 1).(*gi.Action) - emen.Menu.AddCopyCutPaste(win) - - win.SetCloseCleanFunc(func(w *gi.Window) { - go gi.Quit() // once main window is closed, quit + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Defaults", Icon: "update", + Tooltip: "Restore initial default parameters.", + Active: egui.ActiveStopped, + Func: func() { + ss.Defaults() + ss.Init() + ss.GUI.UpdateWindow() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/neuron/README.md") + }, + }) }) + ss.GUI.FinalizeGUI(false) if ss.Config.Run.GPU { ss.Net.ConfigGPUwithGUI(&ss.Context) @@ -514,15 +467,12 @@ See 1 then does selection among options presented in parallel (not yet supported / tested) -- otherwise does go / no on a single optoin (default)", Directives: gti.Directives{}, Tag: "def:\"1\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- generally faster even for small models if NData ~16", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"NData", >i.Field{Name: "NData", Type: "int", LocalType: "int", Doc: "number of data-parallel items to process in parallel per trial -- works (and is significantly faster) for both CPU and GPU. Results in an effective mini-batch of learning.", Directives: gti.Directives{}, Tag: "def:\"16\" min:\"1\""}}, + {"NThreads", >i.Field{Name: "NThreads", Type: "int", LocalType: "int", Doc: "number of parallel threads for CPU computation -- 0 = use default", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"Run", >i.Field{Name: "Run", Type: "int", LocalType: "int", Doc: "starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"NRuns", >i.Field{Name: "NRuns", Type: "int", LocalType: "int", Doc: "total number of runs to do when running Train", Directives: gti.Directives{}, Tag: "def:\"1\" min:\"1\""}}, + {"NEpochs", >i.Field{Name: "NEpochs", Type: "int", LocalType: "int", Doc: "total number of epochs per run", Directives: gti.Directives{}, Tag: "def:\"30\""}}, + {"NTrials", >i.Field{Name: "NTrials", Type: "int", LocalType: "int", Doc: "total number of trials per epoch. Should be an even multiple of NData.", Directives: gti.Directives{}, Tag: "def:\"128\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"SaveWts", >i.Field{Name: "SaveWts", Type: "bool", LocalType: "bool", Doc: "if true, save final weights after each run", Directives: gti.Directives{}, Tag: ""}}, + {"Epoch", >i.Field{Name: "Epoch", Type: "bool", LocalType: "bool", Doc: "if true, save train epoch log to file, as .epc.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Run", >i.Field{Name: "Run", Type: "bool", LocalType: "bool", Doc: "if true, save run log to file, as .run.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "bool", LocalType: "bool", Doc: "if true, save train trial log to file, as .trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestEpoch", >i.Field{Name: "TestEpoch", Type: "bool", LocalType: "bool", Doc: "if true, save testing epoch log to file, as .tst_epc.tsv typically. In general it is better to copy testing items over to the training epoch log and record there.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"TestTrial", >i.Field{Name: "TestTrial", Type: "bool", LocalType: "bool", Doc: "if true, save testing trial log to file, as .tst_trl.tsv typically. May be large.", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + {"Testing", >i.Field{Name: "Testing", Type: "bool", LocalType: "bool", Doc: "activates testing mode -- records detailed data for Go CI tests (not the same as running test mode on network, via Looper)", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Env", >i.Field{Name: "Env", Type: "github.com/emer/axon/examples/pcore.EnvConfig", LocalType: "EnvConfig", Doc: "environment configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/pcore.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/pcore.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/pcore.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.GoNoEnv", + ShortName: "main.GoNoEnv", + IDName: "go-no-env", + Doc: "GoNoEnv implements simple Go vs. NoGo input patterns to test BG learning.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Nm", >i.Field{Name: "Nm", Type: "string", LocalType: "string", Doc: "name of environment -- Train or Test", Directives: gti.Directives{}, Tag: ""}}, + {"Mode", >i.Field{Name: "Mode", Type: "github.com/emer/emergent/v2/etime.Modes", LocalType: "etime.Modes", Doc: "training or testing env?", Directives: gti.Directives{}, Tag: ""}}, + {"Trial", >i.Field{Name: "Trial", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "trial counter -- set by caller for testing", Directives: gti.Directives{}, Tag: ""}}, + {"ACCPos", >i.Field{Name: "ACCPos", Type: "float32", LocalType: "float32", Doc: "activation of ACC positive valence -- drives go", Directives: gti.Directives{}, Tag: ""}}, + {"ACCNeg", >i.Field{Name: "ACCNeg", Type: "float32", LocalType: "float32", Doc: "activation of ACC neg valence -- drives nogo", Directives: gti.Directives{}, Tag: ""}}, + {"PosNegThr", >i.Field{Name: "PosNegThr", Type: "float32", LocalType: "float32", Doc: "threshold on diff between ACCPos - ACCNeg for counting as a Go trial", Directives: gti.Directives{}, Tag: ""}}, + {"ManualVals", >i.Field{Name: "ManualVals", Type: "bool", LocalType: "bool", Doc: "ACCPos and Neg are set manually -- do not generate random vals for training or auto-increment ACCPos / Neg values during test", Directives: gti.Directives{}, Tag: ""}}, + {"TestInc", >i.Field{Name: "TestInc", Type: "float32", LocalType: "float32", Doc: "increment in testing activation for test all", Directives: gti.Directives{}, Tag: ""}}, + {"TestReps", >i.Field{Name: "TestReps", Type: "int", LocalType: "int", Doc: "number of repetitions per testing level", Directives: gti.Directives{}, Tag: ""}}, + {"NPools", >i.Field{Name: "NPools", Type: "int", LocalType: "int", Doc: "number of pools for representing multiple different options to be evaluated in parallel, vs. 1 pool with a simple go nogo overall choice -- currently tested / configured for the 1 pool case", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"ACCPosInc", >i.Field{Name: "ACCPosInc", Type: "float32", LocalType: "float32", Doc: "for case with multiple pools evaluated in parallel (not currently used), this is the across-pools multiplier in activation of ACC positive valence -- e.g., .9 daecrements subsequent units by 10%", Directives: gti.Directives{}, Tag: ""}}, + {"ACCNegInc", >i.Field{Name: "ACCNegInc", Type: "float32", LocalType: "float32", Doc: "for case with multiple pools evaluated in parallel (not currently used), this is the across-pools multiplier in activation of ACC neg valence, e.g., 1.1 increments subsequent units by 10%", Directives: gti.Directives{}, Tag: ""}}, + {"NUnitsY", >i.Field{Name: "NUnitsY", Type: "int", LocalType: "int", Doc: "number of units within each pool, Y", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"NUnitsX", >i.Field{Name: "NUnitsX", Type: "int", LocalType: "int", Doc: "number of units within each pool, X", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"NUnits", >i.Field{Name: "NUnits", Type: "int", LocalType: "int", Doc: "total number of units within each pool", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"InN", >i.Field{Name: "InN", Type: "int", LocalType: "int", Doc: "number of different values for PFC to learn in input layer -- gives PFC network something to do", Directives: gti.Directives{}, Tag: ""}}, + {"PopCode", >i.Field{Name: "PopCode", Type: "github.com/emer/emergent/v2/popcode.OneD", LocalType: "popcode.OneD", Doc: "pop code the values in ACCPos and Neg", Directives: gti.Directives{}, Tag: ""}}, + {"Rand", >i.Field{Name: "Rand", Type: "github.com/emer/emergent/v2/erand.SysRand", LocalType: "erand.SysRand", Doc: "random number generator for the env -- all random calls must use this", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeed", >i.Field{Name: "RndSeed", Type: "int64", LocalType: "int64", Doc: "random seed", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"States", >i.Field{Name: "States", Type: "map[string]*goki.dev/etable/v2/etensor.Float32", LocalType: "map[string]*etensor.Float32", Doc: "named states: ACCPos, ACCNeg", Directives: gti.Directives{}, Tag: ""}}, + {"Should", >i.Field{Name: "Should", Type: "bool", LocalType: "bool", Doc: "true if Pos - Neg > Thr", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"Gated", >i.Field{Name: "Gated", Type: "bool", LocalType: "bool", Doc: "true if model gated on this trial", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"Match", >i.Field{Name: "Match", Type: "bool", LocalType: "bool", Doc: "true if gated == should", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"Rew", >i.Field{Name: "Rew", Type: "float32", LocalType: "float32", Doc: "reward based on match between Should vs. Gated", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"InCtr", >i.Field{Name: "InCtr", Type: "int", LocalType: "int", Doc: "input counter -- gives PFC network something to do", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/pcore.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "all parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Loops", >i.Field{Name: "Loops", Type: "*github.com/emer/emergent/v2/looper.Manager", LocalType: "*looper.Manager", Doc: "contains looper control loops for running sim", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "Contains all the logs and information about the logs.'", Directives: gti.Directives{}, Tag: ""}}, + {"Envs", >i.Field{Name: "Envs", Type: "github.com/emer/emergent/v2/env.Envs", LocalType: "env.Envs", Doc: "Environments", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeeds", >i.Field{Name: "RndSeeds", Type: "github.com/emer/emergent/v2/erand.Seeds", LocalType: "erand.Seeds", Doc: "a list of random seeds to use for each run", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/pcore/pcore.go b/examples/pcore/pcore.go index 457658148..5ecd118eb 100644 --- a/examples/pcore/pcore.go +++ b/examples/pcore/pcore.go @@ -7,6 +7,8 @@ pcore: This project simulates the inhibitory dynamics in the STN and GPe leading */ package main +//go:generate goki generate -add-types + import ( "fmt" "os" @@ -33,7 +35,7 @@ import ( "goki.dev/etable/v2/split" "goki.dev/gi/v2/gi" "goki.dev/gi/v2/gimain" - "goki.dev/glop/bools" + "goki.dev/glop/num" "goki.dev/mat32/v2" ) @@ -42,7 +44,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(sim.RunGUI) + gimain.Run(sim.RunGUI) } else { sim.RunNoGUI() } @@ -531,9 +533,9 @@ func (ss *Sim) TrialStats(di int) { ev := ss.Envs.ByModeDi(ctx.Mode, di).(*GoNoEnv) ss.Stats.SetFloat32("ACCPos", ev.ACCPos) ss.Stats.SetFloat32("ACCNeg", ev.ACCNeg) - ss.Stats.SetFloat32("Gated", bools.ToFloat32(ev.Gated)) - ss.Stats.SetFloat32("Should", bools.ToFloat32(ev.Should)) - ss.Stats.SetFloat32("Match", bools.ToFloat32(ev.Match)) + ss.Stats.SetFloat32("Gated", num.FromBool[float32](ev.Gated)) + ss.Stats.SetFloat32("Should", num.FromBool[float32](ev.Should)) + ss.Stats.SetFloat32("Match", num.FromBool[float32](ev.Match)) ss.Stats.SetFloat32("Rew", ev.Rew) ss.Stats.SetFloat32("PFCVM_RT", ss.Stats.Float32Di("PFCVM_RT", di)) ss.Stats.SetFloat32("PFCVM_ActAvg", ss.Stats.Float32Di("PFCVM_ActAvg", di)) @@ -647,9 +649,9 @@ func (ss *Sim) TestStats() { // Gui // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { +func (ss *Sim) ConfigGUI() { title := "PCore Test" - ss.GUI.MakeWindow(ss, "pcore", title, `This project simulates the inhibitory dynamics in the STN and GPe leading to integration of Go vs. NoGo signal in the basal ganglia. See axon on GitHub.

`) + ss.GUI.MakeBody(ss, "pcore", title, `This project simulates the inhibitory dynamics in the STN and GPe leading to integration of Go vs. NoGo signal in the basal ganglia. See axon on GitHub.

`) ss.GUI.CycleUpdateInterval = 20 nv := ss.GUI.AddNetView("NetView") @@ -667,59 +669,61 @@ func (ss *Sim) ConfigGUI() *gi.Window { tststnm := "TestTrialStats" tstst := ss.Logs.MiscTable(tststnm) - plt := ss.GUI.TabView.AddNewTab(eplot.KiT_Plot2D, tststnm+" Plot").(*eplot.Plot2D) + plt := eplot.NewPlot2D(ss.GUI.Tabs.NewTab(tststnm + " Plot")) ss.GUI.Plots[etime.ScopeKey(tststnm)] = plt plt.Params.Title = tststnm plt.Params.XAxisCol = "Trial" plt.SetTable(tstst) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", - Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", - Active: egui.ActiveStopped, - Func: func() { - ss.Init() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddLooperCtrl(ss.Loops, []etime.Modes{etime.Train, etime.Test}) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "TestInit", Icon: "update", - Tooltip: "reinitialize the testing control so it re-runs.", - Active: egui.ActiveStopped, - Func: func() { - ss.Loops.ResetCountersByMode(etime.Test) - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.AddLooperCtrl(tb, ss.Loops, []etime.Modes{etime.Train, etime.Test}) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "TestInit", Icon: "update", + Tooltip: "reinitialize the testing control so it re-runs.", + Active: egui.ActiveStopped, + Func: func() { + ss.Loops.ResetCountersByMode(etime.Test) + ss.GUI.UpdateWindow() + }, + }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"log") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", - Icon: "reset", - Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", - Active: egui.ActiveAlways, - Func: func() { - ss.Logs.ResetLog(etime.Train, etime.Run) - ss.GUI.UpdatePlot(etime.Train, etime.Run) - }, - }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"misc") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", - Icon: "new", - Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", - Active: egui.ActiveAlways, - Func: func() { - ss.RndSeeds.NewSeeds() - }, - }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", - Icon: "file-markdown", - Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", - Active: egui.ActiveAlways, - Func: func() { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/pcore/README.md") - }, + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", + Icon: "reset", + Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", + Active: egui.ActiveAlways, + Func: func() { + ss.Logs.ResetLog(etime.Train, etime.Run) + ss.GUI.UpdatePlot(etime.Train, etime.Run) + }, + }) + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", + Icon: "new", + Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", + Active: egui.ActiveAlways, + Func: func() { + ss.RndSeeds.NewSeeds() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/pcore/README.md") + }, + }) }) ss.GUI.FinalizeGUI(false) if ss.Config.Run.GPU { @@ -729,13 +733,12 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.Net.GPU.Destroy() }) } - return ss.GUI.Win } func (ss *Sim) RunGUI() { ss.Init() - win := ss.ConfigGUI() - win.StartEventLoop() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/pvlv/cond/blocks_test.go b/examples/pvlv/cond/blocks_test.go index 4b63b9a33..02fb23e86 100644 --- a/examples/pvlv/cond/blocks_test.go +++ b/examples/pvlv/cond/blocks_test.go @@ -8,8 +8,6 @@ import ( "fmt" "strings" "testing" - - "github.com/goki/ki/ints" ) func TestCSContext(t *testing.T) { @@ -22,7 +20,7 @@ func TestCSContext(t *testing.T) { css[trl.CS] = cnt + 1 cnt = ctxs[trl.Context] ctxs[trl.Context] = cnt + 1 - maxTicks = ints.MaxInt(maxTicks, trl.NTicks) + maxTicks = max(maxTicks, trl.NTicks) if trl.CS == "" { t.Errorf("CS is empty: %s in block: %s trial: %s\n", trl.CS, blnm, trl.Name) diff --git a/examples/pvlv/cond/enumgen.go b/examples/pvlv/cond/enumgen.go new file mode 100644 index 000000000..3b85eb9e0 --- /dev/null +++ b/examples/pvlv/cond/enumgen.go @@ -0,0 +1,121 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package cond + +import ( + "errors" + "log" + "strconv" + "strings" + + "goki.dev/enums" +) + +var _ValenceValues = []Valence{0, 1} + +// ValenceN is the highest valid value +// for type Valence, plus one. +const ValenceN Valence = 2 + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the enumgen command to generate them again. +func _ValenceNoOp() { + var x [1]struct{} + _ = x[Pos-(0)] + _ = x[Neg-(1)] +} + +var _ValenceNameToValueMap = map[string]Valence{ + `Pos`: 0, + `pos`: 0, + `Neg`: 1, + `neg`: 1, +} + +var _ValenceDescMap = map[Valence]string{ + 0: ``, + 1: ``, +} + +var _ValenceMap = map[Valence]string{ + 0: `Pos`, + 1: `Neg`, +} + +// String returns the string representation +// of this Valence value. +func (i Valence) String() string { + if str, ok := _ValenceMap[i]; ok { + return str + } + return strconv.FormatInt(int64(i), 10) +} + +// SetString sets the Valence value from its +// string representation, and returns an +// error if the string is invalid. +func (i *Valence) SetString(s string) error { + if val, ok := _ValenceNameToValueMap[s]; ok { + *i = val + return nil + } + if val, ok := _ValenceNameToValueMap[strings.ToLower(s)]; ok { + *i = val + return nil + } + return errors.New(s + " is not a valid value for type Valence") +} + +// Int64 returns the Valence value as an int64. +func (i Valence) Int64() int64 { + return int64(i) +} + +// SetInt64 sets the Valence value from an int64. +func (i *Valence) SetInt64(in int64) { + *i = Valence(in) +} + +// Desc returns the description of the Valence value. +func (i Valence) Desc() string { + if str, ok := _ValenceDescMap[i]; ok { + return str + } + return i.String() +} + +// ValenceValues returns all possible values +// for the type Valence. +func ValenceValues() []Valence { + return _ValenceValues +} + +// Values returns all possible values +// for the type Valence. +func (i Valence) Values() []enums.Enum { + res := make([]enums.Enum, len(_ValenceValues)) + for i, d := range _ValenceValues { + res[i] = d + } + return res +} + +// IsValid returns whether the value is a +// valid option for type Valence. +func (i Valence) IsValid() bool { + _, ok := _ValenceMap[i] + return ok +} + +// MarshalText implements the [encoding.TextMarshaler] interface. +func (i Valence) MarshalText() ([]byte, error) { + return []byte(i.String()), nil +} + +// UnmarshalText implements the [encoding.TextUnmarshaler] interface. +func (i *Valence) UnmarshalText(text []byte) error { + if err := i.SetString(string(text)); err != nil { + log.Println(err) + } + return nil +} diff --git a/examples/pvlv/cond/env.go b/examples/pvlv/cond/env.go index 410afb87e..c55ab9620 100644 --- a/examples/pvlv/cond/env.go +++ b/examples/pvlv/cond/env.go @@ -4,12 +4,13 @@ package cond +//go:generate goki generate -add-types + import ( "fmt" - "github.com/emer/emergent/env" - "github.com/emer/etable/etensor" - "github.com/goki/ki/ints" + "github.com/emer/emergent/v2/env" + "goki.dev/etable/v2/etensor" ) // CondEnv provides a flexible implementation of standard Pavlovian @@ -223,9 +224,9 @@ func (ev *CondEnv) RenderTrial(trli, tick int) { } minStart := trl.CSStart if trl.CS2Start > 0 { - minStart = ints.MinInt(minStart, trl.CS2Start) + minStart = min(minStart, trl.CS2Start) } - maxEnd := ints.MaxInt(trl.CSEnd, trl.CS2End) + maxEnd := max(trl.CSEnd, trl.CS2End) if tick >= minStart && tick <= maxEnd { SetContext(ctxt, ev.NYReps, trl.Context) diff --git a/examples/pvlv/cond/gtigen.go b/examples/pvlv/cond/gtigen.go new file mode 100644 index 000000000..77d1e1ecd --- /dev/null +++ b/examples/pvlv/cond/gtigen.go @@ -0,0 +1,131 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package cond + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "github.com/emer/axon/examples/pvlv/cond.Condition", + ShortName: "cond.Condition", + IDName: "condition", + Doc: "Condition defines parameters for running a specific type of conditioning expt", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Name", >i.Field{Name: "Name", Type: "string", LocalType: "string", Doc: "identifier for this type of configuration", Directives: gti.Directives{}, Tag: ""}}, + {"Desc", >i.Field{Name: "Desc", Type: "string", LocalType: "string", Doc: "description of this configuration", Directives: gti.Directives{}, Tag: ""}}, + {"Block", >i.Field{Name: "Block", Type: "string", LocalType: "string", Doc: "mix of trial types per block to run -- must be listed in AllBlocks", Directives: gti.Directives{}, Tag: ""}}, + {"FixedProb", >i.Field{Name: "FixedProb", Type: "bool", LocalType: "bool", Doc: "use a permuted list to ensure an exact number of trials have US -- else random draw each time", Directives: gti.Directives{}, Tag: ""}}, + {"NBlocks", >i.Field{Name: "NBlocks", Type: "int", LocalType: "int", Doc: "number of full blocks of different trial types to run (like Epochs)", Directives: gti.Directives{}, Tag: ""}}, + {"NTrials", >i.Field{Name: "NTrials", Type: "int", LocalType: "int", Doc: "number of behavioral trials per block -- blocks, with the different types of Trials specified in Block allocated across these Trials. More different trial types and greater stochasticity (lower probability) of US presentation requires more trials.", Directives: gti.Directives{}, Tag: ""}}, + {"Permute", >i.Field{Name: "Permute", Type: "bool", LocalType: "bool", Doc: "permute list of generated trials in random order after generation -- otherwise presented in order specified in the Block type", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "github.com/emer/axon/examples/pvlv/cond.CondEnv", + ShortName: "cond.CondEnv", + IDName: "cond-env", + Doc: "CondEnv provides a flexible implementation of standard Pavlovian\nconditioning experiments involving CS -> US sequences (trials).\nHas a large database of standard conditioning paradigms\nparameterized in a controlled manner.\n\nTime hierarchy:\n* Run = sequence of 1 or more Conditions\n* Condition = specific mix of trial types, generated at start of Condition\n* Block = one full pass through all trial types generated for condition (like Epoch)\n* Trial = one behavioral trial consisting of CS -> US presentation over time steps (Ticks)\n* Tick = discrete time steps within behavioral Trial, typically one Network update (Alpha / Theta cycle)", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Nm", >i.Field{Name: "Nm", Type: "string", LocalType: "string", Doc: "name of this environment", Directives: gti.Directives{}, Tag: ""}}, + {"Dsc", >i.Field{Name: "Dsc", Type: "string", LocalType: "string", Doc: "description of this environment", Directives: gti.Directives{}, Tag: ""}}, + {"NYReps", >i.Field{Name: "NYReps", Type: "int", LocalType: "int", Doc: "number of Y repetitions for localist reps", Directives: gti.Directives{}, Tag: ""}}, + {"RunName", >i.Field{Name: "RunName", Type: "string", LocalType: "string", Doc: "current run name", Directives: gti.Directives{}, Tag: ""}}, + {"RunDesc", >i.Field{Name: "RunDesc", Type: "string", LocalType: "string", Doc: "description of current run", Directives: gti.Directives{}, Tag: ""}}, + {"CondName", >i.Field{Name: "CondName", Type: "string", LocalType: "string", Doc: "name of current condition", Directives: gti.Directives{}, Tag: ""}}, + {"CondDesc", >i.Field{Name: "CondDesc", Type: "string", LocalType: "string", Doc: "description of current condition", Directives: gti.Directives{}, Tag: ""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "counter over runs", Directives: gti.Directives{}, Tag: "inactive:\"+\" view:\"inline\""}}, + {"Condition", >i.Field{Name: "Condition", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "counter over Condition within a run -- Max depends on number of conditions specified in given Run", Directives: gti.Directives{}, Tag: "inactive:\"+\" view:\"inline\""}}, + {"Block", >i.Field{Name: "Block", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "counter over full blocks of all trial types within a Condition -- like an Epoch", Directives: gti.Directives{}, Tag: "inactive:\"+\" view:\"inline\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "counter of behavioral trials within a Block", Directives: gti.Directives{}, Tag: "inactive:\"+\" view:\"inline\""}}, + {"Tick", >i.Field{Name: "Tick", Type: "github.com/emer/emergent/v2/env.Ctr", LocalType: "env.Ctr", Doc: "counter of discrete steps within a behavioral trial -- typically maps onto Alpha / Theta cycle in network", Directives: gti.Directives{}, Tag: "inactive:\"+\" view:\"inline\""}}, + {"TrialName", >i.Field{Name: "TrialName", Type: "string", LocalType: "string", Doc: "name of current trial step", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"TrialType", >i.Field{Name: "TrialType", Type: "string", LocalType: "string", Doc: "type of current trial step", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"USTimeInStr", >i.Field{Name: "USTimeInStr", Type: "string", LocalType: "string", Doc: "decoded value of USTimeIn", Directives: gti.Directives{}, Tag: "inactive:\"+\""}}, + {"Trials", >i.Field{Name: "Trials", Type: "[]*github.com/emer/axon/examples/pvlv/cond.Trial", LocalType: "[]*Trial", Doc: "current generated set of trials per Block", Directives: gti.Directives{}, Tag: ""}}, + {"CurRun", >i.Field{Name: "CurRun", Type: "github.com/emer/axon/examples/pvlv/cond.Run", LocalType: "Run", Doc: "copy of current run parameters", Directives: gti.Directives{}, Tag: ""}}, + {"CurTrial", >i.Field{Name: "CurTrial", Type: "github.com/emer/axon/examples/pvlv/cond.Trial", LocalType: "Trial", Doc: "copy of info for current trial", Directives: gti.Directives{}, Tag: ""}}, + {"CurStates", >i.Field{Name: "CurStates", Type: "map[string]*goki.dev/etable/v2/etensor.Float32", LocalType: "map[string]*etensor.Float32", Doc: "current rendered state tensors -- extensible map", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "github.com/emer/axon/examples/pvlv/cond.Run", + ShortName: "cond.Run", + IDName: "run", + Doc: "Run is a sequence of Conditions to run in order", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Name", >i.Field{Name: "Name", Type: "string", LocalType: "string", Doc: "Name of the run", Directives: gti.Directives{}, Tag: ""}}, + {"Desc", >i.Field{Name: "Desc", Type: "string", LocalType: "string", Doc: "Description", Directives: gti.Directives{}, Tag: ""}}, + {"Weights", >i.Field{Name: "Weights", Type: "string", LocalType: "string", Doc: "name of condition for weights file to load prior to starting -- allows faster testing but weights may be out of date", Directives: gti.Directives{}, Tag: ""}}, + {"Cond1", >i.Field{Name: "Cond1", Type: "string", LocalType: "string", Doc: "name of condition 1", Directives: gti.Directives{}, Tag: ""}}, + {"Cond2", >i.Field{Name: "Cond2", Type: "string", LocalType: "string", Doc: "name of condition 2", Directives: gti.Directives{}, Tag: ""}}, + {"Cond3", >i.Field{Name: "Cond3", Type: "string", LocalType: "string", Doc: "name of condition 3", Directives: gti.Directives{}, Tag: ""}}, + {"Cond4", >i.Field{Name: "Cond4", Type: "string", LocalType: "string", Doc: "name of condition 4", Directives: gti.Directives{}, Tag: ""}}, + {"Cond5", >i.Field{Name: "Cond5", Type: "string", LocalType: "string", Doc: "name of condition 5", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "github.com/emer/axon/examples/pvlv/cond.Valence", + ShortName: "cond.Valence", + IDName: "valence", + Doc: "Valence", + Directives: gti.Directives{ + >i.Directive{Tool: "enums", Directive: "enum", Args: []string{}}, + }, + + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "github.com/emer/axon/examples/pvlv/cond.Trial", + ShortName: "cond.Trial", + IDName: "trial", + Doc: "Trial represents one behavioral trial, unfolding over\nNTicks individual time steps, with one or more CS's (conditioned stimuli)\nand a US (unconditioned stimulus -- outcome).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Name", >i.Field{Name: "Name", Type: "string", LocalType: "string", Doc: "conventional suffixes: _R = reward, _NR = non-reward; _test = test trial (no learning)", Directives: gti.Directives{}, Tag: ""}}, + {"Test", >i.Field{Name: "Test", Type: "bool", LocalType: "bool", Doc: "true if testing only -- no learning", Directives: gti.Directives{}, Tag: ""}}, + {"Pct", >i.Field{Name: "Pct", Type: "float32", LocalType: "float32", Doc: "Percent of all trials for this type", Directives: gti.Directives{}, Tag: ""}}, + {"Valence", >i.Field{Name: "Valence", Type: "github.com/emer/axon/examples/pvlv/cond.Valence", LocalType: "Valence", Doc: "Positive or negative reward valence", Directives: gti.Directives{}, Tag: ""}}, + {"USProb", >i.Field{Name: "USProb", Type: "float32", LocalType: "float32", Doc: "Probability of US", Directives: gti.Directives{}, Tag: ""}}, + {"MixedUS", >i.Field{Name: "MixedUS", Type: "bool", LocalType: "bool", Doc: "Mixed US set?", Directives: gti.Directives{}, Tag: ""}}, + {"USMag", >i.Field{Name: "USMag", Type: "float32", LocalType: "float32", Doc: "US magnitude", Directives: gti.Directives{}, Tag: ""}}, + {"NTicks", >i.Field{Name: "NTicks", Type: "int", LocalType: "int", Doc: "Number of ticks for a trial", Directives: gti.Directives{}, Tag: ""}}, + {"CS", >i.Field{Name: "CS", Type: "string", LocalType: "string", Doc: "Conditioned stimulus", Directives: gti.Directives{}, Tag: ""}}, + {"CSStart", >i.Field{Name: "CSStart", Type: "int", LocalType: "int", Doc: "Tick of CS start", Directives: gti.Directives{}, Tag: ""}}, + {"CSEnd", >i.Field{Name: "CSEnd", Type: "int", LocalType: "int", Doc: "Tick of CS end", Directives: gti.Directives{}, Tag: ""}}, + {"CS2Start", >i.Field{Name: "CS2Start", Type: "int", LocalType: "int", Doc: "Tick of CS2 start: -1 for none", Directives: gti.Directives{}, Tag: ""}}, + {"CS2End", >i.Field{Name: "CS2End", Type: "int", LocalType: "int", Doc: "Tick of CS2 end: -1 for none", Directives: gti.Directives{}, Tag: ""}}, + {"US", >i.Field{Name: "US", Type: "int", LocalType: "int", Doc: "Unconditioned stimulus", Directives: gti.Directives{}, Tag: ""}}, + {"USStart", >i.Field{Name: "USStart", Type: "int", LocalType: "int", Doc: "Tick for start of US presentation", Directives: gti.Directives{}, Tag: ""}}, + {"USEnd", >i.Field{Name: "USEnd", Type: "int", LocalType: "int", Doc: "Tick for end of US presentation", Directives: gti.Directives{}, Tag: ""}}, + {"Context", >i.Field{Name: "Context", Type: "string", LocalType: "string", Doc: "Context -- typically same as CS -- if blank CS will be copied -- different in certain extinguishing contexts", Directives: gti.Directives{}, Tag: ""}}, + {"USOn", >i.Field{Name: "USOn", Type: "bool", LocalType: "bool", Doc: "for rendered trials, true if US active", Directives: gti.Directives{}, Tag: ""}}, + {"CSOn", >i.Field{Name: "CSOn", Type: "bool", LocalType: "bool", Doc: "for rendered trials, true if CS active", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "github.com/emer/axon/examples/pvlv/cond.Block", + ShortName: "cond.Block", + IDName: "block", + Doc: "Block represents a set of trial types", + Directives: gti.Directives{}, + + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/pvlv/cond/inputs.go b/examples/pvlv/cond/inputs.go index 21ae8523e..db7c76d0c 100644 --- a/examples/pvlv/cond/inputs.go +++ b/examples/pvlv/cond/inputs.go @@ -4,7 +4,7 @@ package cond -import "github.com/emer/etable/etensor" +import "goki.dev/etable/v2/etensor" var ( NUSs = 4 diff --git a/examples/pvlv/cond/trial.go b/examples/pvlv/cond/trial.go index 17ad8c4a5..8962c478e 100644 --- a/examples/pvlv/cond/trial.go +++ b/examples/pvlv/cond/trial.go @@ -7,27 +7,18 @@ package cond import ( "math/rand" - "github.com/emer/emergent/erand" - "github.com/goki/ki/kit" - "github.com/goki/mat32" + "github.com/emer/emergent/v2/erand" + "goki.dev/mat32/v2" ) -//go:generate stringer -type=Valence - // Valence -type Valence int32 +type Valence int32 //enums:enum const ( Pos Valence = iota Neg - ValenceN ) -var KiT_Valence = kit.Enums.AddEnum(ValenceN, kit.NotBitFlag, nil) - -func (ev Valence) MarshalJSON() ([]byte, error) { return kit.EnumMarshalJSON(ev) } -func (ev *Valence) UnmarshalJSON(b []byte) error { return kit.EnumUnmarshalJSON(ev, b) } - // Trial represents one behavioral trial, unfolding over // NTicks individual time steps, with one or more CS's (conditioned stimuli) // and a US (unconditioned stimulus -- outcome). diff --git a/examples/pvlv/cond/valence_string.go b/examples/pvlv/cond/valence_string.go deleted file mode 100644 index b60ca79b1..000000000 --- a/examples/pvlv/cond/valence_string.go +++ /dev/null @@ -1,40 +0,0 @@ -// Code generated by "stringer -type=Valence"; DO NOT EDIT. - -package cond - -import ( - "errors" - "strconv" -) - -var _ = errors.New("dummy error") - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[Pos-0] - _ = x[Neg-1] - _ = x[ValenceN-2] -} - -const _Valence_name = "PosNegValenceN" - -var _Valence_index = [...]uint8{0, 3, 6, 14} - -func (i Valence) String() string { - if i < 0 || i >= Valence(len(_Valence_index)-1) { - return "Valence(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _Valence_name[_Valence_index[i]:_Valence_index[i+1]] -} - -func (i *Valence) FromString(s string) error { - for j := 0; j < len(_Valence_index)-1; j++ { - if s == _Valence_name[_Valence_index[j]:_Valence_index[j+1]] { - *i = Valence(j) - return nil - } - } - return errors.New("String: " + s + " is not a valid option for type: Valence") -} diff --git a/examples/pvlv/effort_plot.go b/examples/pvlv/effort_plot.go index daf47522e..0cf027eb8 100644 --- a/examples/pvlv/effort_plot.go +++ b/examples/pvlv/effort_plot.go @@ -11,7 +11,6 @@ import ( "github.com/emer/axon/axon" "github.com/emer/emergent/v2/erand" - "github.com/goki/ki/ki" "goki.dev/etable/v2/eplot" "goki.dev/etable/v2/etable" "goki.dev/etable/v2/etensor" @@ -19,15 +18,15 @@ import ( "goki.dev/etable/v2/minmax" "goki.dev/gi/v2/gi" "goki.dev/gi/v2/giv" - "goki.dev/glop/bools" - "goki.dev/mat32/v2" + "goki.dev/glop/num" + "goki.dev/icons" ) func DriveEffortGUI() { ep := &DrEffPlot{} ep.Config() - win := ep.ConfigGUI() - win.StartEventLoop() + b := ep.ConfigGUI() + b.NewWindow().Run().Wait() } // LogPrec is precision for saving float values in logs @@ -63,12 +62,6 @@ type DrEffPlot struct { // the plot TimePlot *eplot.Plot2D `view:"-"` - // main GUI window - Win *gi.Window `view:"-"` - - // the master toolbar - ToolBar *gi.ToolBar `view:"-"` - // random number generator Rand erand.SysRand `view:"-"` } @@ -99,7 +92,7 @@ func (ss *DrEffPlot) Update() { } // EffortPlot plots the equation as a function of effort / time -func (ss *DrEffPlot) EffortPlot() { +func (ss *DrEffPlot) EffortPlot() { //gti:add ss.Update() ctx := &ss.Context pp := &ss.PVLV @@ -118,7 +111,7 @@ func (ss *DrEffPlot) EffortPlot() { } // UrgencyPlot plots the equation as a function of effort / time -func (ss *DrEffPlot) UrgencyPlot() { +func (ss *DrEffPlot) UrgencyPlot() { //gti:add ctx := &ss.Context pp := &ss.PVLV ss.Update() @@ -161,7 +154,7 @@ func (ss *DrEffPlot) ConfigPlot(plt *eplot.Plot2D, dt *etable.Table) *eplot.Plot ///////////////////////////////////////////////////////////////// // TimeRun runs the equation over time. -func (ss *DrEffPlot) TimeRun() { +func (ss *DrEffPlot) TimeRun() { //gti:add ss.Update() dt := ss.TimeTable pp := &ss.PVLV @@ -194,7 +187,7 @@ func (ss *DrEffPlot) TimeRun() { dt.SetCellFloat("Drive", ti, float64(dr)) axon.SetGlbUSposV(ctx, 0, axon.GvUSpos, 1, usv) - axon.SetGlbV(ctx, 0, axon.GvHadRew, bools.ToFloat32(usv > 0)) + axon.SetGlbV(ctx, 0, axon.GvHadRew, num.FromBool[float32](usv > 0)) pp.EffortUrgencyUpdt(ctx, 0, 0) pp.DriveUpdt(ctx, 0) } @@ -232,74 +225,28 @@ func (ss *DrEffPlot) ConfigTimePlot(plt *eplot.Plot2D, dt *etable.Table) *eplot. } // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *DrEffPlot) ConfigGUI() *gi.Window { - width := 1600 - height := 1200 - - // gi.WinEventTrace = true - - win := gi.NewMainWindow("dreff_plot", "Drive / Effort / Urgency Plotting", width, height) - ss.Win = win - - vp := win.WinViewport2D() - updt := vp.UpdateStart() +func (ss *DrEffPlot) ConfigGUI() *gi.Body { + b := gi.NewAppBody("dreffa_plot").SetTitle("Drive / Effort / Urgency Plotting") - mfr := win.SetMainFrame() - - tbar := gi.AddNewToolBar(mfr, "tbar") - tbar.SetStretchMaxWidth() - ss.ToolBar = tbar - - split := gi.AddNewSplitView(mfr, "split") - split.Dim = mat32.X - split.SetStretchMax() - - sv := giv.AddNewStructView(split, "sv") + split := gi.NewSplits(b, "split") + sv := giv.NewStructView(split, "sv") sv.SetStruct(ss) - tv := gi.AddNewTabView(split, "tv") + tv := gi.NewTabs(split, "tv") - plt := tv.AddNewTab(eplot.KiT_Plot2D, "EffortPlot").(*eplot.Plot2D) - ss.Plot = ss.ConfigPlot(plt, ss.Table) + ss.Plot = eplot.NewSubPlot(tv.NewTab("Effort Plot")) + ss.ConfigPlot(ss.Plot, ss.Table) - plt = tv.AddNewTab(eplot.KiT_Plot2D, "TimePlot").(*eplot.Plot2D) - ss.TimePlot = ss.ConfigTimePlot(plt, ss.TimeTable) + ss.TimePlot = eplot.NewSubPlot(tv.NewTab("TimePlot")) + ss.ConfigTimePlot(ss.TimePlot, ss.TimeTable) split.SetSplits(.3, .7) - tbar.AddAction(gi.ActOpts{Label: "Effort Plot", Icon: "update", Tooltip: "plot effort equation."}, win.This(), func(recv, send ki.Ki, sig int64, data any) { - ss.EffortPlot() - vp.SetNeedsFullRender() + b.AddAppBar(func(tb *gi.Toolbar) { + giv.NewFuncButton(tb, ss.EffortPlot).SetIcon(icons.PlayArrow) + giv.NewFuncButton(tb, ss.UrgencyPlot).SetIcon(icons.PlayArrow) + giv.NewFuncButton(tb, ss.TimeRun).SetIcon(icons.PlayArrow) }) - tbar.AddAction(gi.ActOpts{Label: "Urgency Plot", Icon: "update", Tooltip: "plot urgency equation."}, win.This(), func(recv, send ki.Ki, sig int64, data any) { - ss.UrgencyPlot() - vp.SetNeedsFullRender() - }) - - tbar.AddAction(gi.ActOpts{Label: "Time Run", Icon: "update", Tooltip: "Run a simulated time-evolution and plot results."}, win.This(), func(recv, send ki.Ki, sig int64, data any) { - ss.TimeRun() - vp.SetNeedsFullRender() - }) - - tbar.AddAction(gi.ActOpts{Label: "README", Icon: "file-markdown", Tooltip: "Opens your browser on the README file that contains instructions for how to run this model."}, win.This(), - func(recv, send ki.Ki, sig int64, data any) { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/pvlv/README.md") - }) - - vp.UpdateEndNoSig(updt) - - // main menu - appnm := gi.AppName() - mmen := win.MainMenu - mmen.ConfigMenus([]string{appnm, "File", "Edit", "Window"}) - - amen := win.MainMenu.ChildByName(appnm, 0).(*gi.Action) - amen.Menu.AddAppMenu(win) - - emen := win.MainMenu.ChildByName("Edit", 1).(*gi.Action) - emen.Menu.AddCopyCutPaste(win) - - win.MainMenuUpdated() - return win + return b } diff --git a/examples/pvlv/gtigen.go b/examples/pvlv/gtigen.go new file mode 100644 index 000000000..594037897 --- /dev/null +++ b/examples/pvlv/gtigen.go @@ -0,0 +1,152 @@ +// Code generated by "goki generate -add-types"; DO NOT EDIT. + +package main + +import ( + "goki.dev/gti" + "goki.dev/ordmap" +) + +var _ = gti.AddType(>i.Type{ + Name: "main.EnvConfig", + ShortName: "main.EnvConfig", + IDName: "env-config", + Doc: "EnvConfig has config params for environment\nnote: only adding fields for key Env params that matter for both Network and Env\nother params are set via the Env map data mechanism.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Env", >i.Field{Name: "Env", Type: "map[string]any", LocalType: "map[string]any", Doc: "env parameters -- can set any field/subfield on Env struct, using standard TOML formatting", Directives: gti.Directives{}, Tag: ""}}, + {"RunName", >i.Field{Name: "RunName", Type: "string", LocalType: "string", Doc: "environment run name", Directives: gti.Directives{}, Tag: "def:\"PosAcq_A100B50\""}}, + {"SetNBlocks", >i.Field{Name: "SetNBlocks", Type: "bool", LocalType: "bool", Doc: "override the default number of blocks to run conditions with NBlocks", Directives: gti.Directives{}, Tag: ""}}, + {"NBlocks", >i.Field{Name: "NBlocks", Type: "int", LocalType: "int", Doc: "number of blocks to run if SetNBlocks is true", Directives: gti.Directives{}, Tag: "viewif:\"SetNBlocks\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.ParamConfig", + ShortName: "main.ParamConfig", + IDName: "param-config", + Doc: "ParamConfig has config parameters related to sim params", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"PVLV", >i.Field{Name: "PVLV", Type: "map[string]any", LocalType: "map[string]any", Doc: "PVLV parameters -- can set any field/subfield on Net.PVLV params, using standard TOML formatting", Directives: gti.Directives{}, Tag: ""}}, + {"Network", >i.Field{Name: "Network", Type: "map[string]any", LocalType: "map[string]any", Doc: "network parameters", Directives: gti.Directives{}, Tag: ""}}, + {"Sheet", >i.Field{Name: "Sheet", Type: "string", LocalType: "string", Doc: "Extra Param Sheet name(s) to use (space separated if multiple) -- must be valid name as listed in compiled-in params or loaded params", Directives: gti.Directives{}, Tag: ""}}, + {"Tag", >i.Field{Name: "Tag", Type: "string", LocalType: "string", Doc: "extra tag to add to file names and logs saved from this run", Directives: gti.Directives{}, Tag: ""}}, + {"Note", >i.Field{Name: "Note", Type: "string", LocalType: "string", Doc: "user note -- describe the run params etc -- like a git commit message for the run", Directives: gti.Directives{}, Tag: ""}}, + {"File", >i.Field{Name: "File", Type: "string", LocalType: "string", Doc: "Name of the JSON file to input saved parameters from.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"SaveAll", >i.Field{Name: "SaveAll", Type: "bool", LocalType: "bool", Doc: "Save a snapshot of all current param and config settings in a directory named params_ (or _good if Good is true), then quit -- useful for comparing to later changes and seeing multiple views of current params", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + {"Good", >i.Field{Name: "Good", Type: "bool", LocalType: "bool", Doc: "for SaveAll, save to params_good for a known good params state. This can be done prior to making a new release after all tests are passing -- add results to git to provide a full diff record of all params over time.", Directives: gti.Directives{}, Tag: "nest:\"+\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.RunConfig", + ShortName: "main.RunConfig", + IDName: "run-config", + Doc: "RunConfig has config parameters related to running the sim", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"GPU", >i.Field{Name: "GPU", Type: "bool", LocalType: "bool", Doc: "use the GPU for computation -- only for testing in this model -- not faster", Directives: gti.Directives{}, Tag: "def:\"false\""}}, + {"NThreads", >i.Field{Name: "NThreads", Type: "int", LocalType: "int", Doc: "number of parallel threads for CPU computation -- 0 = use default", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"Run", >i.Field{Name: "Run", Type: "int", LocalType: "int", Doc: "starting run number -- determines the random seed -- runs counts from there -- can do all runs in parallel by launching separate jobs with each run, runs = 1", Directives: gti.Directives{}, Tag: "def:\"0\""}}, + {"NRuns", >i.Field{Name: "NRuns", Type: "int", LocalType: "int", Doc: "total number of runs to do when running Train", Directives: gti.Directives{}, Tag: "def:\"1\" min:\"1\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.LogConfig", + ShortName: "main.LogConfig", + IDName: "log-config", + Doc: "LogConfig has config parameters related to logging data", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"AggStats", >i.Field{Name: "AggStats", Type: "[]string", LocalType: "[]string", Doc: "] stats to aggregate at higher levels", Directives: gti.Directives{}, Tag: "def:\"['DA','VSPatch']\""}}, + {"SaveWts", >i.Field{Name: "SaveWts", Type: "bool", LocalType: "bool", Doc: "if true, save final weights after each run", Directives: gti.Directives{}, Tag: ""}}, + {"Block", >i.Field{Name: "Block", Type: "bool", LocalType: "bool", Doc: "if true, save block log to file, as .blk.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Cond", >i.Field{Name: "Cond", Type: "bool", LocalType: "bool", Doc: "if true, save condition log to file, as .cnd.tsv typically", Directives: gti.Directives{}, Tag: "def:\"true\" nest:\"+\""}}, + {"Trial", >i.Field{Name: "Trial", Type: "bool", LocalType: "bool", Doc: "if true, save trial log to file, as .trl.tsv typically", Directives: gti.Directives{}, Tag: "def:\"false\" nest:\"+\""}}, + {"NetData", >i.Field{Name: "NetData", Type: "bool", LocalType: "bool", Doc: "if true, save network activation etc data from testing trials, for later viewing in netview", Directives: gti.Directives{}, Tag: ""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Config", + ShortName: "main.Config", + IDName: "config", + Doc: "Config is a standard Sim config -- use as a starting point.", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Includes", >i.Field{Name: "Includes", Type: "[]string", LocalType: "[]string", Doc: "specify include files here, and after configuration, it contains list of include files added", Directives: gti.Directives{}, Tag: ""}}, + {"GUI", >i.Field{Name: "GUI", Type: "bool", LocalType: "bool", Doc: "open the GUI -- does not automatically run -- if false, then runs automatically and quits", Directives: gti.Directives{}, Tag: "def:\"true\""}}, + {"Debug", >i.Field{Name: "Debug", Type: "bool", LocalType: "bool", Doc: "log debugging information", Directives: gti.Directives{}, Tag: ""}}, + {"Env", >i.Field{Name: "Env", Type: "github.com/emer/axon/examples/pvlv.EnvConfig", LocalType: "EnvConfig", Doc: "environment configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/axon/examples/pvlv.ParamConfig", LocalType: "ParamConfig", Doc: "parameter related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Run", >i.Field{Name: "Run", Type: "github.com/emer/axon/examples/pvlv.RunConfig", LocalType: "RunConfig", Doc: "sim running related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + {"Log", >i.Field{Name: "Log", Type: "github.com/emer/axon/examples/pvlv.LogConfig", LocalType: "LogConfig", Doc: "data logging related configuration options", Directives: gti.Directives{}, Tag: "view:\"add-fields\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.DrEffPlot", + ShortName: "main.DrEffPlot", + IDName: "dr-eff-plot", + Doc: "DrEffPlot holds the params, table, etc", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "context just for plotting", Directives: gti.Directives{}, Tag: ""}}, + {"PVLV", >i.Field{Name: "PVLV", Type: "github.com/emer/axon/axon.PVLV", LocalType: "axon.PVLV", Doc: "PVLV params", Directives: gti.Directives{}, Tag: ""}}, + {"TimeSteps", >i.Field{Name: "TimeSteps", Type: "int", LocalType: "int", Doc: "total number of time steps to simulate", Directives: gti.Directives{}, Tag: ""}}, + {"USTime", >i.Field{Name: "USTime", Type: "goki.dev/etable/v2/minmax.Int", LocalType: "minmax.Int", Doc: "range for number of time steps between US receipt", Directives: gti.Directives{}, Tag: ""}}, + {"Effort", >i.Field{Name: "Effort", Type: "goki.dev/etable/v2/minmax.F32", LocalType: "minmax.F32", Doc: "range for random effort per step", Directives: gti.Directives{}, Tag: ""}}, + {"Table", >i.Field{Name: "Table", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "table for plot", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Plot", >i.Field{Name: "Plot", Type: "*goki.dev/etable/v2/eplot.Plot2D", LocalType: "*eplot.Plot2D", Doc: "the plot", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"TimeTable", >i.Field{Name: "TimeTable", Type: "*goki.dev/etable/v2/etable.Table", LocalType: "*etable.Table", Doc: "table for plot", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"TimePlot", >i.Field{Name: "TimePlot", Type: "*goki.dev/etable/v2/eplot.Plot2D", LocalType: "*eplot.Plot2D", Doc: "the plot", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"Rand", >i.Field{Name: "Rand", Type: "github.com/emer/emergent/v2/erand.SysRand", LocalType: "erand.SysRand", Doc: "random number generator", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{ + {"EffortPlot", >i.Method{Name: "EffortPlot", Doc: "EffortPlot plots the equation as a function of effort / time", Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, Args: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), Returns: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{})}}, + {"UrgencyPlot", >i.Method{Name: "UrgencyPlot", Doc: "UrgencyPlot plots the equation as a function of effort / time", Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, Args: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), Returns: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{})}}, + {"TimeRun", >i.Method{Name: "TimeRun", Doc: "TimeRun runs the equation over time.", Directives: gti.Directives{ + >i.Directive{Tool: "gti", Directive: "add", Args: []string{}}, + }, Args: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), Returns: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{})}}, + }), +}) + +var _ = gti.AddType(>i.Type{ + Name: "main.Sim", + ShortName: "main.Sim", + IDName: "sim", + Doc: "Sim encapsulates the entire simulation model, and we define all the\nfunctionality as methods on this struct. This structure keeps all relevant\nstate information organized and available without having to pass everything around\nas arguments to methods, and provides the core GUI interface (note the view tags\nfor the fields which provide hints to how things should be displayed).", + Directives: gti.Directives{}, + Fields: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{ + {"Config", >i.Field{Name: "Config", Type: "github.com/emer/axon/examples/pvlv.Config", LocalType: "Config", Doc: "simulation configuration parameters -- set by .toml config file and / or args", Directives: gti.Directives{}, Tag: ""}}, + {"Net", >i.Field{Name: "Net", Type: "*github.com/emer/axon/axon.Network", LocalType: "*axon.Network", Doc: "the network -- click to view / edit parameters for layers, prjns, etc", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Params", >i.Field{Name: "Params", Type: "github.com/emer/emergent/v2/emer.NetParams", LocalType: "emer.NetParams", Doc: "all parameter management", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"Loops", >i.Field{Name: "Loops", Type: "*github.com/emer/emergent/v2/looper.Manager", LocalType: "*looper.Manager", Doc: "contains looper control loops for running sim", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Stats", >i.Field{Name: "Stats", Type: "github.com/emer/emergent/v2/estats.Stats", LocalType: "estats.Stats", Doc: "contains computed statistic values", Directives: gti.Directives{}, Tag: ""}}, + {"Logs", >i.Field{Name: "Logs", Type: "github.com/emer/emergent/v2/elog.Logs", LocalType: "elog.Logs", Doc: "Contains all the logs and information about the logs.'", Directives: gti.Directives{}, Tag: ""}}, + {"Envs", >i.Field{Name: "Envs", Type: "github.com/emer/emergent/v2/env.Envs", LocalType: "env.Envs", Doc: "Environments", Directives: gti.Directives{}, Tag: "view:\"no-inline\""}}, + {"Context", >i.Field{Name: "Context", Type: "github.com/emer/axon/axon.Context", LocalType: "axon.Context", Doc: "axon timing parameters and state", Directives: gti.Directives{}, Tag: ""}}, + {"ViewUpdt", >i.Field{Name: "ViewUpdt", Type: "github.com/emer/emergent/v2/netview.ViewUpdt", LocalType: "netview.ViewUpdt", Doc: "netview update parameters", Directives: gti.Directives{}, Tag: "view:\"inline\""}}, + {"GUI", >i.Field{Name: "GUI", Type: "github.com/emer/emergent/v2/egui.GUI", LocalType: "egui.GUI", Doc: "manages all the gui elements", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + {"RndSeeds", >i.Field{Name: "RndSeeds", Type: "github.com/emer/emergent/v2/erand.Seeds", LocalType: "erand.Seeds", Doc: "a list of random seeds to use for each run", Directives: gti.Directives{}, Tag: "view:\"-\""}}, + }), + Embeds: ordmap.Make([]ordmap.KeyVal[string, *gti.Field]{}), + Methods: ordmap.Make([]ordmap.KeyVal[string, *gti.Method]{}), +}) diff --git a/examples/pvlv/pvlv.go b/examples/pvlv/pvlv.go index bb7a2e55f..9d4073d1a 100644 --- a/examples/pvlv/pvlv.go +++ b/examples/pvlv/pvlv.go @@ -8,6 +8,8 @@ in the amygdala, ventral striatum and associated areas. */ package main +//go:generate goki generate -add-types + import ( "fmt" "log" @@ -28,7 +30,6 @@ import ( "github.com/emer/emergent/v2/params" "github.com/emer/emergent/v2/prjn" "github.com/emer/empi/v2/mpi" - "github.com/goki/ki/ki" "github.com/goki/ki/kit" "goki.dev/etable/v2/agg" "goki.dev/etable/v2/eplot" @@ -38,6 +39,7 @@ import ( "goki.dev/etable/v2/split" "goki.dev/gi/v2/gi" "goki.dev/gi/v2/gimain" + "goki.dev/goosi/events" "goki.dev/mat32/v2" ) @@ -46,7 +48,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(sim.RunGUI) + gimain.Run(sim.RunGUI) } else { sim.RunNoGUI() } @@ -717,7 +719,7 @@ func (ss *Sim) BlockStats() { if ss.Config.GUI { plt := ss.GUI.Plots[etime.ScopeKey(stnm)] plt.SetTable(dt) - plt.Update() + plt.GoUpdatePlot() } } @@ -725,9 +727,9 @@ func (ss *Sim) BlockStats() { // Gui // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { +func (ss *Sim) ConfigGUI() { title := "Axon PVLV" - ss.GUI.MakeWindow(ss, "pvlv", title, `This is the PVLV test model in Axon. See emergent on GitHub.

`) + ss.GUI.MakeBody(ss, "pvlv", title, `This is the PVLV test model in Axon. See emergent on GitHub.

`) ss.GUI.CycleUpdateInterval = 10 nv := ss.GUI.AddNetView("NetView") @@ -746,85 +748,87 @@ func (ss *Sim) ConfigGUI() *gi.Window { stnm := "BlockByType" dt := ss.Logs.MiscTable(stnm) - plt := ss.GUI.TabView.AddNewTab(eplot.KiT_Plot2D, stnm+" Plot").(*eplot.Plot2D) + plt := eplot.NewPlot2D(ss.GUI.Tabs.NewTab(stnm + " Plot")) ss.GUI.Plots[etime.ScopeKey(stnm)] = plt plt.Params.Title = stnm plt.Params.XAxisCol = "TrialType" plt.SetTable(dt) - cb := gi.AddNewComboBox(ss.GUI.ToolBar, "runs") - cb.ItemsFromStringList(cond.RunNames, false, 50) - ri := 0 - for i, rn := range cond.RunNames { - if rn == ss.Config.Env.RunName { - ri = i - break + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + cb := gi.NewChooser(tb, "runs") + cb.SetStrings(cond.RunNames, false, 50) + ri := 0 + for i, rn := range cond.RunNames { + if rn == ss.Config.Env.RunName { + ri = i + break + } } - } - cb.SelectItem(ri) - cb.ComboSig.Connect(ss.GUI.Win.This(), func(recv, send ki.Ki, sig int64, data any) { - ss.Config.Env.RunName = data.(string) - ss.InitEnvRun() - }) + cb.SelectItem(ri) + cb.OnChange(func(e events.Event) { + ss.Config.Env.RunName = cb.CurVal.(string) + ss.InitEnvRun() + }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", - Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", - Active: egui.ActiveStopped, - Func: func() { - ss.Init() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddLooperCtrl(ss.Loops, []etime.Modes{etime.Train}) + ss.GUI.AddLooperCtrl(tb, ss.Loops, []etime.Modes{etime.Train}) - gi.NewSeparator(tb)"wts") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Save Wts", Icon: "file-save", - Tooltip: "Save weights for the current condition name.", - Active: egui.ActiveStopped, - Func: func() { - ss.SaveCondWeights() - // ss.GUI.UpdateWindow() - }, - }) + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Save Wts", Icon: "file-save", + Tooltip: "Save weights for the current condition name.", + Active: egui.ActiveStopped, + Func: func() { + ss.SaveCondWeights() + // ss.GUI.UpdateWindow() + }, + }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"log") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", - Icon: "reset", - Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", - Active: egui.ActiveAlways, - Func: func() { - ss.Logs.ResetLog(etime.Train, etime.Run) - ss.GUI.UpdatePlot(etime.Train, etime.Run) - }, - }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"misc") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", - Icon: "new", - Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", - Active: egui.ActiveAlways, - Func: func() { - ss.RndSeeds.NewSeeds() - }, - }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Plot Drive & Effort", - Icon: "play", - Tooltip: "Opens a new window to plot PVLV Drive and Effort dynamics.", - Active: egui.ActiveAlways, - Func: func() { - go DriveEffortGUI() - }, - }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", - Icon: "file-markdown", - Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", - Active: egui.ActiveAlways, - Func: func() { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/pvlv/README.md") - }, + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", + Icon: "reset", + Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", + Active: egui.ActiveAlways, + Func: func() { + ss.Logs.ResetLog(etime.Train, etime.Run) + ss.GUI.UpdatePlot(etime.Train, etime.Run) + }, + }) + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", + Icon: "new", + Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", + Active: egui.ActiveAlways, + Func: func() { + ss.RndSeeds.NewSeeds() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Plot Drive & Effort", + Icon: "play", + Tooltip: "Opens a new window to plot PVLV Drive and Effort dynamics.", + Active: egui.ActiveAlways, + Func: func() { + go DriveEffortGUI() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/pvlv/README.md") + }, + }) }) ss.GUI.FinalizeGUI(false) @@ -835,13 +839,12 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.Net.GPU.Destroy() }) } - return ss.GUI.Win } func (ss *Sim) RunGUI() { ss.Init() - win := ss.ConfigGUI() - win.StartEventLoop() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/ra25x/ra25x.go b/examples/ra25x/ra25x.go index ab89ce0ac..7eaeb4fdd 100644 --- a/examples/ra25x/ra25x.go +++ b/examples/ra25x/ra25x.go @@ -8,6 +8,8 @@ // defined over 5x5 input / output layers (i.e., 25 units) package main +//go:generate goki generate -add-types + import ( "log" "os" @@ -41,7 +43,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(sim.RunGUI) + gimain.Run(sim.RunGUI) } else { sim.RunNoGUI() } @@ -615,9 +617,9 @@ func (ss *Sim) Log(mode etime.Modes, time etime.Times) { // Gui // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { +func (ss *Sim) ConfigGUI() { title := "Axon Random Associator" - ss.GUI.MakeWindow(ss, "ra25x", title, `This demonstrates a basic Axon model. See emergent on GitHub.

`) + ss.GUI.MakeBody(ss, "ra25x", title, `This demonstrates a basic Axon model. See emergent on GitHub.

`) ss.GUI.CycleUpdateInterval = 10 nv := ss.GUI.AddNetView("NetView") @@ -631,45 +633,47 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.GUI.AddPlots(title, &ss.Logs) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", - Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", - Active: egui.ActiveStopped, - Func: func() { - ss.Init() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddLooperCtrl(ss.Loops, []etime.Modes{etime.Train, etime.Test}) - - //////////////////////////////////////////////// - gi.NewSeparator(tb)"log") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", - Icon: "reset", - Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", - Active: egui.ActiveAlways, - Func: func() { - ss.Logs.ResetLog(etime.Train, etime.Run) - ss.GUI.UpdatePlot(etime.Train, etime.Run) - }, - }) - //////////////////////////////////////////////// - gi.NewSeparator(tb)"misc") - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", - Icon: "new", - Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", - Active: egui.ActiveAlways, - Func: func() { - ss.RndSeeds.NewSeeds() - }, - }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", - Icon: "file-markdown", - Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", - Active: egui.ActiveAlways, - Func: func() { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/ra25x/README.md") - }, + ss.GUI.AddLooperCtrl(tb, ss.Loops, []etime.Modes{etime.Train, etime.Test}) + + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset RunLog", + Icon: "reset", + Tooltip: "Reset the accumulated log of all Runs, which are tagged with the ParamSet used", + Active: egui.ActiveAlways, + Func: func() { + ss.Logs.ResetLog(etime.Train, etime.Run) + ss.GUI.UpdatePlot(etime.Train, etime.Run) + }, + }) + //////////////////////////////////////////////// + gi.NewSeparator(tb) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "New Seed", + Icon: "new", + Tooltip: "Generate a new initial random seed to get different results. By default, Init re-establishes the same initial seed every time.", + Active: egui.ActiveAlways, + Func: func() { + ss.RndSeeds.NewSeeds() + }, + }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/ra25x/README.md") + }, + }) }) ss.GUI.FinalizeGUI(false) if ss.Config.Run.GPU { @@ -679,13 +683,12 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.Net.GPU.Destroy() }) } - return ss.GUI.Win } func (ss *Sim) RunGUI() { ss.Init() - win := ss.ConfigGUI() - win.StartEventLoop() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() { diff --git a/examples/rl/rl.go b/examples/rl/rl.go index 22341f4d1..18cecc462 100644 --- a/examples/rl/rl.go +++ b/examples/rl/rl.go @@ -7,6 +7,8 @@ rl_cond explores the temporal differences (TD) and Rescorla-Wagner reinforcement */ package main +//go:generate goki generate -add-types + import ( "os" @@ -34,7 +36,7 @@ func main() { sim.New() sim.ConfigAll() if sim.Config.GUI { - gimain.Main(sim.RunGUI) + gimain.Run(sim.RunGUI) } else { sim.RunNoGUI() } @@ -402,9 +404,9 @@ func (ss *Sim) Log(mode etime.Modes, time etime.Times) { // Gui // ConfigGUI configures the GoGi gui interface for this simulation, -func (ss *Sim) ConfigGUI() *gi.Window { +func (ss *Sim) ConfigGUI() { title := "Reinforcement Learning" - ss.GUI.MakeWindow(ss, "rl", title, `rl_cond explores the temporal differences (TD) reinforcement learning algorithm under some basic Pavlovian conditioning environments. See axon on GitHub.

`) + ss.GUI.MakeBody(ss, "rl", title, `rl_cond explores the temporal differences (TD) reinforcement learning algorithm under some basic Pavlovian conditioning environments. See axon on GitHub.

`) ss.GUI.CycleUpdateInterval = 10 nv := ss.GUI.AddNetView("NetView") @@ -418,32 +420,34 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.GUI.AddPlots(title, &ss.Logs) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", - Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", - Active: egui.ActiveStopped, - Func: func() { - ss.Init() - ss.GUI.UpdateWindow() - }, - }) + ss.GUI.Body.AddAppBar(func(tb *gi.Toolbar) { + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Init", Icon: "update", + Tooltip: "Initialize everything including network weights, and start over. Also applies current params.", + Active: egui.ActiveStopped, + Func: func() { + ss.Init() + ss.GUI.UpdateWindow() + }, + }) - ss.GUI.AddLooperCtrl(ss.Loops, []etime.Modes{etime.Train}) + ss.GUI.AddLooperCtrl(tb, ss.Loops, []etime.Modes{etime.Train}) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset Trial Log", Icon: "update", - Tooltip: "reset trial log .", - Func: func() { - ss.Logs.ResetLog(etime.Train, etime.Trial) - ss.GUI.UpdatePlot(etime.Train, etime.Trial) - }, - }) + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "Reset Trial Log", Icon: "update", + Tooltip: "reset trial log .", + Func: func() { + ss.Logs.ResetLog(etime.Train, etime.Trial) + ss.GUI.UpdatePlot(etime.Train, etime.Trial) + }, + }) - ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", - Icon: "file-markdown", - Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", - Active: egui.ActiveAlways, - Func: func() { - gi.OpenURL("https://github.com/emer/axon/blob/master/examples/rl/README.md") - }, + ss.GUI.AddToolbarItem(tb, egui.ToolbarItem{Label: "README", + Icon: "file-markdown", + Tooltip: "Opens your browser on the README file that contains instructions for how to run this model.", + Active: egui.ActiveAlways, + Func: func() { + gi.OpenURL("https://github.com/emer/axon/blob/master/examples/rl/README.md") + }, + }) }) ss.GUI.FinalizeGUI(false) if ss.Config.Run.GPU { @@ -452,13 +456,12 @@ func (ss *Sim) ConfigGUI() *gi.Window { ss.Net.GPU.Destroy() }) } - return ss.GUI.Win } func (ss *Sim) RunGUI() { ss.Init() - win := ss.ConfigGUI() - win.StartEventLoop() + ss.ConfigGUI() + ss.GUI.Body.NewWindow().Run().Wait() } func (ss *Sim) RunNoGUI() {