diff --git a/go.mod b/go.mod index 2ac83b2c429b939cf7aea7a747c6119eedc4c6c3..623f9bd558116dfbb39524b39343c65bc2a61535 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,6 @@ go 1.16 require ( github.com/gizak/termui/v3 v3.1.0 + github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d gonum.org/v1/plot v0.9.0 ) diff --git a/screenplot.go b/screenplot.go index aa61dc3c9e641c777e6e83953173d069711c94aa..358c5ae3bebe3a5dea34e58b018fd8aae74c262f 100644 --- a/screenplot.go +++ b/screenplot.go @@ -3,54 +3,87 @@ package main import ( - "fmt" "math" + ui "github.com/gizak/termui/v3" "github.com/gizak/termui/v3/widgets" + tb "github.com/nsf/termbox-go" ) -func breaker(x interface{}) {} -func copyToData (y []float32) ([][]float64){ +// render overrides the library function. It was not respecting +// background color, so I trashed it. +func render(items ...ui.Drawable) { + for _, item := range items { + buf := ui.NewBuffer(item.GetRect()) + item.Lock() + item.Draw(buf) + item.Unlock() + for point, cell := range buf.CellMap { + if point.In(buf.Rectangle) { + tb.SetCell( + point.X, point.Y, + cell.Rune, + tb.Attribute(tb.ColorWhite), tb.ColorBlack, + ) + } + } + } + tb.Flush() +} + +// copyToData puts the data in a slice of slices with crazy +// unnecessary double precision. +func copyToData(y []float32) [][]float64 { data := make([]float64, len(y)) for i := range y { data[i] = float64(y[i]) } - data[0] = data[1] return [][]float64{data} } - +// wipeFirst Takes the first n entries and sets them to the n+1'th +// so we effectively discard the first entries where the estimates are +// so bad. We do not have to return anything, since the slice is a +// reference structure anyway. +func wipeFirst(x []float64, n int) { + for i := 0; i < n; i++ { + x[i] = x[n] + } +} + +// scrnPlot puts the data in a retro-look plot. func scrnPlt(pi, stdErr []float32) error { - fmt.Println() + const toWipe = 12 marker := widgets.MarkerDot dotMarkerRune := '.' - p1 := widgets.NewPlot() - p1.Title = "π" - p1.Data = copyToData (pi) + p1.Title = " π " + p1.Data = copyToData(pi) + wipeFirst(p1.Data[0], toWipe) p1.Marker = marker p1.DotMarkerRune = dotMarkerRune - p1.PlotType = widgets.ScatterPlot - p1.Border = true p2 := widgets.NewPlot() + p2.PlotType = widgets.ScatterPlot p2.Title = "standard error" - p2.Data = copyToData (stdErr) + p2.Data = copyToData(stdErr) p2.DotMarkerRune = dotMarkerRune p2.Marker = marker + wipeFirst(p2.Data[0], toWipe) p3 := widgets.NewPlot() p3.Title = "abs error" { - d := make ([]float64, len(pi)) + d := make([]float64, len(pi)) for i, piV := range pi { - d[i] = math.Pi - float64(piV) + d[i] = math.Abs(math.Pi - float64(piV)) } p3.Data = [][]float64{d} + wipeFirst(p3.Data[0], toWipe) } - - + p3.DotMarkerRune = dotMarkerRune + p3.Marker = marker if err := ui.Init(); err != nil { return err @@ -59,8 +92,8 @@ func scrnPlt(pi, stdErr []float32) error { grid := ui.NewGrid() termWidth, termHeight := ui.TerminalDimensions() grid.SetRect(0, 0, termWidth, termHeight) - grid.Set (ui.NewRow(1./3, p1), ui.NewRow(1./3, p2), ui.NewRow(1./3, p3)) - + grid.Set(ui.NewRow(1./3, p1), ui.NewRow(1./3, p2), ui.NewRow(1./3, p3)) + render(grid) for e := range ui.PollEvents() { if e.Type == ui.KeyboardEvent { @@ -69,14 +102,3 @@ func scrnPlt(pi, stdErr []float32) error { } return nil } - -// This was how I wanted to do it, but the library does -// not seem to respect background colours. -// ui.Theme = thm -// nrmlStyle := ui.NewStyle (ui.ColorWhite, ui.ColorBlack) -// thm := ui.Theme -// thm.Block.Title = nrmlStyle -// thm.Plot.Axes = ui.ColorWhite -// thm.Plot.Lines = []ui.Color{ui.ColorWhite} -// thm.Default = ui.NewStyle(ui.ColorWhite, ui.ColorBlack) -// thm.Block.Border = nrmlStyle