Exemple #1
0
func plotDensity(rs1, rs2 []result, ftype string) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "Scheduler Benchmark"
	p.X.Label.Text = "Seconds"

	var filename string
	switch ftype {
	case "total":
		p.Y.Label.Text = "Number of Pods"
		err = plotutil.AddLinePoints(p,
			"Total-new", getTotal(rs1),
			"Total-old", getTotal(rs2))
		filename = "schedule-total.png"
	case "rate":
		p.Y.Label.Text = "Rate of Scheduling"
		err = plotutil.AddLinePoints(p,
			"Rate-new", getRate(rs1),
			"Rate-old", getRate(rs2))
		filename = "schedule-rate.png"
	}
	if err != nil {
		panic(err)
	}

	if err := p.Save(10*vg.Inch, 10*vg.Inch, filename); err != nil {
		panic(err)
	}

	fmt.Println("successfully plotted density graph to", filename)
}
Exemple #2
0
// Save benched results.
func save(filename string, names []string, ns [][]int64, X []int64) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "ns/sort"
	p.X.Label.Text = "N"
	p.Y.Label.Text = "ns"
	p.X.Scale = plot.LogScale{}
	p.Y.Scale = plot.LogScale{}

	data := make([]interface{}, len(names)*2)
	for i, name := range names {
		data[i*2] = name
		data[i*2+1] = points(X, ns[i])
	}

	if err := plotutil.AddLinePoints(p, data...); err != nil {
		panic(err)
	}

	if err := p.Save(10*vg.Inch, 8*vg.Inch, filename); err != nil {
		panic(err)
	}
}
Exemple #3
0
func drawEmbeddedFeaturesFilteringResults(results []testEmbeddedFeaturesFilteringResult, refF1 float64, fileName string) {
	fmt.Println("plotting ...")

	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "Adaboost: Embedded features filtering test"
	p.X.Label.Text = "Selected features count"
	p.Y.Label.Text = "F1"

	var resultPoints plotter.XYs
	for _, nextResult := range results {
		resultPoints = append(resultPoints,
			struct{ X, Y float64 }{float64(nextResult.FeaturesCount), nextResult.F1})
	}

	refPoints := make(plotter.XYs, 2)
	refPoints[0] = struct{ X, Y float64 }{float64(results[0].FeaturesCount), refF1}
	refPoints[1] = struct{ X, Y float64 }{float64(results[len(results)-1].FeaturesCount), refF1}

	err = plotutil.AddLinePoints(p,
		"F1 with selected features", resultPoints,
		"reference F1 with all features", refPoints)
	if err != nil {
		panic(err)
	}

	if err := p.Save(8*vg.Inch, 8*vg.Inch, fileName); err != nil {
		panic(err)
	}
}
Exemple #4
0
func plotSingle(df *DataFrame, name string) {
	p, err := plot.New()
	if err != nil {
		log.Fatal(err)
	}

	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"

	err = plotutil.AddLinePoints(p, name, df.PlotPoints())
	if err != nil {
		log.Fatal(err)
	}

	c := vgsvg.New(16*vg.Inch, 9*vg.Inch)

	can := draw.New(c)

	p.Draw(can)
	p.Save(16*vg.Inch/2, 9*vg.Inch/2, fmt.Sprintf("graphs/%s.png", name))
	f, err := os.Create(fmt.Sprintf("graphs/%s.svg", name))
	if err != nil {
		log.Fatal(err)
	}

	c.WriteTo(f)

}
Exemple #5
0
func createSubPlots(root *node.Node, pts plotter.XYs, depth int) {
	if pts == nil {
		pts = make(plotter.XYs, depth+1)
	}

	// fmt.Println("Depth: ", depth)
	pts[depth].X = float64(root.GetX())
	pts[depth].Y = float64(root.GetY())

	if depth == 0 {
		if root.GetX() != theGoalX || root.GetY() != theGoalY {
			return
		}

		pts[depth].X = float64(root.GetX())
		pts[depth].Y = float64(root.GetY())

		total++

		plotutil.AddLinePoints(myPlot, pts)
		return
	}

	for _, item := range root.GetChildren() {
		createSubPlots(item, pts, depth-1)
	}
}
Exemple #6
0
func PlotGraph(title string, timestamps []int64, w io.Writer) error {
	p, err := plot.New()
	if err != nil {
		return err
	}

	p.Title.Text = title
	p.X.Label.Text = "Time"
	p.Y.Label.Text = "Number of stars"
	p.Y.Min = 0

	points := make(plotter.XYs, len(timestamps))
	for i, timestamp := range timestamps {
		points[i].X = float64(timestamp)
		points[i].Y = float64(i + 1)
	}
	plotutil.AddLinePoints(p, "Stars", points)

	c := vgimg.New(4*vg.Inch, 4*vg.Inch)
	cpng := vgimg.PngCanvas{c}

	p.Draw(draw.New(cpng))

	if _, err := cpng.WriteTo(w); err != nil {
		return err
	}
	return nil
}
Exemple #7
0
// makePlots creates and saves the first of our plots showing the raw input data.
func makePlots(xys plotter.XYs) error {

	// Create a new plot.
	p, err := plot.New()
	if err != nil {
		return errors.Wrap(err, "Could not create plot object")
	}

	// Label the new plot.
	p.Title.Text = "Daily Counts of Go Repos Created"
	p.X.Label.Text = "Days from Jan. 1, 2013"
	p.Y.Label.Text = "Count"

	// Add the prepared points to the plot.
	if err = plotutil.AddLinePoints(p, "Counts", xys); err != nil {
		return errors.Wrap(err, "Could not add lines to plot")
	}

	// Save the plot to a PNG file.
	if err := p.Save(7*vg.Inch, 4*vg.Inch, "countseries.png"); err != nil {
		return errors.Wrap(err, "Could not output plot")
	}

	return nil
}
// makeRegPlots makes the second plot including the raw input data and the
// trained function.
func makeRegPlots(xys1, xys2 plotter.XYs) error {

	// Create a plot value.
	p, err := plot.New()
	if err != nil {
		return errors.Wrap(err, "Could not create plot object")
	}

	// Label the plot.
	p.Title.Text = "Daily Counts of Go Repos Created"
	p.X.Label.Text = "Days from Jan. 1, 2013"
	p.Y.Label.Text = "Count"

	// Add both sets of points, predicted and actual, to the plot.
	if err := plotutil.AddLinePoints(p, "Actual", xys1, "Predicted", xys2); err != nil {
		return errors.Wrap(err, "Could not add lines to plot")
	}

	// Save the plot.
	if err := p.Save(7*vg.Inch, 4*vg.Inch, "regression.png"); err != nil {
		return errors.Wrap(err, "Could not output plot")
	}

	return nil
}
Exemple #9
0
func plotDensity(results []densityResult) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "Density"
	p.X.Label.Text = "Seconds"
	p.Y.Label.Text = "Number of Pods"

	err = plotutil.AddLinePoints(p,
		"Created", getCreatedPoints(results),
		"Running", getRunningPoints(results),
		"Pending", getPendingPoints(results),
		"Waiting", getWaitingPoints(results))
	if err != nil {
		panic(err)
	}

	// Save the plot to a SVG file.
	if err := p.Save(10*vg.Inch, 10*vg.Inch, "density-all.svg"); err != nil {
		panic(err)
	}

	fmt.Println("successfully plotted density graph to density-all.svg")
}
Exemple #10
0
func main() {
	rand.Seed(int64(0))

	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "Plotutil example"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"

	err = plotutil.AddLinePoints(
		p,
		"First", randomPoints(15),
	)
	if err != nil {
		panic(err)
	}

	cnvs, err := vgx11.New(4*96, 4*96, "Example")
	if err != nil {
		panic(err)
	}

	p.Draw(draw.New(cnvs))
	cnvs.Paint()
	time.Sleep(5 * time.Second)

	err = plotutil.AddLinePoints(
		p,
		"Second", randomPoints(15),
		"Third", randomPoints(15),
	)
	if err != nil {
		panic(err)
	}

	p.Draw(draw.New(cnvs))
	cnvs.Paint()
	time.Sleep(10 * time.Second)

	// Save the plot to a PNG file.
	//        if err := p.Save(4, 4, "points.png"); err != nil {
	//                panic(err)
	//        }
}
Exemple #11
0
func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, "Usage: plotWav <file.wav>\n")
		os.Exit(1)
	}

	// open file
	testInfo, err := os.Stat(os.Args[1])
	checkErr(err)

	testWav, err := os.Open(os.Args[1])
	checkErr(err)

	wavReader, err := wav.NewReader(testWav, testInfo.Size())
	checkErr(err)

	// File informations
	fmt.Println(wavReader)

	// limit sample count
	sampleCnt := wavReader.GetSampleCount()
	if sampleCnt > 10000 {
		sampleCnt = 10000
	}

	// setup plotter
	p, err := plot.New()
	checkErr(err)

	p.Title.Text = "Waveplot"
	p.X.Label.Text = "t"
	p.Y.Label.Text = "Ampl"

	pts := make(plotter.XYs, sampleCnt)

	// read samples and construct points for plot
	for i := range pts {
		n, err := wavReader.ReadSample()
		if err == io.EOF {
			break
		}
		checkErr(err)

		pts[i].X = float64(i)
		pts[i].Y = float64(n)
	}

	err = plotutil.AddLinePoints(p, "", pts)
	checkErr(err)

	// construct output filename
	inputFname := path.Base(os.Args[1])
	plotFname := strings.Split(inputFname, ".")[0] + ".pdf"

	if err := p.Save(10*vg.Inch, 4*vg.Inch, plotFname); err != nil {
		panic(err)
	}
}
Exemple #12
0
func main() {
	// Connecting
	log.Println("Trying to connect to localhost:1972 ...")

	conn, err := gobci.Connect("localhost:1972")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// Getting header information
	log.Println("Requesting header data ...")

	header, err := conn.GetHeader()
	if err != nil {
		log.Fatal(err)
	}

	for {
		// Getting samples
		log.Println("Requesting sample data ...")

		var amountOfSamples uint32 = 100
		if header.NSamples < amountOfSamples {
			log.Fatal("Not enough samples avialable")
		}

		samples, err := conn.GetData(0, 0)
		if err != nil {
			log.Fatal(err)
		}

		// Visualizing the channels
		channels := make([]channelXYer, header.NChannels)
		for _, sample := range samples {
			for i := uint32(0); i < header.NChannels; i++ {
				channels[i].Values = append(channels[i].Values, sample[i])
			}
		}
		for chIndex := range channels {
			channels[chIndex].freq = header.SamplingFrequency
		}

		log.Println("Plotting samples ...")
		plt, err := plot.New()
		plotutil.AddLinePoints(plt,
			"CH0", plotter.XYer(channels[0]))
		//"CH1", plotter.XYer(channels[1]),
		//"CH2", plotter.XYer(channels[2]))

		log.Println("Saving plot to output.jpg ...")
		plt.Save(10*vg.Inch, 5*vg.Inch, "output.jpg")

	}

	log.Println("Done")
}
Exemple #13
0
func graph(P []string) {
	var XY = make(plotter.XYs, len(P))
	for i, p := range P {
		// Store the best fitness for plotting
		XY[i].X = points[p].x
		XY[i].Y = points[p].y
	}
	var p, _ = plot.New()
	p.Title.Text = "Grid TSP"
	plotutil.AddLinePoints(p, strconv.Itoa(size)+" x "+strconv.Itoa(size), XY)
	// Save the plot to a PNG file.
	if err := p.Save(5*vg.Inch, 5*vg.Inch, "grid.png"); err != nil {
		panic(err)
	}
}
Exemple #14
0
func graph(P []string) {
	var XY = make(plotter.XYs, len(P))
	for i, p := range P {
		// Store the best fitness for plotting
		XY[i].X = points[p].x
		XY[i].Y = points[p].y
	}
	var p, _ = plot.New()
	p.Title.Text = "Capitals TSP"
	plotutil.AddLinePoints(p, "Path", XY)
	// Save the plot to a PNG file.
	if err := p.Save(5*vg.Inch, 5*vg.Inch, "capitals.png"); err != nil {
		panic(err)
	}
}
Exemple #15
0
// Example_errpoints draws some error points.
func Example_errpoints() *plot.Plot {
	// Get some random data.
	n, m := 5, 10
	pts := make([]plotter.XYer, n)
	for i := range pts {
		xys := make(plotter.XYs, m)
		pts[i] = xys
		center := float64(i)
		for j := range xys {
			xys[j].X = center + (rand.Float64() - 0.5)
			xys[j].Y = center + (rand.Float64() - 0.5)
		}
	}

	plt, err := plot.New()
	if err != nil {
		panic(err)
	}

	mean95, err := plotutil.NewErrorPoints(plotutil.MeanAndConf95, pts...)
	if err != nil {
		panic(err)
	}
	medMinMax, err := plotutil.NewErrorPoints(plotutil.MedianAndMinMax, pts...)
	if err != nil {
		panic(err)
	}
	plotutil.AddLinePoints(plt,
		"mean and 95% confidence", mean95,
		"median and minimum and maximum", medMinMax)
	if err := plotutil.AddErrorBars(plt, mean95, medMinMax); err != nil {
		panic(err)
	}
	if err := plotutil.AddScatters(plt, pts[0], pts[1], pts[2], pts[3], pts[4]); err != nil {
		panic(err)
	}

	return plt
}
Exemple #16
0
func (c *Calibrate) Update(entity *ecs.Entity, dt float32) {
	if c.frameIndex != 0 {
		return
	}

	var (
		cal *CalibrateComponent
		ok  bool
	)

	if cal, ok = entity.ComponentFast(cal).(*CalibrateComponent); !ok {
		return
	}

	// Render the image again
	plt, err := plot.New()
	if err != nil {
		log.Fatal(err)
	}

	plotutil.AddLinePoints(plt,
		"CH"+strconv.Itoa(int(cal.ChannelIndex)), plotter.XYer(c.channels[cal.ChannelIndex]))
	img := image.NewRGBA(image.Rect(0, 0, 3*dpi, 3*dpi))
	canv := vgimg.NewWith(vgimg.UseImage(img))
	plt.Draw(draw.New(canv))
	bgTexture := engi.NewImageRGBA(img)

	// Give it to engi

	erender := &engi.RenderComponent{
		Display:      engi.NewRegion(engi.NewTexture(bgTexture), 0, 0, 3*dpi, 3*dpi),
		Scale:        engi.Point{1, 1},
		Transparency: 1,
		Color:        color.RGBA{255, 255, 255, 255},
	}
	erender.SetPriority(engi.HUDGround)

	entity.AddComponent(erender)
}
Exemple #17
0
func plotMulti(name string, names []string, frames []*DataFrame) {
	if len(names) != len(frames) {
		log.Fatal("wrong length for plots")
	}
	p, err := plot.New()
	if err != nil {
		log.Fatal(err)
	}

	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"

	lines := make([]interface{}, len(names)*2)
	x := 0
	for i := 0; i < len(lines); i += 2 {
		lines[i] = names[x]
		lines[i+1] = frames[x].PlotPoints()
		x += 1
	}

	err = plotutil.AddLinePoints(p, lines...)
	if err != nil {
		log.Fatal(err)
	}

	c := vgsvg.New(16*vg.Inch, 9*vg.Inch)

	can := draw.New(c)

	p.Draw(can)
	p.Save(16*vg.Inch/2, 9*vg.Inch/2, fmt.Sprintf("graphs/%s.png", name))
	f, err := os.Create(fmt.Sprintf("graphs/%s.svg", name))
	if err != nil {
		log.Fatal(err)
	}

	c.WriteTo(f)

}
Exemple #18
0
func plotRunningRateVsPods(rs []densityResult) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "RunningRate"
	p.X.Label.Text = "Number of Pods"
	p.Y.Label.Text = "Rate"

	err = plotutil.AddLinePoints(p, "RunningRate", getRunningRatePoints(rs))
	if err != nil {
		panic(err)
	}

	// Save the plot to a SVG file.
	if err := p.Save(10*vg.Inch, 10*vg.Inch, "density-running-rate.svg"); err != nil {
		panic(err)
	}

	fmt.Println("successfully plotted density graph to density-running-rate.svg")
}
Exemple #19
0
// Plot plots a simple graph.
func Plot(coll Plottable, title, xLabel, yLabel, file string) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = title
	p.X.Label.Text = xLabel
	p.Y.Label.Text = yLabel

	points := make(plotter.XYs, coll.Len())
	for i := 0; i < coll.Len(); i++ {
		a, b := coll.Pluck(i)
		points[i].X = a
		points[i].Y = b
	}

	err = plotutil.AddLinePoints(p, "", points)

	if err := p.Save(8*vg.Inch, 8*vg.Inch, file); err != nil {
		panic(err)
	}
}
Exemple #20
0
func graph(best plotter.XYs) {

	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "Fitness per iteration"
	p.X.Label.Text = "Iteration"
	p.Y.Label.Text = "Fitness"

	err = plotutil.AddLinePoints(p,
		"Best", best,
	)
	if err != nil {
		panic(err)
	}

	// Save the plot to a PNG file.
	if err := p.Save(8*vg.Inch, 8*vg.Inch, "plot.png"); err != nil {
		panic(err)
	}
}
Exemple #21
0
func main() {
	if len(os.Args) < 2 {
		fmt.Printf("%s <replay log>\n", os.Args[0])
		return
	}
	f, err := os.Open(os.Args[1])
	if err != nil {
		fmt.Printf("error opening '%s': %s\n", os.Args[1], err.Error())
		return
	}
	rdr := bufio.NewReader(f)

	// For now, "windows" are 5 minute intervals.
	qos := make(map[int64]float64) // window number -> qos value
	curWindow := int64(0)
	windowOffset := int64(0)
	metarsByWindow := make(map[int64][]string)
	for {
		buf, err := rdr.ReadString('\n')
		if err != nil {
			break
		}
		buf = strings.TrimFunc(buf, func(r rune) bool { return unicode.IsControl(r) })
		linesplit := strings.Split(buf, ",")
		if len(linesplit) < 2 { // Blank line or invalid.
			continue
		}
		if linesplit[0] == "START" { // Reset ticker, new start.
			//TODO: Support multiple sessions.
			// Reset the counters, new session.
			//			qos = make(map[uint]float64)
			//			curWindowMetars = make([]string, 0)
			//			curWindow = 0
			windowOffset = curWindow
		} else { // If it's not "START", then it's a tick count.
			i, err := strconv.ParseInt(linesplit[0], 10, 64)
			if err != nil {
				fmt.Printf("invalid tick: '%s'\n\n\n%s\n", linesplit[0], buf)
				continue
			}

			// Window number in current session.
			wnum := int64(i / (5 * 60 * 1000000000))
			//			fmt.Printf("%d\n", curWindow)
			if wnum+windowOffset != curWindow { // Switched over.
				curWindow = wnum + windowOffset
				beforeLastWindowMetars, ok := metarsByWindow[curWindow-2]
				lastWindowMetars, ok2 := metarsByWindow[curWindow-1]
				if ok && ok2 {
					//		fmt.Printf("%v\n\n\nheyy\n\n%v\n", beforeLastWindowMetars, lastWindowMetars)
					qos[curWindow-1] = metar_qos_one_period(beforeLastWindowMetars, lastWindowMetars)
					fmt.Printf("qos=%f\n", qos[curWindow-1])
					delete(metarsByWindow, curWindow-2)
					delete(metarsByWindow, curWindow-1)
				}
			}
			metarsByWindow[curWindow] = append_metars(linesplit[1], metarsByWindow[curWindow])
		}
	}

	// Make graph.
	p, err := plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "Stratux FIS-B QoS vs. Time"
	p.X.Label.Text = "5 min intervals"
	p.Y.Label.Text = "QoS"

	// Loop through an ordered list of the periods, so that the line connects the right dots.
	var keys []int
	for k := range qos {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)

	pts := make(plotter.XYs, len(qos))
	i := 0
	for _, k := range keys {
		v := qos[int64(k)]
		fmt.Printf("%d, %f\n", k, v)
		pts[i].X = float64(k)
		pts[i].Y = v
		i++
	}

	err = plotutil.AddLinePoints(p, "UAT", pts)
	if err != nil {
		panic(err)
	}
	if err := p.Save(4*vg.Inch, 4*vg.Inch, "qos.png"); err != nil {
		panic(err)
	}
}
Exemple #22
0
func main() {
	if len(os.Args) < 2 {
		fmt.Printf("%s <replay log>\n", os.Args[0])
		return
	}
	f, err := os.Open(os.Args[1])
	if err != nil {
		fmt.Printf("error opening '%s': %s\n", os.Args[1], err.Error())
		return
	}
	rdr := bufio.NewReader(f)

	// For now, "windows" are 1 minute intervals.
	ppm := make(map[int64]int64) // window number -> pkts
	curWindow := int64(0)
	windowOffset := int64(0)
	for {
		buf, err := rdr.ReadString('\n')
		if err != nil {
			break
		}
		buf = strings.TrimFunc(buf, func(r rune) bool { return unicode.IsControl(r) })
		linesplit := strings.Split(buf, ",")
		if len(linesplit) < 2 { // Blank line or invalid.
			continue
		}
		if linesplit[0] == "START" { // Reset ticker, new start.
			windowOffset = curWindow
		} else { // If it's not "START", then it's a tick count.
			i, err := strconv.ParseInt(linesplit[0], 10, 64)
			if err != nil {
				fmt.Printf("invalid tick: '%s'\n\n\n%s\n", linesplit[0], buf)
				continue
			}

			// Window number in current session.
			wnum := int64(i / (60 * 1000000000))
			//			fmt.Printf("%d\n", curWindow)
			if wnum+windowOffset != curWindow { // Switched over.
				curWindow = wnum + windowOffset
				fmt.Printf("ppm=%d\n", ppm[curWindow-1])
			}
			ppm[curWindow]++
		}
	}

	// Make graph.
	p, err := plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "Stratux PPM vs. Time"
	p.X.Label.Text = "1 min intervals"
	p.Y.Label.Text = "PPM"

	// Loop through an ordered list of the periods, so that the line connects the right dots.
	var keys []int
	for k := range ppm {
		keys = append(keys, int(k))
	}
	sort.Ints(keys)

	pts := make(plotter.XYs, len(ppm))
	i := 0
	for _, k := range keys {
		v := ppm[int64(k)]
		fmt.Printf("%d, %d\n", k, v)
		pts[i].X = float64(k)
		pts[i].Y = float64(v)
		i++
	}

	err = plotutil.AddLinePoints(p, "UAT", pts)
	if err != nil {
		panic(err)
	}
	if err := p.Save(4*vg.Inch, 4*vg.Inch, "ppm.png"); err != nil {
		panic(err)
	}
}
Exemple #23
0
func (p *promH) graphHook(w http.ResponseWriter, r *http.Request) {
	q, ok := r.URL.Query()["q"]
	if !ok || len(q) != 1 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	s, ok := r.URL.Query()["s"]
	if !ok || len(s) != 1 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	e, ok := r.URL.Query()["e"]
	if !ok || len(e) != 1 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	st, _ := strconv.Atoi(s[0])
	et, _ := strconv.Atoi(e[0])

	ctx := r.Context()

	qapi := prom.NewQueryAPI(*p.client)
	d, err := qapi.QueryRange(ctx, q[0], prom.Range{time.Unix(0, int64(st)), time.Unix(0, int64(et)), 15 * time.Second})
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	var mx model.Matrix
	switch d.Type() {
	case model.ValMatrix:
		mx = d.(model.Matrix)
		sort.Sort(mx)
	default:
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	plt, err := plot.New()
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	plt.Title.Text = q[0]
	plt.X.Tick.Marker = plot.UnixTimeTicks{Format: "Mon 15:04:05"}

	for _, ss := range mx {
		for _, sps := range mx {
			err = plotutil.AddLinePoints(plt, ss.Metric.String(), modelToPlot(sps.Values))
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				return
			}
		}
	}

	// Save the plot to a PNG file.
	var wt io.WriterTo
	if wt, err = plt.WriterTo(4*vg.Inch, 2*vg.Inch, "png"); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "image/png")
	if _, err := wt.WriteTo(w); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
}