// 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(plotter.NewBoxPlot(vg.Points(20), 0, uniform), plotter.NewBoxPlot(vg.Points(20), 1, normal), plotter.NewBoxPlot(vg.Points(20), 2, expon)) // 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 }
// 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 := plotter.NewLine(pts) scatter := plotter.NewScatter(pts) p.Add(line, scatter) pts = plotter.XYs{{1, 0}, {0.75, 0}, {0.75, 0.75}} line = plotter.NewLine(pts) scatter = plotter.NewScatter(pts) p.Add(line, scatter) pts = plotter.XYs{{0.5, 0.5}, {1, 0.5}} line = plotter.NewLine(pts) scatter = plotter.NewScatter(pts) p.Add(line, scatter) return p }
// 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: TextStyle{Font: font}, }, nil }
// 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 { b := new(BoxPlot) b.Location = loc b.Width = w b.CapWidth = 3 * w / 4 b.GlyphStyle = DefaultGlyphStyle b.BoxStyle = DefaultLineStyle b.MedianStyle = DefaultLineStyle b.WhiskerStyle = plot.LineStyle{ Width: vg.Points(0.5), Dashes: []vg.Length{vg.Points(4), vg.Points(2)}, } b.Values = CopyValues(values) sorted := CopyValues(values) sort.Float64s(sorted) if len(sorted) == 0 { b.Width = 0 b.GlyphStyle.Radius = 0 b.BoxStyle.Width = 0 b.MedianStyle.Width = 0 b.WhiskerStyle.Width = 0 return b } else if len(sorted) == 1 { b.Median = sorted[0] b.Quartile1 = sorted[0] b.Quartile3 = sorted[0] } else { b.Median = median(sorted) b.Quartile1 = median(sorted[:len(sorted)/2]) b.Quartile3 = median(sorted[len(sorted)/2:]) } b.Min = sorted[0] b.Max = sorted[len(sorted)-1] low := b.Quartile1 - 1.5*(b.Quartile3-b.Quartile1) high := b.Quartile3 + 1.5*(b.Quartile3-b.Quartile1) b.AdjLow = math.Inf(1) b.AdjHigh = math.Inf(-1) for i, v := range b.Values { if v > high || v < low { b.Outside = append(b.Outside, i) continue } if v < b.AdjLow { b.AdjLow = v } if v > b.AdjHigh { b.AdjHigh = v } } return b }
// 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 := plotter.HorizBoxPlot{plotter.NewBoxPlot(vg.Points(20), 0, uniform)} uniLabels, err := uniBox.OutsideLabels(uniform) if err != nil { panic(err) } normBox := plotter.HorizBoxPlot{plotter.NewBoxPlot(vg.Points(20), 1, normal)} normLabels, err := normBox.OutsideLabels(normal) if err != nil { panic(err) } expBox := plotter.HorizBoxPlot{plotter.NewBoxPlot(vg.Points(20), 2, expon)} 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 }
// 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 := plotter.NewHist(vals, 16) 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(da *DrawArea, sty GlyphStyle, pt Point) { da.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() da.Stroke(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 := plotter.NewBubbles(bubbleData, vg.Points(1), vg.Points(20)) bs.Color = color.RGBA{R: 196, B: 128, A: 255} p.Add(bs) return p }
// DrawGlyph implements the Glyph interface. func (TriangleGlyph) DrawGlyph(da *DrawArea, sty GlyphStyle, pt Point) { da.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() da.Stroke(p) }
// DrawGlyph implements the Glyph interface. func (SquareGlyph) DrawGlyph(da *DrawArea, sty GlyphStyle, pt Point) { da.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() da.Stroke(p) }
// DrawGlyph implements the Glyph interface. func (CrossGlyph) DrawGlyph(da *DrawArea, sty GlyphStyle, pt Point) { da.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) da.Stroke(p) p = vg.Path{} p.Move(pt.X-r, pt.Y+r) p.Line(pt.X+r, pt.Y-r) da.Stroke(p) }
// 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 = vg.Inches(0.5) p.X.Min = 0 p.X.Max = 10 p.Y.Min = 0 p.Y.Max = 100 return 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 := plotter.NewScatter(scatterData) s.GlyphStyle.Color = color.RGBA{R: 255, B: 128, A: 255} s.GlyphStyle.Radius = vg.Points(3) l := plotter.NewLine(lineData) 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 := plotter.NewLinePoints(linePointsData) lpLine.Color = color.RGBA{G: 255, A: 255} lpPoints.Shape = plot.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 }
// 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 := plotter.NewBarChart(groupA, w) barsA.Color = color.RGBA{R: 255, A: 255} barsA.Offset = -w / 2 barsB := plotter.NewBarChart(groupB, w) barsB.Color = color.RGBA{R: 196, G: 196, A: 255} barsB.Offset = w / 2 barsC := plotter.NewBarChart(groupC, w) barsC.Color = color.RGBA{B: 255, A: 255} barsC.XMin = 6 barsC.Offset = -w / 2 barsD := plotter.NewBarChart(groupD, w) 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 }
// makeAxis returns a default Axis. // // The default range is (∞, ∞), and thus any finite // value is less than Min and greater than Max. func makeAxis() (Axis, error) { labelFont, err := vg.MakeFont(defaultFont, vg.Points(12)) if err != nil { return Axis{}, err } tickFont, err := vg.MakeFont(defaultFont, vg.Points(10)) if err != nil { return Axis{}, err } a := Axis{ Min: math.Inf(1), Max: math.Inf(-1), LineStyle: LineStyle{ Color: color.Black, Width: vg.Points(0.5), }, Padding: vg.Points(5), } a.Label.TextStyle = TextStyle{ Color: color.Black, Font: labelFont, } a.Tick.Label = TextStyle{ Color: color.Black, Font: tickFont, } a.Tick.LineStyle = LineStyle{ Color: color.Black, Width: vg.Points(0.5), } a.Tick.Length = vg.Points(8) a.Tick.Marker = DefaultTicks return a, nil }
// Use of this source code is governed by an MIT-style license // that can be found in the LICENSE file. package plotter import ( "github.com/vron/plotinum/plot" "github.com/vron/plotinum/vg" ) var ( // DefaultFont is the default font name. DefaultFont = "Times-Roman" // DefaultFontSize is the default font. DefaultFontSize = vg.Points(10) ) // Labels implements the Plotter interface, // drawing a set of labels at specified points. type Labels struct { XYs // Labels is the set of labels corresponding // to each point. Labels []string // TextStyle is the style of the label text. plot.TextStyle // XAlign and YAlign are multiplied by the width
// box plots, labels, and more. package plotter import ( "github.com/vron/plotinum/plot" "github.com/vron/plotinum/vg" "image/color" "math" ) var ( // DefaultLineStyle is the default style for drawing // lines. DefaultLineStyle = plot.LineStyle{ Color: color.Black, Width: vg.Points(1), Dashes: []vg.Length{}, DashOffs: 0, } // DefaultGlyphStyle is the default style used // for gyph marks. DefaultGlyphStyle = plot.GlyphStyle{ Color: color.Black, Radius: vg.Points(2.5), Shape: plot.RingGlyph{}, } ) // Valuer wraps the Len and Value methods. type Valuer interface {
func NewGlyphBoxes() *GlyphBoxes { g := new(GlyphBoxes) g.Color = color.RGBA{R: 255, A: 255} g.Width = vg.Points(0.25) return g }
// than the max number of GlyphDrawers // in the DefaultGlyphShapes slice. func Shape(i int) plot.GlyphDrawer { n := len(DefaultGlyphShapes) if i < 0 { return DefaultGlyphShapes[i%n+n] } return DefaultGlyphShapes[i%n] } // DefaultDashes is a set of dash patterns used by // the Dashes function. var DefaultDashes = [][]vg.Length{ {}, {vg.Points(6), vg.Points(2)}, {vg.Points(2), vg.Points(2)}, {vg.Points(1), vg.Points(1)}, {vg.Points(5), vg.Points(2), vg.Points(1), vg.Points(2)}, {vg.Points(10), vg.Points(2), vg.Points(2), vg.Points(2), vg.Points(2), vg.Points(2), vg.Points(2), vg.Points(2)}, {vg.Points(10), vg.Points(2), vg.Points(2), vg.Points(2)}, {vg.Points(5), vg.Points(2), vg.Points(5), vg.Points(2), vg.Points(2), vg.Points(2), vg.Points(2), vg.Points(2)},
// Copyright 2012 The Plotinum Authors. All rights reserved. // Use of this source code is governed by an MIT-style license // that can be found in the LICENSE file. package plotter import ( "github.com/vron/plotinum/plot" "github.com/vron/plotinum/vg" "math" ) // DefaultCapWidth is the default width of error bar caps. var DefaultCapWidth = vg.Points(5) // YErrorBars implements the plot.Plotter, plot.DataRanger, // and plot.GlyphBoxer interfaces, drawing vertical error // bars, denoting error in Y values. type YErrorBars struct { XYs // YErrors is a copy of the Y errors for each point. YErrors // LineStyle is the style used to draw the error bars. plot.LineStyle // CapWidth is the width of the caps drawn at the top // of each error bar. CapWidth vg.Length }
// Use of this source code is governed by an MIT-style license // that can be found in the LICENSE file. package plotter import ( "github.com/vron/plotinum/plot" "github.com/vron/plotinum/vg" "image/color" ) var ( // DefaultGridLineStyle is the default style for grid lines. DefaultGridLineStyle = plot.LineStyle{ Color: color.Gray{128}, Width: vg.Points(0.25), } ) // Grid implements the plot.Plotter interface, drawing // a set of grid lines at the major tick marks. type Grid struct { // Vertical is the style of the vertical lines. Vertical plot.LineStyle // Horizontal is the style of the horizontal lines. Horizontal plot.LineStyle } // NewGrid returns a new grid with both vertical and // horizontal lines using the default grid line style.