func TestArcsSVG() { img := vgsvg.New(vg.Inches(4), vg.Inches(4)) DrawArcs(img) err := img.Save("arcs.svg") if err != nil { panic(err) } }
func TestFontsSVG() { img := vgsvg.New(vg.Inches(4), vg.Inches(4)) DrawFonts(img) err := img.Save("fonts.svg") if err != nil { panic(err) } }
//Save saves the board (i.e. all subplots, appropriately laid out) to the specified filename. //It basically rips off the implementation of Save in plotinum to support various file formats. func (b *Board) Save(width, height float64, file string) (err error) { w, h := vg.Inches(width), vg.Inches(height) var c interface { vg.Canvas Size() (w, h vg.Length) io.WriterTo } switch ext := strings.ToLower(filepath.Ext(file)); ext { case ".eps": c = vgeps.NewTitle(w, h, file) case ".jpg", ".jpeg": c = vgimg.JpegCanvas{Canvas: vgimg.New(w, h)} case ".pdf": c = vgpdf.New(w, h) case ".png": c = vgimg.PngCanvas{Canvas: vgimg.New(w, h)} case ".svg": c = vgsvg.New(w, h) case ".tiff": c = vgimg.TiffCanvas{Canvas: vgimg.New(w, h)} default: return fmt.Errorf("Unsupported file extension: %s", ext) } for _, subplot := range b.SubPlots { w, h := c.Size() drawArea := plot.DrawArea{ Canvas: c, Rect: subplot.ScaledRect(float64(w), float64(h)), } subplot.Plot.Draw(drawArea) } f, err := os.Create(file) if err != nil { return err } if _, err = c.WriteTo(f); err != nil { return err } say.Println(0, say.Yellow("Saved %s", file)) return f.Close() }
// Save saves the plot to an image file. Width and height // are specified in inches, and the file format is determined // by the extension. Supported extensions are // .eps, .jpg, .jpeg, .pdf, .png, .svg, and .tiff. func (p *Plot) Save(width, height float64, file string) (err error) { w, h := vg.Inches(width), vg.Inches(height) var c interface { vg.Canvas Size() (w, h vg.Length) io.WriterTo } switch ext := strings.ToLower(filepath.Ext(file)); ext { case ".eps": c = vgeps.NewTitle(w, h, file) case ".jpg", ".jpeg": c = vgimg.JpegCanvas{Canvas: vgimg.New(w, h)} case ".pdf": c = vgpdf.New(w, h) case ".png": c = vgimg.PngCanvas{Canvas: vgimg.New(w, h)} case ".svg": c = vgsvg.New(w, h) case ".tiff": c = vgimg.TiffCanvas{Canvas: vgimg.New(w, h)} default: return fmt.Errorf("Unsupported file extension: %s", ext) } p.Draw(MakeDrawArea(c)) f, err := os.Create(file) if err != nil { return err } if _, err = c.WriteTo(f); err != nil { return err } return f.Close() }
// 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 }