func main() { tests := []*Test{} // if file, err := os.Open("results.txt"); err != nil { if file, err := os.Stdin, error(nil); err != nil { log.Fatal(err) } else { scanner := bufio.NewScanner(file) for scanner.Scan() { test, err := ParseLine(scanner.Text()) if err != nil { continue } test.Calculate() tests = append(tests, test) } } if len(tests) == 0 { log.Fatal("No tests found.") } if plt, err := plot.New(); err != nil { log.Fatal(err) } else { for i, test := range tests { xys := test.ToXY(100000.0) line, err := plotter.NewLine(xys) if err != nil { log.Fatal(err) } line.Color, line.Dashes = plotutil.Color(i), plotutil.Dashes(0) plt.Add(line) { name := fmt.Sprintf("%s (%d)", test.Name, int(test.Stats.Mean/100000)) plt.Legend.Add(name, line) } } // plt.Legend.Font.Size = vg.Inches(plt.Legend.Font.Size * 0.75) plt.Legend.Font.Size *= 0.65 plt.Legend.Top = true plt.Legend.Left = true // plt.Legend.YOffs = vg.Inches(-1.12) // plt.Legend.XOffs = vg.Inches(1) plt.HideX() // plt.X.Padding = 20 plt.Y.Min = 0 plt.Y.Max = 1600 plt.Title.Text = fmt.Sprintf("Speed Test (averaged over %d runs and %d tests)", 100000, 100) plt.Y.Label.Text = "Cycles" plt.Save(6, 4, "number-parse.svg") } }
// Add colored line to chart func InfoAddLinePoints(plt *plot.Plot, color int, vs ...interface{}) error { var ps []plot.Plotter names := make(map[[2]plot.Thumbnailer]string) name := "" var i int = color for _, v := range vs { switch t := v.(type) { case string: name = t case plotter.XYer: l, s, err := plotter.NewLinePoints(t) if err != nil { return err } l.Color = plotutil.Color(i) l.Dashes = plotutil.Dashes(i) s.Color = plotutil.Color(i) s.Shape = plotutil.Shape(i) i++ ps = append(ps, l, s) if name != "" { names[[2]plot.Thumbnailer{l, s}] = name name = "" } default: panic(fmt.Sprintf("AddLinePoints handles strings and plotter.XYers, got %T", t)) } } plt.Add(ps...) for ps, n := range names { plt.Legend.Add(n, ps[0], ps[1]) } return nil }
func plotBehind(sp *raw.SpicePlot, scale_vector *raw.SpiceVector, typemap map[string][]*raw.SpiceVector) PlotMap { m := findMultiplicity(scale_vector.Data) c := int(sp.NPoints) / m plots := PlotMap{} for vector_type, vectors := range typemap { plot, err := plot.New() if err != nil { log.Fatal(err) } for i, vector := range vectors { xys := SpiceToXY(scale_vector, vector) for j := 0; j < m; j++ { line, err := plotter.NewLine(xys[j*c : (j+1)*c]) if err != nil { log.Fatal(err) } line.Color = plotutil.Color(i) line.Dashes = plotutil.Dashes(0) plot.Add(line) // plot.Legend.Add(vector.Name, line) // plot.Legend.Add(fmt.Sprintf("%s-%d", vector.Name, j), line) if j == 0 { plot.Legend.Add(vector.Name, line) } } // xys := SpiceToXY(scale_vector, vector) // line, err := plotter.NewLine(xys) // if err != nil { // log.Fatal(err) // } // line.Color = plotutil.Color(i + 1) // line.Dashes = plotutil.Dashes(0) // plot.Add(line) // plot.Legend.Add(vector.Name, line) } plot.Title.Text = sp.Title + ": " + sp.Name plot.X.Label.Text = scale_vector.Name plot.Y.Label.Text = vector_type // plots = append(plots, plot) plots[vector_type] = plot } return plots }
// Report builds up a plot of the response times of the requests // in SVG format and writes it to out func (r *TimingsPlotReporter) Report(out io.Writer) error { timestamps := make([]time.Time, 0) timings := make([]time.Duration, 0) for e := r.responses.Front(); e != nil; e = e.Next() { r := e.Value.(*result) timestamps = append(timestamps, r.timestamp) timings = append(timings, r.timing) } p, err := plot.New() if err != nil { return err } pts := make(plotter.XYs, len(timestamps)) for i := 0; i < len(pts); i++ { pts[i].X = timestamps[i].Sub(timestamps[0]).Seconds() pts[i].Y = timings[i].Seconds() * 1000 } line, err := plotter.NewLine(pts) if err != nil { return err } line.Color = plotutil.Color(1) p.Add(line) p.X.Padding = vg.Length(3.0) p.X.Label.Text = "Time elapsed" p.Y.Padding = vg.Length(3.0) p.Y.Label.Text = "Latency (ms)" w, h := vg.Millimeters(float64(len(timestamps))), vg.Centimeters(12.0) canvas := vgsvg.New(w, h) p.Draw(plot.MakeDrawArea(canvas)) _, err = canvas.WriteTo(out) return err }
func boxplot(path string, sets []set) error { var ( fiveEnds = make([]plotter.Values, len(sets)) threeEnds = make([]plotter.Values, len(sets)) err error ln int ) for i := range sets { fiveEnds[i], err = plotter.CopyValues(&normalised{vals: sets[i].fiveEnd}) if err != nil { return err } threeEnds[i], err = plotter.CopyValues(&normalised{vals: sets[i].threeEnd}) if err != nil { return err } if i == 0 { ln = fiveEnds[i].Len() } if fiveEnds[i].Len() != threeEnds[i].Len() || fiveEnds[i].Len() != ln { return errors.New("missing values") } } font, err := vg.MakeFont("Helvetica", 10) if err != nil { return err } titleFont, err := vg.MakeFont("Helvetica", 12) if err != nil { return err } style := plot.TextStyle{Color: color.Gray{0}, Font: font} p, err := plot.New() if err != nil { return err } p.Title.Text = titles[filter] p.Title.TextStyle = plot.TextStyle{Color: color.Gray{0}, Font: titleFont} p.X.Label.Text = "Length Offset" p.Y.Label.Text = "Relative Frequency" p.X.Label.TextStyle = style p.Y.Label.TextStyle = style p.X.Tick.Label = style p.Y.Tick.Label = style p.Legend.TextStyle = style type boxPair struct{ five, three *plotter.BoxPlot } var boxes []boxPair for i := 0; i < ln; i++ { fiveEnd := make(plotter.Values, len(sets)) threeEnd := make(plotter.Values, len(sets)) for j := range sets { fiveEnd[j] = fiveEnds[j][i] threeEnd[j] = threeEnds[j][i] } boxFivePrime, err := plotter.NewBoxPlot(1, float64(i), fiveEnd) // A non-zero width is required to prevent the creation failing. if err != nil { return err } boxFivePrime.MedianStyle.Width = 0.5 boxFivePrime.BoxStyle.Width = 0.75 boxFivePrime.BoxStyle.Color = plotutil.Color(0) boxThreePrime, err := plotter.NewBoxPlot(1, float64(i), threeEnd) // A non-zero width is required to prevent the creation failing. if err != nil { return err } boxThreePrime.MedianStyle.Width = 0.5 boxThreePrime.BoxStyle.Width = 0.75 boxThreePrime.BoxStyle.Color = plotutil.Color(1) boxes = append(boxes, boxPair{boxFivePrime, boxThreePrime}) p.Add(boxFivePrime, boxThreePrime) } p.Legend.Add("5'-end", &plotter.BarChart{Color: plotutil.Color(0)}) p.Legend.Add("3'-end", &plotter.BarChart{Color: plotutil.Color(1)}) p.Legend.Top = true p.NominalX(func() []string { n := make([]string, ln) for i := 0; i < ln; i++ { if v := i - maxLength; v%5 == 0 { n[i] = fmt.Sprint(v) } } return n }()...) p.X.Width = 0.5 p.X.Tick.Width = 0.5 p.X.Tick.Length = 8 p.Add(&plotter.Grid{Vertical: plotter.DefaultGridLineStyle}) c := vgsvg.New(vg.Centimeters(19), vg.Centimeters(10)) da := plot.MakeDrawArea(c) trX, _ := p.Transforms(&da) w := ((trX(float64(2*maxLength)) - trX(float64(0))) / vg.Length(2*maxLength)) / 3 for _, b := range boxes { b.five.Width = w b.five.Offset = -w / 2 b.three.Width = w b.three.Offset = w / 2 } p.Draw(da) f, err := os.Create(decorate(path, "boxplot.svg", filter)) if err != nil { return err } defer f.Close() _, err = c.WriteTo(f) return err }
func barchart(path string, data set) error { font, err := vg.MakeFont("Helvetica", 10) if err != nil { return err } titleFont, err := vg.MakeFont("Helvetica", 12) if err != nil { return err } style := plot.TextStyle{Color: color.Gray{0}, Font: font} p, err := plot.New() if err != nil { return err } p.Title.Text = titles[filter] p.Title.TextStyle = plot.TextStyle{Color: color.Gray{0}, Font: titleFont} p.X.Label.Text = "Length Offset" p.Y.Label.Text = "Relative Frequency" p.X.Label.TextStyle = style p.Y.Label.TextStyle = style p.X.Tick.Label = style p.Y.Tick.Label = style p.Legend.TextStyle = style barsFivePrime, err := plotter.NewBarChart(&normalised{vals: data.fiveEnd}, 1) // A non-zero width is required to prevent the creation failing. if err != nil { return err } barsFivePrime.LineStyle.Width = vg.Length(0) barsFivePrime.Color = plotutil.Color(0) barsThreePrime, err := plotter.NewBarChart(&normalised{vals: data.threeEnd}, 1) // A non-zero width is required to prevent the creation failing. if err != nil { return err } barsThreePrime.LineStyle.Width = vg.Length(0) barsThreePrime.Color = plotutil.Color(1) p.Add(barsFivePrime, barsThreePrime) p.Legend.Add("5'-end", barsFivePrime) p.Legend.Add("3'-end", barsThreePrime) p.Legend.Top = true p.NominalX(func() []string { n := make([]string, len(data.fiveEnd)) for i := range data.fiveEnd { if v := i - maxLength; v%5 == 0 { n[i] = fmt.Sprint(v) } } return n }()...) c := vgsvg.New(vg.Centimeters(19), vg.Centimeters(10)) da := plot.MakeDrawArea(c) trX, _ := p.Transforms(&da) w := ((trX(float64(2*maxLength)) - trX(float64(0))) / vg.Length(2*maxLength)) / 3 barsFivePrime.Width = w barsFivePrime.Offset = -w / 2 barsThreePrime.Width = w barsThreePrime.Offset = w / 2 p.Draw(da) f, err := os.Create(decorate(path, "barchart.svg", filter)) if err != nil { return err } defer f.Close() _, err = c.WriteTo(f) return err }
func marshalPNG(r *http.Request, results []*metricData) []byte { p, err := plot.New() if err != nil { panic(err) } // set bg/fg colors bgcolor := string2Color(getString(r.FormValue("bgcolor"), "black")) p.BackgroundColor = bgcolor fgcolorstr := getString(r.FormValue("fgcolor"), "white") fgcolor := string2Color(fgcolorstr) p.Title.Color = fgcolor p.X.LineStyle.Color = fgcolor p.Y.LineStyle.Color = fgcolor p.X.Tick.LineStyle.Color = fgcolor p.Y.Tick.LineStyle.Color = fgcolor p.X.Tick.Label.Color = fgcolor p.Y.Tick.Label.Color = fgcolor p.X.Label.Color = fgcolor p.Y.Label.Color = fgcolor p.Legend.Color = fgcolor // set grid grid := plotter.NewGrid() grid.Vertical.Color = fgcolor grid.Horizontal.Color = fgcolor p.Add(grid) // line mode (ikruglow) TODO check values lineMode := getString(r.FormValue("lineMode"), "slope") // width and height width := getInt(r.FormValue("width"), 330) height := getInt(r.FormValue("height"), 250) // need different timeMarker's based on step size p.Title.Text = r.FormValue("title") p.X.Tick.Marker = makeTimeMarker(results[0].GetStepTime()) hideLegend := getBool(r.FormValue("hideLegend"), false) graphOnly := getBool(r.FormValue("graphOnly"), false) if graphOnly { p.HideAxes() } if len(results) == 1 && results[0].color == "" { results[0].color = fgcolorstr } var lines []plot.Plotter for i, r := range results { l := NewResponsePlotter(r) l.LineStyle.Color = fgcolor // consolidate datapoints l.maybeConsolidateData(width) if r.drawAsInfinite { l.lineMode = "drawAsInfinite" } else { l.lineMode = lineMode } if r.color != "" { l.Color = string2Color(r.color) } else { l.Color = plotutil.Color(i) } lines = append(lines, l) if !graphOnly && !hideLegend { p.Legend.Add(r.GetName(), l) } } p.Add(lines...) p.Y.Max *= 1.05 p.Y.Min *= 0.95 // Draw the plot to an in-memory image. img := image.NewRGBA(image.Rect(0, 0, width, height)) da := plot.MakeDrawArea(vgimg.NewImage(img)) p.Draw(da) var b bytes.Buffer if err := png.Encode(&b, img); err != nil { panic(err) } return b.Bytes() }