diff --git a/lab/filetree.go b/lab/filetree.go index 7d24cd0f..e6f65e3d 100644 --- a/lab/filetree.go +++ b/lab/filetree.go @@ -242,7 +242,7 @@ func (fn *FileNode) PlotFiles() { //types:add }) } -// PlotFile pulls up this file in a texteditor. +// PlotFile creates a plot of data. func (fn *FileNode) PlotFile() { ts := fn.Tabber() if ts == nil { @@ -267,6 +267,30 @@ func (fn *FileNode) PlotFile() { ts.AsLab().PlotTable(ptab, dt) } +// todo: this is too redundant -- need a better soln + +// GridFiles calls GridFile on selected files +func (fn *FileNode) GridFiles() { //types:add + fn.SelectedFunc(func(sn *filetree.Node) { + if sfn, ok := sn.This.(*FileNode); ok { + sfn.GridFile() + } + }) +} + +// GridFile creates a grid view of data. +func (fn *FileNode) GridFile() { + ts := fn.Tabber() + if ts == nil { + return + } + d := TensorFS(fn.AsNode()) + if d != nil { + ts.AsLab().GridTensorFS(d) + return + } +} + // DiffDirs displays a browser with differences between two selected directories func (fn *FileNode) DiffDirs() { //types:add var da, db *filetree.Node @@ -315,6 +339,10 @@ func (fn *FileNode) ContextMenu(m *core.Scene) { Styler(func(s *styles.Style) { s.SetState(!fn.HasSelection() || fn.Info.Cat != fileinfo.Data, states.Disabled) }) + core.NewFuncButton(m).SetFunc(fn.GridFiles).SetText("Grid").SetIcon(icons.Edit). + Styler(func(s *styles.Style) { + s.SetState(!fn.HasSelection() || fn.Info.Cat != fileinfo.Data, states.Disabled) + }) core.NewFuncButton(m).SetFunc(fn.DiffDirs).SetText("Diff Dirs").SetIcon(icons.Edit). Styler(func(s *styles.Style) { s.SetState(!fn.HasSelection() || !fn.IsDir(), states.Disabled) diff --git a/lab/tabs.go b/lab/tabs.go index 9e28534d..1326b7ee 100644 --- a/lab/tabs.go +++ b/lab/tabs.go @@ -133,6 +133,17 @@ func (ts *Tabs) TensorGrid(label string, tsr tensor.Tensor) *tensorcore.TensorGr return tv } +// GridTensorFS recycles a tab with a Grid of given [tensorfs.Node]. +func (ts *Tabs) GridTensorFS(dfs *tensorfs.Node) *tensorcore.TensorGrid { + label := fsx.DirAndFile(dfs.Path()) + " Grid" + if dfs.IsDir() { + core.MessageSnackbar(ts, "Use Edit instead of Grid to view a directory") + return nil + } + tsr := dfs.Tensor + return ts.TensorGrid(label, tsr) +} + // PlotTable recycles a tab with a Plot of given table.Table. func (ts *Tabs) PlotTable(label string, dt *table.Table) *plotcore.PlotEditor { pl := NewTab(ts, label, func(tab *core.Frame) *plotcore.PlotEditor { diff --git a/lab/typegen.go b/lab/typegen.go index 603d1eea..dd79f4a6 100644 --- a/lab/typegen.go +++ b/lab/typegen.go @@ -63,7 +63,7 @@ func NewDataTree(parent ...tree.Node) *DataTree { return tree.New[DataTree](pare // Tabber is the [Tabber] for this tree. func (t *DataTree) SetTabber(v Tabber) *DataTree { t.Tabber = v; return t } -var _ = types.AddType(&types.Type{Name: "cogentcore.org/lab/lab.FileNode", IDName: "file-node", Doc: "FileNode is databrowser version of FileNode for FileTree", Methods: []types.Method{{Name: "EditFiles", Doc: "EditFiles calls EditFile on selected files", Directives: []types.Directive{{Tool: "types", Directive: "add"}}}, {Name: "PlotFiles", Doc: "PlotFiles calls PlotFile on selected files", Directives: []types.Directive{{Tool: "types", Directive: "add"}}}, {Name: "DiffDirs", Doc: "DiffDirs displays a browser with differences between two selected directories", Directives: []types.Directive{{Tool: "types", Directive: "add"}}}}, Embeds: []types.Field{{Name: "Node"}}}) +var _ = types.AddType(&types.Type{Name: "cogentcore.org/lab/lab.FileNode", IDName: "file-node", Doc: "FileNode is databrowser version of FileNode for FileTree", Methods: []types.Method{{Name: "EditFiles", Doc: "EditFiles calls EditFile on selected files", Directives: []types.Directive{{Tool: "types", Directive: "add"}}}, {Name: "PlotFiles", Doc: "PlotFiles calls PlotFile on selected files", Directives: []types.Directive{{Tool: "types", Directive: "add"}}}, {Name: "GridFiles", Doc: "GridFiles calls GridFile on selected files", Directives: []types.Directive{{Tool: "types", Directive: "add"}}}, {Name: "DiffDirs", Doc: "DiffDirs displays a browser with differences between two selected directories", Directives: []types.Directive{{Tool: "types", Directive: "add"}}}}, Embeds: []types.Field{{Name: "Node"}}}) // NewFileNode returns a new [FileNode] with the given optional parent: // FileNode is databrowser version of FileNode for FileTree diff --git a/patterns/patterns_test.go b/patterns/patterns_test.go index a8e6d9d3..55e3e111 100644 --- a/patterns/patterns_test.go +++ b/patterns/patterns_test.go @@ -272,3 +272,16 @@ func TestABAC(t *testing.T) { // fmt.Println(mix) assert.Equal(t, exmix, mix.String()) } + +func TestNameRows(t *testing.T) { + dir, _ := tensorfs.NewDir("test") + nr := dir.StringValue("Name", 12) + NameRows(nr, "AB_", 2) + // fmt.Println(nr) + + exnm := `Name [12] AB_00 AB_01 AB_02 AB_03 AB_04 AB_05 AB_06 AB_07 AB_08 AB_09 AB_10 + AB_11 +` + + assert.Equal(t, exnm, nr.String()) +} diff --git a/patterns/permuted.go b/patterns/permuted.go index 5779954b..eb1469ae 100644 --- a/patterns/permuted.go +++ b/patterns/permuted.go @@ -106,7 +106,7 @@ func PermutedBinaryMinDiff(tsr tensor.Values, nOn int, onVal, offVal float64, mi r1v := tsr.SubSpace(r1) for r2 := r1 + 1; r2 < rows; r2++ { r2v := tsr.SubSpace(r2) - dst := metric.Hamming(r1v, r2v).Float1D(0) + dst := metric.Hamming(tensor.As1D(r1v), tensor.As1D(r2v)).Float1D(0) df := int(math.Round(float64(.5 * dst))) if df < minDiff { nunder[r1]++ diff --git a/patterns/rows.go b/patterns/rows.go index c582824c..b9fef24d 100644 --- a/patterns/rows.go +++ b/patterns/rows.go @@ -29,6 +29,16 @@ func PctActInTensor(trow tensor.Values) float32 { // Note: AppendFrom can be used to concatenate tensors. +// NameRows sets strings as prefix + row number with given number +// of leading zeros. +func NameRows(tsr tensor.Values, prefix string, nzeros int) { + ft := fmt.Sprintf("%s%%0%dd", prefix, nzeros) + rows := tsr.DimSize(0) + for i := range rows { + tsr.SetString1D(fmt.Sprintf(ft, i), i) + } +} + // Shuffle returns a [tensor.Rows] view of the given source tensor // with the outer row-wise dimension randomly shuffled (permuted). func Shuffle(src tensor.Values) *tensor.Rows { diff --git a/tensor/bool.go b/tensor/bool.go index 002439c9..d078232f 100644 --- a/tensor/bool.go +++ b/tensor/bool.go @@ -9,6 +9,7 @@ import ( "reflect" "slices" + "cogentcore.org/core/base/errors" "cogentcore.org/core/base/metadata" "cogentcore.org/core/base/num" "cogentcore.org/core/base/reflectx" @@ -306,23 +307,24 @@ func (tsr *Bool) CopyFrom(frm Values) { // It uses and optimized implementation if the other tensor // is of the same type, and otherwise it goes through // appropriate standard type. -func (tsr *Bool) AppendFrom(frm Values) error { +func (tsr *Bool) AppendFrom(frm Values) Values { rows, cell := tsr.shape.RowCellSize() frows, fcell := frm.Shape().RowCellSize() if cell != fcell { - return fmt.Errorf("tensor.AppendFrom: cell sizes do not match: %d != %d", cell, fcell) + errors.Log(fmt.Errorf("tensor.AppendFrom: cell sizes do not match: %d != %d", cell, fcell)) + return tsr } tsr.SetNumRows(rows + frows) st := rows * cell fsz := frows * fcell if fsm, ok := frm.(*Bool); ok { copy(tsr.Values[st:st+fsz], fsm.Values) - return nil + return tsr } for i := 0; i < fsz; i++ { tsr.Values.Set(Float64ToBool(frm.Float1D(i)), st+i) } - return nil + return tsr } // CopyCellsFrom copies given range of values from other tensor into this tensor, diff --git a/tensor/number.go b/tensor/number.go index 76455166..9201e544 100644 --- a/tensor/number.go +++ b/tensor/number.go @@ -8,6 +8,7 @@ import ( "fmt" "strconv" + "cogentcore.org/core/base/errors" "cogentcore.org/core/base/num" "cogentcore.org/core/base/reflectx" ) @@ -281,23 +282,24 @@ func (tsr *Number[T]) CopyFrom(frm Values) { // It uses and optimized implementation if the other tensor // is of the same type, and otherwise it goes through // appropriate standard type. -func (tsr *Number[T]) AppendFrom(frm Values) error { +func (tsr *Number[T]) AppendFrom(frm Values) Values { rows, cell := tsr.shape.RowCellSize() frows, fcell := frm.Shape().RowCellSize() if cell != fcell { - return fmt.Errorf("tensor.AppendFrom: cell sizes do not match: %d != %d", cell, fcell) + errors.Log(fmt.Errorf("tensor.AppendFrom: cell sizes do not match: %d != %d", cell, fcell)) + return tsr } tsr.SetNumRows(rows + frows) st := rows * cell fsz := frows * fcell if fsm, ok := frm.(*Number[T]); ok { copy(tsr.Values[st:st+fsz], fsm.Values) - return nil + return tsr } for i := 0; i < fsz; i++ { tsr.Values[st+i] = T(frm.Float1D(i)) } - return nil + return tsr } // CopyCellsFrom copies given range of values from other tensor into this tensor, diff --git a/tensor/string.go b/tensor/string.go index 6d20cd56..b9741dfb 100644 --- a/tensor/string.go +++ b/tensor/string.go @@ -214,23 +214,24 @@ func (tsr *String) CopyFrom(frm Values) { // It uses and optimized implementation if the other tensor // is of the same type, and otherwise it goes through // appropriate standard type. -func (tsr *String) AppendFrom(frm Values) error { +func (tsr *String) AppendFrom(frm Values) Values { rows, cell := tsr.shape.RowCellSize() frows, fcell := frm.Shape().RowCellSize() if cell != fcell { - return fmt.Errorf("tensor.AppendFrom: cell sizes do not match: %d != %d", cell, fcell) + errors.Log(fmt.Errorf("tensor.AppendFrom: cell sizes do not match: %d != %d", cell, fcell)) + return tsr } tsr.SetNumRows(rows + frows) st := rows * cell fsz := frows * fcell if fsm, ok := frm.(*String); ok { copy(tsr.Values[st:st+fsz], fsm.Values) - return nil + return tsr } for i := 0; i < fsz; i++ { tsr.Values[st+i] = Float64ToString(frm.Float1D(i)) } - return nil + return tsr } // CopyCellsFrom copies given range of values from other tensor into this tensor, diff --git a/tensor/values.go b/tensor/values.go index 38fe07ba..79e9737c 100644 --- a/tensor/values.go +++ b/tensor/values.go @@ -60,7 +60,7 @@ type Values interface { // AppendFrom appends all values from other tensor into this tensor, with an // optimized implementation if the other tensor is of the same type, and // otherwise it goes through the appropriate standard type (Float, Int, String). - AppendFrom(from Values) error + AppendFrom(from Values) Values } // New returns a new n-dimensional tensor of given value type diff --git a/yaegilab/gui/cogentcore_org-lab-lab.go b/yaegilab/gui/cogentcore_org-lab-lab.go index 34d05559..4a072561 100644 --- a/yaegilab/gui/cogentcore_org-lab-lab.go +++ b/yaegilab/gui/cogentcore_org-lab-lab.go @@ -4,13 +4,7 @@ package gui import ( "cogentcore.org/core/core" - "cogentcore.org/core/texteditor" "cogentcore.org/lab/lab" - "cogentcore.org/lab/plotcore" - "cogentcore.org/lab/table" - "cogentcore.org/lab/tensor" - "cogentcore.org/lab/tensorcore" - "cogentcore.org/lab/tensorfs" "reflect" ) @@ -51,69 +45,13 @@ func init() { // _cogentcore_org_lab_lab_Tabber is an interface wrapper for Tabber type type _cogentcore_org_lab_lab_Tabber struct { - IValue interface{} - WAsCoreTabs func() *core.Tabs - WAsDataTabs func() *lab.Tabs - WCurrentTab func() (core.Widget, int) - WEditorFile func(label string, filename string) *texteditor.Editor - WEditorString func(label string, content string) *texteditor.Editor - WGoUpdatePlot func(label string) *plotcore.PlotEditor - WPlotTable func(label string, dt *table.Table) *plotcore.PlotEditor - WPlotTensorFS func(dfs *tensorfs.Node) *plotcore.PlotEditor - WRecycleTab func(name string) *core.Frame - WSelectTabByName func(name string) *core.Frame - WSelectTabIndex func(idx int) *core.Frame - WSliceTable func(label string, slc any) *core.Table - WTabByName func(name string) *core.Frame - WTensorEditor func(label string, tsr tensor.Tensor) *tensorcore.TensorEditor - WTensorGrid func(label string, tsr tensor.Tensor) *tensorcore.TensorGrid - WTensorTable func(label string, dt *table.Table) *tensorcore.Table - WUpdatePlot func(label string) *plotcore.PlotEditor + IValue interface{} + WAsCoreTabs func() *core.Tabs + WAsLab func() *lab.Tabs } -func (W _cogentcore_org_lab_lab_Tabber) AsCoreTabs() *core.Tabs { return W.WAsCoreTabs() } -func (W _cogentcore_org_lab_lab_Tabber) AsDataTabs() *lab.Tabs { return W.WAsDataTabs() } -func (W _cogentcore_org_lab_lab_Tabber) CurrentTab() (core.Widget, int) { return W.WCurrentTab() } -func (W _cogentcore_org_lab_lab_Tabber) EditorFile(label string, filename string) *texteditor.Editor { - return W.WEditorFile(label, filename) -} -func (W _cogentcore_org_lab_lab_Tabber) EditorString(label string, content string) *texteditor.Editor { - return W.WEditorString(label, content) -} -func (W _cogentcore_org_lab_lab_Tabber) GoUpdatePlot(label string) *plotcore.PlotEditor { - return W.WGoUpdatePlot(label) -} -func (W _cogentcore_org_lab_lab_Tabber) PlotTable(label string, dt *table.Table) *plotcore.PlotEditor { - return W.WPlotTable(label, dt) -} -func (W _cogentcore_org_lab_lab_Tabber) PlotTensorFS(dfs *tensorfs.Node) *plotcore.PlotEditor { - return W.WPlotTensorFS(dfs) -} -func (W _cogentcore_org_lab_lab_Tabber) RecycleTab(name string) *core.Frame { - return W.WRecycleTab(name) -} -func (W _cogentcore_org_lab_lab_Tabber) SelectTabByName(name string) *core.Frame { - return W.WSelectTabByName(name) -} -func (W _cogentcore_org_lab_lab_Tabber) SelectTabIndex(idx int) *core.Frame { - return W.WSelectTabIndex(idx) -} -func (W _cogentcore_org_lab_lab_Tabber) SliceTable(label string, slc any) *core.Table { - return W.WSliceTable(label, slc) -} -func (W _cogentcore_org_lab_lab_Tabber) TabByName(name string) *core.Frame { return W.WTabByName(name) } -func (W _cogentcore_org_lab_lab_Tabber) TensorEditor(label string, tsr tensor.Tensor) *tensorcore.TensorEditor { - return W.WTensorEditor(label, tsr) -} -func (W _cogentcore_org_lab_lab_Tabber) TensorGrid(label string, tsr tensor.Tensor) *tensorcore.TensorGrid { - return W.WTensorGrid(label, tsr) -} -func (W _cogentcore_org_lab_lab_Tabber) TensorTable(label string, dt *table.Table) *tensorcore.Table { - return W.WTensorTable(label, dt) -} -func (W _cogentcore_org_lab_lab_Tabber) UpdatePlot(label string) *plotcore.PlotEditor { - return W.WUpdatePlot(label) -} +func (W _cogentcore_org_lab_lab_Tabber) AsCoreTabs() *core.Tabs { return W.WAsCoreTabs() } +func (W _cogentcore_org_lab_lab_Tabber) AsLab() *lab.Tabs { return W.WAsLab() } // _cogentcore_org_lab_lab_Treer is an interface wrapper for Treer type type _cogentcore_org_lab_lab_Treer struct { diff --git a/yaegilab/nogui/cogentcore_org-lab-tensor.go b/yaegilab/nogui/cogentcore_org-lab-tensor.go index b2480b19..e24e2e59 100644 --- a/yaegilab/nogui/cogentcore_org-lab-tensor.go +++ b/yaegilab/nogui/cogentcore_org-lab-tensor.go @@ -361,7 +361,7 @@ func (W _cogentcore_org_lab_tensor_Tensor) StringValue(i ...int) string { return // _cogentcore_org_lab_tensor_Values is an interface wrapper for Values type type _cogentcore_org_lab_tensor_Values struct { IValue interface{} - WAppendFrom func(from tensor.Values) error + WAppendFrom func(from tensor.Values) tensor.Values WAppendRow func(val tensor.Values) WAppendRowFloat func(val ...float64) WAppendRowInt func(val ...int) @@ -408,7 +408,7 @@ type _cogentcore_org_lab_tensor_Values struct { WSubSpace func(offs ...int) tensor.Values } -func (W _cogentcore_org_lab_tensor_Values) AppendFrom(from tensor.Values) error { +func (W _cogentcore_org_lab_tensor_Values) AppendFrom(from tensor.Values) tensor.Values { return W.WAppendFrom(from) } func (W _cogentcore_org_lab_tensor_Values) AppendRow(val tensor.Values) { W.WAppendRow(val) } diff --git a/yaegilab/nogui/cogentcore_org-lab-tensorfs.go b/yaegilab/nogui/cogentcore_org-lab-tensorfs.go index eff9fe66..5079629d 100644 --- a/yaegilab/nogui/cogentcore_org-lab-tensorfs.go +++ b/yaegilab/nogui/cogentcore_org-lab-tensorfs.go @@ -21,12 +21,12 @@ func init() { "Long": reflect.ValueOf(tensorfs.Long), "Mkdir": reflect.ValueOf(tensorfs.Mkdir), "NewDir": reflect.ValueOf(tensorfs.NewDir), - "NewForTensor": reflect.ValueOf(tensorfs.NewForTensor), "Overwrite": reflect.ValueOf(tensorfs.Overwrite), "Preserve": reflect.ValueOf(tensorfs.Preserve), "Record": reflect.ValueOf(tensorfs.Record), "Recursive": reflect.ValueOf(tensorfs.Recursive), "Set": reflect.ValueOf(tensorfs.Set), + "SetTensor": reflect.ValueOf(tensorfs.SetTensor), "Short": reflect.ValueOf(tensorfs.Short), "ValueType": reflect.ValueOf(tensorfs.ValueType),