Skip to content

Commit

Permalink
line plot updates on draws, remove field UpdateInterval, fix docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mlange-42 committed Apr 16, 2023
1 parent 645864d commit ba170ac
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 26 deletions.
49 changes: 26 additions & 23 deletions plot/lines.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,21 @@ import (
)

// Lines plot drawer.
//
// Creates a line series per column of the observer.
// Replaces the complete data by the table provided by the observer on every update.
// Particularly useful for live histograms.
type Lines struct {
Observer observer.Table // Observer providing a data series as lines.
X string // X column name. Optional. Defaults to row index.
Y []string // Y column names. Optional. Defaults to all but X column.
UpdateInterval int // Interval for updating the observer, in model ticks. Optional.
Observer observer.Table // Observer providing a data series as lines.
X string // X column name. Optional. Defaults to row index.
Y []string // Y column names. Optional. Defaults to all but X column.

xIndex int
yIndices []int

headers []string
series []plotter.XYs
scale float64
step int64
}

// Initialize the drawer.
Expand All @@ -38,7 +40,6 @@ func (l *Lines) Initialize(w *ecs.World, win *pixelgl.Window) {
l.headers = l.Observer.Header()

l.scale = calcScaleCorrection()
l.step = 0

if l.X == "" {
l.xIndex = -1
Expand Down Expand Up @@ -85,30 +86,15 @@ func (l *Lines) Initialize(w *ecs.World, win *pixelgl.Window) {
// Update the drawer.
func (l *Lines) Update(w *ecs.World) {
l.Observer.Update(w)
if l.UpdateInterval <= 1 || l.step%int64(l.UpdateInterval) == 0 {
data := l.Observer.Values(w)
xi := l.xIndex
yis := l.yIndices

for i, idx := range yis {
l.series[i] = l.series[i][:0]
for j, row := range data {
x := float64(j)
if xi >= 0 {
x = row[xi]
}
l.series[i] = append(l.series[i], plotter.XY{X: x, Y: row[idx]})
}
}
}
l.step++
}

// UpdateInputs handles input events of the previous frame update.
func (l *Lines) UpdateInputs(w *ecs.World, win *pixelgl.Window) {}

// Draw the drawer.
func (l *Lines) Draw(w *ecs.World, win *pixelgl.Window) {
l.updateData(w)

width := win.Canvas().Bounds().W()
height := win.Canvas().Bounds().H()

Expand Down Expand Up @@ -140,3 +126,20 @@ func (l *Lines) Draw(w *ecs.World, win *pixelgl.Window) {
sprite := pixel.NewSprite(picture, picture.Bounds())
sprite.Draw(win, pixel.IM.Moved(pixel.V(picture.Rect.W()/2.0+5, picture.Rect.H()/2.0+5)))
}

func (l *Lines) updateData(w *ecs.World) {
data := l.Observer.Values(w)
xi := l.xIndex
yis := l.yIndices

for i, idx := range yis {
l.series[i] = l.series[i][:0]
for j, row := range data {
x := float64(j)
if xi >= 0 {
x = row[xi]
}
l.series[i] = append(l.series[i], plotter.XY{X: x, Y: row[idx]})
}
}
}
4 changes: 2 additions & 2 deletions plot/lines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func ExampleLines() {
m.AddUISystem((&window.Window{}).
With(&plot.Lines{
Observer: &TableObserver{},
X: "X",
Y: []string{"A", "B", "C"},
X: "X", // Optional, defaults to row index
Y: []string{"A", "B", "C"}, // Optional, defaults to all but X
}))

// Add a termination system that ends the simulation.
Expand Down
5 changes: 4 additions & 1 deletion plot/time_series.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ import (
)

// TimeSeries plot drawer.
//
// Creates a line series per column of the observer.
// Adds one row to the data per update.
type TimeSeries struct {
Observer observer.Row // Observer providing a data row per update.
UpdateInterval int // Interval for updating the observer, in model ticks. Optional.
UpdateInterval int // Interval for getting data from the the observer, in model ticks. Optional.

headers []string
series []plotter.XYs
Expand Down

0 comments on commit ba170ac

Please sign in to comment.