// Example_groupedHorizontalBoxPlots draws vertical boxplots. func Example_groupedHorizontalBoxPlots() *plot.Plot { rand.Seed(int64(0)) n := 100 uniform := make(plotter.Values, n) normal := make(plotter.Values, n) expon := make(plotter.Values, n) for i := 0; i < n; i++ { uniform[i] = rand.Float64() normal[i] = rand.NormFloat64() expon[i] = rand.ExpFloat64() } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Box Plot" p.Y.Label.Text = "plotter.Values" w := vg.Points(20) for y := 0.0; y < 3.0; y++ { b0 := must(plotter.MakeHorizBoxPlot(w, y, uniform)).(plotter.HorizBoxPlot) b0.Offset = -w - vg.Points(3) b1 := must(plotter.MakeHorizBoxPlot(w, y, normal)).(plotter.HorizBoxPlot) b2 := must(plotter.MakeHorizBoxPlot(w, y, expon)).(plotter.HorizBoxPlot) b2.Offset = w + vg.Points(3) p.Add(b0, b1, b2) } p.NominalY("Group 0", "Group 1", "Group 2") return p }
// Example_boxPlots draws vertical boxplots. func Example_boxPlots() *plot.Plot { rand.Seed(int64(0)) n := 100 uniform := make(plotter.Values, n) normal := make(plotter.Values, n) expon := make(plotter.Values, n) for i := 0; i < n; i++ { uniform[i] = rand.Float64() normal[i] = rand.NormFloat64() expon[i] = rand.ExpFloat64() } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Box Plot" p.Y.Label.Text = "plotter.Values" // Make boxes for our data and add them to the plot. p.Add(must(plotter.NewBoxPlot(vg.Points(20), 0, uniform)).(*plotter.BoxPlot), must(plotter.NewBoxPlot(vg.Points(20), 1, normal)).(*plotter.BoxPlot), must(plotter.NewBoxPlot(vg.Points(20), 2, expon)).(*plotter.BoxPlot)) // Set the X axis of the plot to nominal with // the given names for x=0, x=1 and x=2. p.NominalX("Uniform\nDistribution", "Normal\nDistribution", "Exponential\nDistribution") return p }
// Example_groupedBoxPlots draws vertical boxplots. func Example_groupedBoxPlots() *plot.Plot { rand.Seed(int64(0)) n := 100 uniform := make(plotter.Values, n) normal := make(plotter.Values, n) expon := make(plotter.Values, n) for i := 0; i < n; i++ { uniform[i] = rand.Float64() normal[i] = rand.NormFloat64() expon[i] = rand.ExpFloat64() } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Box Plot" p.Y.Label.Text = "plotter.Values" w := vg.Points(20) for x := 0.0; x < 3.0; x++ { b0 := must(plotter.NewBoxPlot(w, x, uniform)).(*plotter.BoxPlot) b0.Offset = -w - vg.Points(3) b1 := must(plotter.NewBoxPlot(w, x, normal)).(*plotter.BoxPlot) b2 := must(plotter.NewBoxPlot(w, x, expon)).(*plotter.BoxPlot) b2.Offset = w + vg.Points(3) p.Add(b0, b1, b2) } // Set the X axis of the plot to nominal with // the given names for x=0, x=1 and x=2. p.NominalX("Group 0", "Group 1", "Group 2") return p }
// Draw the plotinum logo. func Example_logo() *plot.Plot { p, err := plot.New() if err != nil { panic(err) } plotter.DefaultLineStyle.Width = vg.Points(1) plotter.DefaultGlyphStyle.Radius = vg.Points(3) p.Y.Tick.Marker = plot.ConstantTicks([]plot.Tick{ {0, "0"}, {0.25, ""}, {0.5, "0.5"}, {0.75, ""}, {1, "1"}, }) p.X.Tick.Marker = plot.ConstantTicks([]plot.Tick{ {0, "0"}, {0.25, ""}, {0.5, "0.5"}, {0.75, ""}, {1, "1"}, }) pts := plotter.XYs{{0, 0}, {0, 1}, {0.5, 1}, {0.5, 0.6}, {0, 0.6}} line := must(plotter.NewLine(pts)).(*plotter.Line) scatter := must(plotter.NewScatter(pts)).(*plotter.Scatter) p.Add(line, scatter) pts = plotter.XYs{{1, 0}, {0.75, 0}, {0.75, 0.75}} line = must(plotter.NewLine(pts)).(*plotter.Line) scatter = must(plotter.NewScatter(pts)).(*plotter.Scatter) p.Add(line, scatter) pts = plotter.XYs{{0.5, 0.5}, {1, 0.5}} line = must(plotter.NewLine(pts)).(*plotter.Line) scatter = must(plotter.NewScatter(pts)).(*plotter.Scatter) p.Add(line, scatter) return p }
// Plot plots only 2-dimensional cluster and points func (em EM) Plot(fileid int, directory string) { p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "EM-Algorithm Plot" p.X.Label.Text = "X" p.Y.Label.Text = "Y" bs, err := plotter.NewBubbles(em.clusterTriples(), vg.Points(30), vg.Points(80)) if err != nil { panic(err) } bs.Color = color.RGBA{R: 255, B: 255, A: 255} p.Add(bs) ss, err := plotter.NewScatter(em.dataTriples()) if err != nil { panic(err) } ss.Color = color.Black p.Add(ss) filename := directory + fmt.Sprintf("%03d", fileid) + ".png" if err := p.Save(10*vg.Inch, 10*vg.Inch, filename); err != nil { panic(err) } }
// NewBoxPlot returns a new BoxPlot that represents // the distribution of the given values. The style of // the box plot is that used for Tukey's schematic // plots is ``Exploratory Data Analysis.'' // // An error is returned if the boxplot is created with // no values. // // The fence values are 1.5x the interquartile before // the first quartile and after the third quartile. Any // value that is outside of the fences are drawn as // Outside points. The adjacent values (to which the // whiskers stretch) are the minimum and maximum // values that are not outside the fences. func NewBoxPlot(w vg.Length, loc float64, values Valuer) (*BoxPlot, error) { if w < 0 { return nil, errors.New("Negative boxplot width") } b := new(BoxPlot) var err error if b.fiveStatPlot, err = newFiveStat(w, loc, values); err != nil { return nil, err } b.Width = w b.CapWidth = 3 * w / 4 b.GlyphStyle = DefaultGlyphStyle b.BoxStyle = DefaultLineStyle b.MedianStyle = DefaultLineStyle b.WhiskerStyle = draw.LineStyle{ Width: vg.Points(0.5), Dashes: []vg.Length{vg.Points(4), vg.Points(2)}, } if len(b.Values) == 0 { b.Width = 0 b.GlyphStyle.Radius = 0 b.BoxStyle.Width = 0 b.MedianStyle.Width = 0 b.WhiskerStyle.Width = 0 } return b, nil }
// makeLegend returns a legend with the default // parameter settings. func makeLegend() (Legend, error) { font, err := vg.MakeFont(DefaultFont, vg.Points(12)) if err != nil { return Legend{}, err } return Legend{ ThumbnailWidth: vg.Points(20), TextStyle: draw.TextStyle{Font: font}, }, nil }
func DataTableToPng(b *bytes.Buffer, dt *db.DataTable, title string, width, height float64, xLabel string) error { p, err := plot.New() if err != nil { return err } p.Title.Text = title p.X.Label.Text = xLabel p.Y.Label.Text = "msec" // TODO: Fix this. // TODO: need new ticker function to handle equalX (while keeping xLabel as selected) if xLabel == common.TimeName { p.X.Tick.Marker = TimeTicks } p.Legend.Top = true numColumns := len(dt.ColumnNames) lines := make([]plotter.XYs, numColumns-1) // Skip X column. for _, dRow := range dt.Data { xp := (*dRow)[0] if xp != nil { for col := 1; col < numColumns; col++ { // Skip X column. yp := (*dRow)[col] if yp != nil { lines[col-1] = append(lines[col-1], struct{ X, Y float64 }{X: *xp, Y: *yp}) } } } } colorList := getColors(numColumns - 1) // Skip X column. for i, line := range lines { columnName := dt.ColumnNames[i+1] l, err := plotter.NewLine(line) if err != nil { return err } if strings.Index(columnName, common.RegressNamePrefix) == 0 { // If regression value. l.LineStyle.Color = color.RGBA{255, 0, 0, 255} l.LineStyle.Width = vg.Points(2.0) } else { l.LineStyle.Color = colorList[i] l.LineStyle.Width = vg.Points(1.5) } p.Add(l) p.Legend.Add(columnName, l) } tPng := time.Now() drawPng(b, p, width, height) glog.V(3).Infof("PERF: makePng time: %v", time.Now().Sub(tPng)) return nil }
// Draw the plot logo. func Example() { p, err := plot.New() if err != nil { log.Panic(err) } DefaultLineStyle.Width = vg.Points(1) DefaultGlyphStyle.Radius = vg.Points(3) p.Y.Tick.Marker = plot.ConstantTicks([]plot.Tick{ {0, "0"}, {0.25, ""}, {0.5, "0.5"}, {0.75, ""}, {1, "1"}, }) p.X.Tick.Marker = plot.ConstantTicks([]plot.Tick{ {0, "0"}, {0.25, ""}, {0.5, "0.5"}, {0.75, ""}, {1, "1"}, }) pts := XYs{{0, 0}, {0, 1}, {0.5, 1}, {0.5, 0.6}, {0, 0.6}} line, err := NewLine(pts) if err != nil { log.Panic(err) } scatter, err := NewScatter(pts) if err != nil { log.Panic(err) } p.Add(line, scatter) pts = XYs{{1, 0}, {0.75, 0}, {0.75, 0.75}} line, err = NewLine(pts) if err != nil { log.Panic(err) } scatter, err = NewScatter(pts) if err != nil { log.Panic(err) } p.Add(line, scatter) pts = XYs{{0.5, 0.5}, {1, 0.5}} line, err = NewLine(pts) if err != nil { log.Panic(err) } scatter, err = NewScatter(pts) if err != nil { log.Panic(err) } p.Add(line, scatter) err = p.Save(100, 100, "testdata/plotLogo.png") if err != nil { log.Panic(err) } }
// Example_horizontalBoxPlots draws horizontal boxplots // with some labels on their points. func Example_horizontalBoxPlots() *plot.Plot { rand.Seed(int64(0)) n := 100 uniform := make(valueLabels, n) normal := make(valueLabels, n) expon := make(valueLabels, n) for i := 0; i < n; i++ { uniform[i].Value = rand.Float64() uniform[i].Label = fmt.Sprintf("%4.4f", uniform[i].Value) normal[i].Value = rand.NormFloat64() normal[i].Label = fmt.Sprintf("%4.4f", normal[i].Value) expon[i].Value = rand.ExpFloat64() expon[i].Label = fmt.Sprintf("%4.4f", expon[i].Value) } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Horizontal Box Plot" p.X.Label.Text = "plotter.Values" // Make boxes for our data and add them to the plot. uniBox := must(plotter.MakeHorizBoxPlot(vg.Points(20), 0, uniform)).(plotter.HorizBoxPlot) uniLabels, err := uniBox.OutsideLabels(uniform) if err != nil { panic(err) } normBox := must(plotter.MakeHorizBoxPlot(vg.Points(20), 1, normal)).(plotter.HorizBoxPlot) normLabels, err := normBox.OutsideLabels(normal) if err != nil { panic(err) } expBox := must(plotter.MakeHorizBoxPlot(vg.Points(20), 2, expon)).(plotter.HorizBoxPlot) expLabels, err := expBox.OutsideLabels(expon) if err != nil { panic(err) } p.Add(uniBox, uniLabels, normBox, normLabels, expBox, expLabels) // Add a GlyphBox plotter for debugging. p.Add(plotter.NewGlyphBoxes()) // Set the Y axis of the plot to nominal with // the given names for y=0, y=1 and y=2. p.NominalY("Uniform\nDistribution", "Normal\nDistribution", "Exponential\nDistribution") return p }
func main() { var levels []float64 for l := 100.5; l < volcano.Matrix.(*mat64.Dense).Max(); l += 5 { levels = append(levels, l) } c := plotter.NewContour(volcano, levels, palette.Rainbow(len(levels), (palette.Yellow+palette.Red)/2, palette.Blue, 1, 1, 1)) quarterStyle := draw.LineStyle{ Color: color.Black, Width: vg.Points(0.5), Dashes: []vg.Length{0.2, 0.4}, } halfStyle := draw.LineStyle{ Color: color.Black, Width: vg.Points(0.5), Dashes: []vg.Length{5, 2, 1, 2}, } c.LineStyles = append(c.LineStyles, quarterStyle, halfStyle, quarterStyle) h := plotter.NewHeatMap(volcano, palette.Heat(len(levels)*2, 1)) p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Maunga Whau Volcano" p.Add(h) p.Add(c) p.X.Padding = 0 p.Y.Padding = 0 _, p.X.Max, _, p.Y.Max = h.DataRange() name := "example_volcano" for _, ext := range []string{ ".eps", ".pdf", ".svg", ".png", ".tiff", ".jpg", } { if err := p.Save(4, 4, name+ext); err != nil { panic(err) } } }
func Example_groupedQuartPlots() *plot.Plot { rand.Seed(int64(0)) n := 100 uniform := make(plotter.Values, n) normal := make(plotter.Values, n) expon := make(plotter.Values, n) for i := 0; i < n; i++ { uniform[i] = rand.Float64() normal[i] = rand.NormFloat64() expon[i] = rand.ExpFloat64() } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Box Plot" p.Y.Label.Text = "plotter.Values" w := vg.Points(10) for x := 0.0; x < 3.0; x++ { b0 := must(plotter.NewQuartPlot(x, uniform)).(*plotter.QuartPlot) b0.Offset = -w b1 := must(plotter.NewQuartPlot(x, normal)).(*plotter.QuartPlot) b2 := must(plotter.NewQuartPlot(x, expon)).(*plotter.QuartPlot) b2.Offset = w p.Add(b0, b1, b2) } p.Add(plotter.NewGlyphBoxes()) p.NominalX("Group 0", "Group 1", "Group 2") return p }
// CreateImage creates graph of nyanpass func (n *Nyanpass) CreateImage(fileName string) error { if n.Counts == nil { return errors.New("Count is not defined.") } p, err := plot.New() if err != nil { return err } bar, err := plotter.NewBarChart(n.Counts, vg.Points(30)) if err != nil { return err } bar.LineStyle.Width = vg.Length(0) bar.Color = plotutil.Color(2) p.Add(bar) p.Title.Text = "Nyanpass Graph" p.X.Label.Text = "Days" p.Y.Label.Text = "Nyanpass count" p.NominalX(n.labels...) p.Y.Tick.Marker = RelabelTicks{} if err := p.Save(6*vg.Inch, 6*vg.Inch, fileName); err != nil { return err } n.imagePath = fileName return nil }
// An example of making a histogram. func Example_histogram() *plot.Plot { rand.Seed(int64(0)) n := 10000 vals := make(plotter.Values, n) for i := 0; i < n; i++ { vals[i] = rand.NormFloat64() } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Histogram" h, err := plotter.NewHist(vals, 16) if err != nil { panic(err) } h.Normalize(1) p.Add(h) // The normal distribution function norm := plotter.NewFunction(stdNorm) norm.Color = color.RGBA{R: 255, A: 255} norm.Width = vg.Points(2) p.Add(norm) return p }
// DrawGlyph implements the Glyph interface. func (RingGlyph) DrawGlyph(c *Canvas, sty GlyphStyle, pt Point) { c.SetLineStyle(LineStyle{Color: sty.Color, Width: vg.Points(0.5)}) var p vg.Path p.Move(pt.X+sty.Radius, pt.Y) p.Arc(pt.X, pt.Y, sty.Radius, 0, 2*math.Pi) p.Close() c.Stroke(p) }
func TestKCmeansSynthetic(t *testing.T) { clusters, spacing := 7, 4.0 data, points := make([][]float64, clusters*POINTS), make(plotter.XYs, clusters*POINTS) for c := 0; c < clusters; c++ { //A, B, C, D := rand.NormFloat64(), rand.NormFloat64(), rand.NormFloat64(), rand.NormFloat64() //x, y := spacing * rand.NormFloat64(), spacing * rand.NormFloat64() for p := 0; p < POINTS; p++ { point := make([]float64, 2) point[0], point[1] = spacing*float64(c)+rand.NormFloat64(), spacing*float64(c)+rand.NormFloat64() //point[0], point[1] = x + rand.NormFloat64(), y + rand.NormFloat64() //point[0], point[1] = A * point[0] + B * point[1], C * point[0] + D * point[1] index := POINTS*c + p data[index], points[index].X, points[index].Y = point, point[0], point[1] } } threshold := 1000 _, means, err := KCmeans(data, 30, EuclideanDistance, threshold, 10) if err != nil { log.Fatal(err) } fmt.Printf("means = %v\n", len(means)) centerPoints := make(plotter.XYs, len(means)) for ii := range means { centerPoints[ii].X, centerPoints[ii].Y = means[ii][0], means[ii][1] } p, err := plot.New() p.Title.Text = "Clusters" p.X.Label.Text = "X" p.Y.Label.Text = "Y" scatter, err := plotter.NewScatter(points) scatter.Shape = draw.CircleGlyph{} scatter.Radius = vg.Points(2) p.Add(scatter) scatter, err = plotter.NewScatter(centerPoints) scatter.Shape = draw.CircleGlyph{} scatter.Radius = vg.Points(2) scatter.Color = color.RGBA{0, 0, 255, 255} p.Add(scatter) if err := p.Save(8, 8, "synthetic.png"); err != nil { panic(err) } }
// DrawGlyph implements the Glyph interface. func (TriangleGlyph) DrawGlyph(c *Canvas, sty GlyphStyle, pt Point) { c.SetLineStyle(LineStyle{Color: sty.Color, Width: vg.Points(0.5)}) r := sty.Radius + (sty.Radius-sty.Radius*sinπover6)/2 var p vg.Path p.Move(pt.X, pt.Y+r) p.Line(pt.X-r*cosπover6, pt.Y-r*sinπover6) p.Line(pt.X+r*cosπover6, pt.Y-r*sinπover6) p.Close() c.Stroke(p) }
func (p *Plot) Write(f string) error { for i, ln := range p.lines { l, _ := plotter.NewLine(ln.pts) l.LineStyle.Width = vg.Points(2) l.LineStyle.Color = colors[i%len(colors)] p.p.Legend.Add(ln.name, l) p.p.Add(l) } return p.p.Save(10*vg.Inch, 10*vg.Inch, f) }
// DrawGlyph implements the Glyph interface. func (SquareGlyph) DrawGlyph(c *Canvas, sty GlyphStyle, pt Point) { c.SetLineStyle(LineStyle{Color: sty.Color, Width: vg.Points(0.5)}) x := (sty.Radius-sty.Radius*cosπover4)/2 + sty.Radius*cosπover4 var p vg.Path p.Move(pt.X-x, pt.Y-x) p.Line(pt.X+x, pt.Y-x) p.Line(pt.X+x, pt.Y+x) p.Line(pt.X-x, pt.Y+x) p.Close() c.Stroke(p) }
// Example_points draws some scatter points, a line, // and a line with points. func Example_points() *plot.Plot { rand.Seed(int64(0)) n := 15 scatterData := randomPoints(n) lineData := randomPoints(n) linePointsData := randomPoints(n) p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Points Example" p.X.Label.Text = "X" p.Y.Label.Text = "Y" p.Add(plotter.NewGrid()) s := must(plotter.NewScatter(scatterData)).(*plotter.Scatter) s.GlyphStyle.Color = color.RGBA{R: 255, B: 128, A: 255} s.GlyphStyle.Radius = vg.Points(3) l := must(plotter.NewLine(lineData)).(*plotter.Line) 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} lpLine, lpPoints, err := plotter.NewLinePoints(linePointsData) if err != nil { panic(err) } lpLine.Color = color.RGBA{G: 255, A: 255} lpPoints.Shape = draw.CircleGlyph{} lpPoints.Color = color.RGBA{R: 255, A: 255} p.Add(s, l, lpLine, lpPoints) p.Legend.Add("scatter", s) p.Legend.Add("line", l) p.Legend.Add("line points", lpLine, lpPoints) return p }
// DrawGlyph implements the Glyph interface. func (CrossGlyph) DrawGlyph(c *Canvas, sty GlyphStyle, pt Point) { c.SetLineStyle(LineStyle{Color: sty.Color, Width: vg.Points(0.5)}) r := sty.Radius * cosπover4 var p vg.Path p.Move(pt.X-r, pt.Y-r) p.Line(pt.X+r, pt.Y+r) c.Stroke(p) p = vg.Path{} p.Move(pt.X-r, pt.Y+r) p.Line(pt.X+r, pt.Y-r) c.Stroke(p) }
func (line GrobLine) Draw(vp Viewport) { vp.Canvas.SetColor(line.color) vp.Canvas.SetLineWidth(vg.Points(line.size)) vp.Canvas.SetLineDash(dashLength[line.linetype%7], 0) x0, y0 := vp.X(line.x0), vp.Y(line.y0) x1, y1 := vp.X(line.x1), vp.Y(line.y1) var p vg.Path p.Move(x0, y0) p.Line(x1, y1) vp.Canvas.Stroke(p) }
func ExampleBubbles() { // randomTriples returns some random x, y, z triples // with some interesting kind of trend. randomTriples := func(n int) XYZs { data := make(XYZs, n) for i := range data { if i == 0 { data[i].X = rand.Float64() } else { data[i].X = data[i-1].X + 2*rand.Float64() } data[i].Y = data[i].X + 10*rand.Float64() data[i].Z = data[i].X } return data } n := 10 bubbleData := randomTriples(n) p, err := plot.New() if err != nil { log.Panic(err) } p.Title.Text = "Bubbles" p.X.Label.Text = "X" p.Y.Label.Text = "Y" bs, err := NewBubbles(bubbleData, vg.Points(1), vg.Points(20)) if err != nil { log.Panic(err) } bs.Color = color.RGBA{R: 196, B: 128, A: 255} p.Add(bs) err = p.Save(200, 200, "testdata/bubbles.png") if err != nil { log.Panic(err) } }
// Example_functions draws some functions. func Example_functions() *plot.Plot { p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Functions" p.X.Label.Text = "X" p.Y.Label.Text = "Y" quad := plotter.NewFunction(func(x float64) float64 { return x * x }) quad.Color = color.RGBA{B: 255, A: 255} exp := plotter.NewFunction(func(x float64) float64 { return math.Pow(2, x) }) exp.Dashes = []vg.Length{vg.Points(2), vg.Points(2)} exp.Width = vg.Points(2) exp.Color = color.RGBA{G: 255, A: 255} sin := plotter.NewFunction(func(x float64) float64 { return 10*math.Sin(x) + 50 }) sin.Dashes = []vg.Length{vg.Points(4), vg.Points(5)} sin.Width = vg.Points(4) sin.Color = color.RGBA{R: 255, A: 255} p.Add(quad, exp, sin) p.Legend.Add("x^2", quad) p.Legend.Add("2^x", exp) p.Legend.Add("10*sin(x)+50", sin) p.Legend.ThumbnailWidth = 0.5 * vg.Inch p.X.Min = 0 p.X.Max = 10 p.Y.Min = 0 p.Y.Max = 100 return p }
func Example_bubbles() *plot.Plot { rand.Seed(int64(0)) n := 10 bubbleData := randomTriples(n) p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Bubbles" p.X.Label.Text = "X" p.Y.Label.Text = "Y" bs, err := plotter.NewBubbles(bubbleData, vg.Points(1), vg.Points(20)) if err != nil { panic(err) } bs.Color = color.RGBA{R: 196, B: 128, A: 255} p.Add(bs) return p }
func (s *Plots) DrawLats() { p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Response Time" p.X.Label.Text = "Time (seconds)" p.Y.Label.Text = "Response time (ms)" p.Add(plotter.NewGrid()) // Make a scatter plotter and set its style. scatter, err := plotter.NewScatter(s.points) if err != nil { panic(err) } scatter.GlyphStyle.Color = color.RGBA{R: 255, B: 128, A: 255} // Make a line plotter and set its style. l, err := plotter.NewLine(s.intervalLats) 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} p.Add(scatter, l) p.Legend.Add("scatter", scatter) p.Legend.Add("line", l) // Save the plot to a PNG file. if err := p.Save(64*vg.Inch, 24*vg.Inch, "points.png"); err != nil { panic(err) } }
func (path GrobPath) Draw(vp Viewport) { vp.Canvas.Push() vp.Canvas.SetColor(path.color) vp.Canvas.SetLineWidth(vg.Points(path.size)) vp.Canvas.SetLineDash(dashLength[path.linetype], 0) x, y := vp.X(path.points[0].x), vp.Y(path.points[0].y) var p vg.Path p.Move(x, y) for i := 1; i < len(path.points); i++ { x, y = vp.X(path.points[i].x), vp.Y(path.points[i].y) p.Line(x, y) } vp.Canvas.Stroke(p) vp.Canvas.Pop() }
func drawTopReleaseDownloads(ctx *context, per *period, filename string) { var rs releases ctx.WalkReleases(func(r github.RepositoryRelease) { var cnt int if r.CreatedAt.Before(per.start) || r.CreatedAt.After(per.end) { return } for _, a := range r.Assets { cnt += *a.DownloadCount } rs = append(rs, release{name: *r.TagName, download: cnt}) }) sort.Sort(rs) var names []string var downloads []int num := 10 if num > len(rs) { num = len(rs) } for i := 0; i < num; i++ { names = append(names, rs[i].name) downloads = append(downloads, rs[i].download) } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Release Downloads" p.Y.Label.Text = "Download Count" if len(names) > 0 { p.NominalX(names...) bars, err := plotter.NewBarChart(ints(downloads), vg.Points(20)) if err != nil { panic(err) } bars.LineStyle.Width = vg.Length(0) p.Add(bars) } // Save the plot to a PNG file. if err := p.Save(defaultWidth, defaultHeight, filename); err != nil { panic(err) } }
// AddStackedAreaPlots adds stacked area plot plotters to a plot. // The variadic arguments must be either strings // or plotter.Valuers. Each valuer adds a stacked area // plot to the plot below the stacked area plots added // before it. If a plotter.Valuer is immediately // preceeded by a string then the string value is used to // label the legend. // Plots should be added in order of tallest to shortest, // because they will be drawn in the order they are added // (i.e. later plots will be painted over earlier plots). // // If an error occurs then none of the plotters are added // to the plot, and the error is returned. func AddStackedAreaPlots(plt *plot.Plot, xs plotter.Valuer, vs ...interface{}) error { var ps []plot.Plotter names := make(map[*plotter.Line]string) name := "" var i int for _, v := range vs { switch t := v.(type) { case string: name = t case plotter.Valuer: if xs.Len() != t.Len() { return errors.New("X/Y length mismatch") } // Make a line plotter and set its style. l, err := plotter.NewLine(combineXYs{xs: xs, ys: t}) if err != nil { return err } l.LineStyle.Width = vg.Points(0) color := Color(i) i++ l.ShadeColor = &color ps = append(ps, l) if name != "" { names[l] = name name = "" } default: panic(fmt.Sprintf("AddStackedAreaPlots handles strings and plotter.Valuers, got %T", t)) } } plt.Add(ps...) for p, n := range names { plt.Legend.Add(n, p) } return nil }
// An example of making a bar chart. func Example_barChart() *plot.Plot { groupA := plotter.Values{20, 35, 30, 35, 27} groupB := plotter.Values{25, 32, 34, 20, 25} groupC := plotter.Values{12, 28, 15, 21, 8} groupD := plotter.Values{30, 42, 6, 9, 12} p, err := plot.New() if err != nil { panic(err) } p.Title.Text = "Bar chart" p.Y.Label.Text = "Heights" w := vg.Points(8) barsA := must(plotter.NewBarChart(groupA, w)).(*plotter.BarChart) barsA.Color = color.RGBA{R: 255, A: 255} barsA.Offset = -w / 2 barsB := must(plotter.NewBarChart(groupB, w)).(*plotter.BarChart) barsB.Color = color.RGBA{R: 196, G: 196, A: 255} barsB.Offset = w / 2 barsC := must(plotter.NewBarChart(groupC, w)).(*plotter.BarChart) barsC.Color = color.RGBA{B: 255, A: 255} barsC.XMin = 6 barsC.Offset = -w / 2 barsD := must(plotter.NewBarChart(groupD, w)).(*plotter.BarChart) barsD.Color = color.RGBA{B: 255, R: 255, A: 255} barsD.XMin = 6 barsD.Offset = w / 2 p.Add(barsA, barsB, barsC, barsD) p.Legend.Add("A", barsA) p.Legend.Add("B", barsB) p.Legend.Add("C", barsC) p.Legend.Add("D", barsD) p.Legend.Top = true p.NominalX("Zero", "One", "Two", "Three", "Four", "", "Six", "Seven", "Eight", "Nine", "Ten") return p }