1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
// Copyright ©2015 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gob_test
import (
"bytes"
"encoding/gob"
"image/color"
"os"
"testing"
"golang.org/x/exp/rand"
"gonum.org/v1/plot"
_ "gonum.org/v1/plot/gob"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"
)
func init() {
gob.Register(commaTicks{})
}
func TestPersistency(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
// Get some random points
n := 15
scatterData := randomPoints(n, rnd)
lineData := randomPoints(n, rnd)
linePointsData := randomPoints(n, rnd)
p, err := plot.New()
if err != nil {
t.Fatalf("error creating plot: %v\n", err)
}
p.Title.Text = "Plot Example"
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
// Use a custom tick marker function that computes the default
// tick marks and re-labels the major ticks with commas.
p.Y.Tick.Marker = commaTicks{}
// Draw a grid behind the data
p.Add(plotter.NewGrid())
// Make a scatter plotter and set its style.
s, err := plotter.NewScatter(scatterData)
if err != nil {
panic(err)
}
s.GlyphStyle.Color = color.RGBA{R: 255, B: 128, A: 255}
// Make a line plotter and set its style.
l, err := plotter.NewLine(lineData)
if err != nil {
panic(err)
}
l.LineStyle.Width = vg.Points(1)
l.LineStyle.Dashes = []vg.Length{vg.Points(5), vg.Points(5)}
l.LineStyle.Color = color.RGBA{B: 255, A: 255}
// Make a line plotter with points and set its style.
lpLine, lpPoints, err := plotter.NewLinePoints(linePointsData)
if err != nil {
panic(err)
}
lpLine.Color = color.RGBA{G: 255, A: 255}
lpPoints.Shape = draw.PyramidGlyph{}
lpPoints.Color = color.RGBA{R: 255, A: 255}
// Add the plotters to the plot, with a legend
// entry for each
p.Add(s, l, lpLine, lpPoints)
p.Legend.Add("scatter", s)
p.Legend.Add("line", l)
p.Legend.Add("line points", lpLine, lpPoints)
// Save the plot to a PNG file.
err = p.Save(4, 4, "test-persistency.png")
if err != nil {
t.Fatalf("error saving to PNG: %v\n", err)
}
defer os.Remove("test-persistency.png")
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
err = enc.Encode(p)
if err != nil {
t.Fatalf("error gob-encoding plot: %v\n", err)
}
// TODO(sbinet): impl. BinaryMarshal for plot.Plot and vg.Font
// {
// dec := gob.NewDecoder(buf)
// var p plot.Plot
// err = dec.Decode(&p)
// if err != nil {
// t.Fatalf("error gob-decoding plot: %v\n", err)
// }
// // Save the plot to a PNG file.
// err = p.Save(4, 4, "test-persistency-readback.png")
// if err != nil {
// t.Fatalf("error saving to PNG: %v\n", err)
// }
// defer os.Remove("test-persistency-readback.png")
// }
}
// randomPoints returns some random x, y points.
func randomPoints(n int, rnd *rand.Rand) plotter.XYs {
pts := make(plotter.XYs, n)
for i := range pts {
if i == 0 {
pts[i].X = rnd.Float64()
} else {
pts[i].X = pts[i-1].X + rnd.Float64()
}
pts[i].Y = pts[i].X + rnd.Float64()*1e4
}
return pts
}
// CommaTicks computes the default tick marks, but inserts commas
// into the labels for the major tick marks.
type commaTicks struct{}
func (commaTicks) Ticks(min, max float64) []plot.Tick {
tks := plot.DefaultTicks{}.Ticks(min, max)
for i, t := range tks {
if t.Label == "" { // Skip minor ticks, they are fine.
continue
}
tks[i].Label = addCommas(t.Label)
}
return tks
}
// AddCommas adds commas after every 3 characters from right to left.
// NOTE: This function is a quick hack, it doesn't work with decimal
// points, and may have a bunch of other problems.
func addCommas(s string) string {
rev := ""
n := 0
for i := len(s) - 1; i >= 0; i-- {
rev += string(s[i])
n++
if n%3 == 0 {
rev += ","
}
}
s = ""
for i := len(rev) - 1; i >= 0; i-- {
s += string(rev[i])
}
return s
}
|