...

Source file src/gonum.org/v1/plot/gob/gob_test.go

Documentation: gonum.org/v1/plot/gob

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

View as plain text