// 784 Bits func Paint(image []float64, imageId int) { outPlotPoints := make(plotter.XYs, len(image)) outPlot, err := plot.New() if err != nil { panic(err) } x := 0 y := 0 for i, bit := range image { outPlotPoints[i].X = float64(x) if bit > 0.4 { outPlotPoints[i].Y = float64(y) } else { outPlotPoints[i].Y = 0 } if i%int(math.Sqrt(float64(len(image)))) == 0 { x = 0 y++ } else { x++ } } outPlot.Add(plotter.NewGrid()) s, _ := plotter.NewScatter(outPlotPoints) outPlot.Add(s) if err = outPlot.Save(6*vg.Inch, 6*vg.Inch, "plots/centroid-drawing-"+strconv.FormatInt(int64(imageId), 16)+".png"); err != nil { panic(err) } }
func (s *Plots) DrawTps() { 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 line plotter and set its style. l, err := plotter.NewLine(s.intervalsTps) if err != nil { panic(err) } l.LineStyle.Color = color.RGBA{B: 255, A: 255} p.Add(l) p.Legend.Add("line", l) // Save the plot to a PNG file. if err := p.Save(128*vg.Inch, 32*vg.Inch, "tps.svg"); err != nil { panic(err) } }
func (plt *plttr) save(name string) error { plt.Add(plotter.NewGrid()) if err := os.MkdirAll("plots", 0755); err != nil { return err } return plt.Save(1000, 500, filepath.Join("plots", name)) }
func NewPlot(title string) *Plot { p0, _ := plot.New() p := &Plot{ p: p0, } p.p.Title.Text = title p.p.X.Label.Text = "time" p.p.Add(plotter.NewGrid()) p.p.X.Min = 0 p.p.Y.Min = 0 p.p.Y.Padding = 0 p.p.X.Padding = 0 p.p.Y.Tick.Marker = &ticks{} 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 := 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 }
func (g *Graph) Save(filename string, w, h int) error { g.Plot.Add(plotter.NewGrid()) for _, c := range g.Curves { lpLine, lpPoints, err := plotter.NewLinePoints(c.Points) if err != nil { return err } if len(c.RGB) != 3 { return errors.New("bad RGB") } color := color.RGBA{R: c.RGB[0], G: c.RGB[1], B: c.RGB[2], A: 255} lpLine.LineStyle.Color = color lpPoints.Color = color g.Plot.Add(lpLine, lpPoints) if c.Name != "" { g.Plot.Legend.Add(c.Name, lpLine, lpPoints) } } return g.Plot.Save(vg.Length(w), vg.Length(h), filename) }
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 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 := getFloat64(r.FormValue("width"), 330) height := getFloat64(r.FormValue("height"), 250) // need different timeMarker's based on step size p.Title.Text = r.FormValue("title") p.X.Tick.Marker = NewTimeMarker(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 writerTo, err := p.WriterTo(vg.Points(width), vg.Points(height), "png") var buffer bytes.Buffer if _, err := writerTo.WriteTo(&buffer); err != nil { panic(err) } return buffer.Bytes() }
func (c *client) run() { var err error dir, err := ioutil.TempDir("", "snfusion-web-") if err != nil { log.Printf("error creating temporary directory: %v\n", err) return } defer func() { c.srv.unregister <- c c.ws.Close() c.srv = nil os.RemoveAll(dir) }() type params struct { ID int `json:"id"` NumIters int `json:"num_iters"` NumCarbons float64 `json:"num_carbons"` Seed int64 `json:"seed"` } type genReply struct { ID int `json:"id"` Stage string `json:"stage"` Err error `json:"err"` Msg string `json:"msg"` Engine sim.Engine `json:"engine"` } type plotReply struct { ID int `json:"id"` Stage string `json:"stage"` Err error `json:"err"` SVG string `json:"svg"` } type zipReply struct { ID int `json:"id"` Stage string `json:"stage"` Err error `json:"err"` Href string `json:"href"` } for { param := params{ NumIters: 100000, NumCarbons: 60, Seed: 1234, } log.Printf("waiting for simulation parameters...\n") err = websocket.JSON.Receive(c.ws, ¶m) if err != nil { log.Printf("error rcv: %v\n", err) return } id := param.ID msgbuf := new(bytes.Buffer) msg := log.New(msgbuf, "snfusion-sim: ", 0) engine := sim.Engine{ NumIters: param.NumIters, NumCarbons: param.NumCarbons, Seed: param.Seed, } engine.SetLogger(msg) log.Printf("processing... %#v\n", engine) csvbuf := new(bytes.Buffer) errc := make(chan error) ticker := time.NewTicker(1 * time.Second) go func() { errc <- engine.Run(csvbuf) ticker.Stop() }() err = <-errc if err != nil { log.Printf("error: %v\n", err) _ = websocket.JSON.Send(c.ws, genReply{ ID: id, Err: err, Engine: engine, Stage: "gen-done", Msg: msgbuf.String(), }) return } err = websocket.JSON.Send(c.ws, genReply{ ID: id, Err: err, Engine: engine, Stage: "gen-done", Msg: msgbuf.String(), }) if err != nil { log.Printf("error sending data: %v\n", err) return } csvdata := make([]byte, len(csvbuf.Bytes())) copy(csvdata, csvbuf.Bytes()) log.Printf("running post-processing...\n") r := csv.NewReader(csvbuf) r.Comma = ';' r.Comment = '#' table := make([]plotter.XYs, len(engine.Population)) for i := range table { table[i] = make(plotter.XYs, engine.NumIters+1) } for ix := 0; ix < engine.NumIters+1; ix++ { var text []string text, err = r.Read() if err != nil { break } for i := range engine.Population { table[i][ix].X = float64(ix) table[i][ix].Y = float64(atoi(text[i])) } } if err == io.EOF { err = nil } if err != nil { log.Printf("error reading data: %v\n", err) return } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = fmt.Sprintf( "Time evolution of nuclei C%v-O%v (seed=%d)", engine.NumCarbons, 100-engine.NumCarbons, engine.Seed, ) p.X.Label.Text = "Iteration number" p.Y.Label.Text = "Atomic mass of nuclei" for i, n := range engine.Population { line, err := plotter.NewLine(table[i]) if err != nil { log.Fatalf( "error adding data points for nucleus %v: %v\n", n, err, ) } line.LineStyle.Color = col(n) line.LineStyle.Width = vg.Points(1) p.Add(line) p.Legend.Add(label(n), line) } p.Add(plotter.NewGrid()) p.Legend.Top = true p.Legend.XOffs = -1 * vg.Centimeter figX := 25 * vg.Centimeter figY := figX / vg.Length(math.Phi) // Create a Canvas for writing SVG images. canvas := vgsvg.New(figX, figY) // Draw to the Canvas. p.Draw(draw.New(canvas)) outsvg := new(bytes.Buffer) _, err = canvas.WriteTo(outsvg) if err != nil { log.Printf("error svg: %v\n", err) return } err = websocket.JSON.Send(c.ws, plotReply{ ID: id, Err: err, SVG: outsvg.String(), Stage: "plot-done", }) if err != nil { log.Printf("error sending data: %v\n", err) return } pngcanvas := vgimg.PngCanvas{Canvas: vgimg.New(figX, figY)} p.Draw(draw.New(pngcanvas)) outpng := new(bytes.Buffer) _, err = pngcanvas.WriteTo(outpng) if err != nil { log.Printf("error png: %v\n", err) return } href := filepath.Join(dir, fmt.Sprintf("output-%d.zip", id)) zipf, err := os.Create(href) if err != nil { log.Printf("error creating zip file: %v\n", err) } defer zipf.Close() zipw := zip.NewWriter(zipf) defer zipw.Close() for _, file := range []struct { Name string Body []byte }{ {"output.csv", csvdata}, {"output.png", outpng.Bytes()}, } { ff, err := zipw.Create(file.Name) if err != nil { log.Printf("error creating zip content %v: %v\n", file.Name, err) return } _, err = ff.Write(file.Body) if err != nil { log.Printf("error writing zip content %v: %v\n", file.Name, err) return } } err = zipw.Close() if err != nil { log.Printf("error closing zip-writer: %v\n", err) return } err = zipf.Close() if err != nil { log.Printf("error closing zip-file: %v\n", err) return } err = websocket.JSON.Send(c.ws, zipReply{ ID: id, Err: err, Href: href, Stage: "zip-done", }) if err != nil { log.Printf("error sending zip: %v\n", err) return } log.Printf("saved report under %v\n", href) } }
func TestPersistency(t *testing.T) { // Get some random points rand.Seed(0) // The default random seed is 1. n := 15 scatterData := randomPoints(n) lineData := randomPoints(n) linePointsData := randomPoints(n) p, err := plot.New() if err != nil { t.Fatalf("error creating plot: %v\n", err) } p.Title.Text = "Plot Example" p.X.Label.Text = "X" p.Y.Label.Text = "Y" // Use a custom tick marker function that computes the default // tick marks and re-labels the major ticks with commas. p.Y.Tick.Marker = commaTicks{} // Draw a grid behind the data p.Add(plotter.NewGrid()) // Make a scatter plotter and set its style. s, err := plotter.NewScatter(scatterData) if err != nil { panic(err) } s.GlyphStyle.Color = color.RGBA{R: 255, B: 128, A: 255} // Make a line plotter and set its style. l, err := plotter.NewLine(lineData) 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} // Make a line plotter with points and set its style. lpLine, lpPoints, err := plotter.NewLinePoints(linePointsData) if err != nil { panic(err) } lpLine.Color = color.RGBA{G: 255, A: 255} lpPoints.Shape = draw.PyramidGlyph{} lpPoints.Color = color.RGBA{R: 255, A: 255} // Add the plotters to the plot, with a legend // entry for each p.Add(s, l, lpLine, lpPoints) p.Legend.Add("scatter", s) p.Legend.Add("line", l) p.Legend.Add("line points", lpLine, lpPoints) // Save the plot to a PNG file. err = p.Save(4, 4, "test-persistency.png") if err != nil { t.Fatalf("error saving to PNG: %v\n", err) } defer os.Remove("test-persistency.png") buf := new(bytes.Buffer) enc := gob.NewEncoder(buf) err = enc.Encode(p) if err != nil { t.Fatalf("error gob-encoding plot: %v\n", err) } // TODO(sbinet): impl. BinaryMarshal for plot.Plot and vg.Font // { // dec := gob.NewDecoder(buf) // var p plot.Plot // err = dec.Decode(&p) // if err != nil { // t.Fatalf("error gob-decoding plot: %v\n", err) // } // // Save the plot to a PNG file. // err = p.Save(4, 4, "test-persistency-readback.png") // if err != nil { // t.Fatalf("error saving to PNG: %v\n", err) // } // defer os.Remove("test-persistency-readback.png") // } }
func main() { ifname := flag.String("f", "output.csv", "input CSV file to analyze") ofname := flag.String("o", "output.png", "output PNG file") flag.Parse() log.SetPrefix("snfusion-plot: ") log.SetFlags(0) f, err := os.Open(*ifname) if err != nil { log.Fatalf("error opening %s: %v\n", *ifname, err) } defer f.Close() var engine sim.Engine var hdr []byte { scanner := bufio.NewScanner(f) for scanner.Scan() { data := scanner.Bytes() if !bytes.HasPrefix(data, []byte("#")) { break } if !bytes.HasPrefix(data, sim.HeaderCSV) { continue } hdr = make([]byte, len(data)-len(sim.HeaderCSV)) copy(hdr, data[len(sim.HeaderCSV):]) break } err = scanner.Err() if err == io.EOF { err = nil } if err != nil { log.Fatalf("error peeking at meta-data: %v\n", err) } if len(hdr) == 0 { log.Fatalf("could not find meta-data in file %s\n", *ifname, ) } _, err = f.Seek(0, 0) if err != nil { log.Fatalf("error rewinding input file %s: %v\n", *ifname, err, ) } } err = json.Unmarshal(hdr, &engine) if err != nil { log.Fatalf("error reading meta-data: %v\n", err) } log.Printf("plotting...\n") log.Printf("NumIters: %d\n", engine.NumIters) log.Printf("NumCarbons: %v\n", engine.NumCarbons) log.Printf("Seed: %d\n", engine.Seed) log.Printf("Nuclei: %v\n", engine.Population) r := csv.NewReader(f) r.Comma = ';' r.Comment = '#' table := make([]plotter.XYs, len(engine.Population)) for i := range table { table[i] = make(plotter.XYs, engine.NumIters+1) } for ix := 0; ix < engine.NumIters+1; ix++ { var text []string text, err = r.Read() if err != nil { break } for i := range engine.Population { table[i][ix].X = float64(ix) table[i][ix].Y = float64(atoi(text[i])) } } if err == io.EOF { err = nil } if err != nil { log.Fatalf("error reading data: %v\n", err) } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = fmt.Sprintf( "Time evolution of nuclei C%v-O%v (seed=%d)", engine.NumCarbons, 100-engine.NumCarbons, engine.Seed, ) p.X.Label.Text = "Iteration number" p.Y.Label.Text = "Atomic mass of nuclei" for i, n := range engine.Population { line, err := plotter.NewLine(table[i]) if err != nil { log.Fatalf( "error adding data points for nucleus %v: %v\n", n, err, ) } line.LineStyle.Color = col(n) line.LineStyle.Width = vg.Points(1) p.Add(line) p.Legend.Add(label(n), line) } p.Add(plotter.NewGrid()) p.Legend.Top = true p.Legend.XOffs = -1 * vg.Centimeter figX := 25 * vg.Centimeter figY := figX / vg.Length(phi) // Save the plot to a PNG file. if err := p.Save(figX, figY, *ofname); err != nil { panic(err) } }