예제 #1
0
파일: main.go 프로젝트: kc-cylon5/gogui
// 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 := must(plotter.NewLine(pts)).(*plotter.Line)
	scatter := must(plotter.NewScatter(pts)).(*plotter.Scatter)
	p.Add(line, scatter)

	pts = plotter.XYs{{1, 0}, {0.75, 0}, {0.75, 0.75}}
	line = must(plotter.NewLine(pts)).(*plotter.Line)
	scatter = must(plotter.NewScatter(pts)).(*plotter.Scatter)
	p.Add(line, scatter)

	pts = plotter.XYs{{0.5, 0.5}, {1, 0.5}}
	line = must(plotter.NewLine(pts)).(*plotter.Line)
	scatter = must(plotter.NewScatter(pts)).(*plotter.Scatter)
	p.Add(line, scatter)

	return p
}
예제 #2
0
// 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)
	}
}
예제 #3
0
// AddScatters adds Scatter plotters to a plot.
// The variadic arguments must be either strings
// or plotter.XYers.  Each plotter.XYer is added to
// the plot using the next color, and glyph shape
// via the Color and Shape functions. If a
// plotter.XYer is immediately preceeded by
// a string then a legend entry is added to the plot
// using the string as the name.
//
// If an error occurs then none of the plotters are added
// to the plot, and the error is returned.
func AddScatters(plt *plot.Plot, vs ...interface{}) error {
	var ps []plot.Plotter
	names := make(map[*plotter.Scatter]string)
	name := ""
	var i int
	for _, v := range vs {
		switch t := v.(type) {
		case string:
			name = t

		case plotter.XYer:
			s, err := plotter.NewScatter(t)
			if err != nil {
				return err
			}
			s.Color = Color(i)
			s.Shape = Shape(i)
			i++
			ps = append(ps, s)
			if name != "" {
				names[s] = name
				name = ""
			}

		default:
			panic(fmt.Sprintf("AddScatters handles strings and plotter.XYers, got %T", t))
		}
	}
	plt.Add(ps...)
	for p, n := range names {
		plt.Legend.Add(n, p)
	}
	return nil
}
예제 #4
0
func TestIssue179(t *testing.T) {
	scatter, err := plotter.NewScatter(plotter.XYs{{1, 1}, {0, 1}, {0, 0}})
	if err != nil {
		log.Fatal(err)
	}
	p, err := plot.New()
	if err != nil {
		log.Fatal(err)
	}
	p.Add(scatter)
	p.HideAxes()

	c := vgimg.JpegCanvas{Canvas: vgimg.New(5.08*vg.Centimeter, 5.08*vg.Centimeter)}
	p.Draw(draw.New(c))
	b := bytes.NewBuffer([]byte{})
	if _, err = c.WriteTo(b); err != nil {
		t.Error(err)
	}

	f, err := os.Open(filepath.Join("testdata", "issue179.jpg"))
	if err != nil {
		t.Error(err)
	}
	defer f.Close()

	want, err := ioutil.ReadAll(f)
	if err != nil {
		t.Error(err)
	}
	if !bytes.Equal(b.Bytes(), want) {
		t.Error("Image mismatch")
	}
}
예제 #5
0
파일: main.go 프로젝트: kc-cylon5/gogui
// Example_errBars draws points and error bars.
func Example_errBars() *plot.Plot {

	type errPoints struct {
		plotter.XYs
		plotter.YErrors
		plotter.XErrors
	}

	rand.Seed(int64(0))
	n := 15
	data := errPoints{
		XYs:     randomPoints(n),
		YErrors: plotter.YErrors(randomError(n)),
		XErrors: plotter.XErrors(randomError(n)),
	}

	p, err := plot.New()
	if err != nil {
		panic(err)
	}
	scatter := must(plotter.NewScatter(data)).(*plotter.Scatter)
	scatter.Shape = draw.CrossGlyph{}
	xerrs, err := plotter.NewXErrorBars(data)
	if err != nil {
		panic(err)
	}
	yerrs, err := plotter.NewYErrorBars(data)
	if err != nil {
		panic(err)
	}
	p.Add(scatter, xerrs, yerrs)
	p.Add(plotter.NewGlyphBoxes())

	return p
}
예제 #6
0
파일: plot.go 프로젝트: 6br/goem
// Plot plots only 2-dimensional cluster and points
func (em EM) Plot(fileid int, directory string) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "EM-Algorithm Plot"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	bs, err := plotter.NewBubbles(em.clusterTriples(), vg.Points(30), vg.Points(80))
	if err != nil {
		panic(err)
	}
	bs.Color = color.RGBA{R: 255, B: 255, A: 255}
	p.Add(bs)

	ss, err := plotter.NewScatter(em.dataTriples())
	if err != nil {
		panic(err)
	}
	ss.Color = color.Black
	p.Add(ss)

	filename := directory + fmt.Sprintf("%03d", fileid) + ".png"
	if err := p.Save(10*vg.Inch, 10*vg.Inch, filename); err != nil {
		panic(err)
	}
}
예제 #7
0
func TestKCmeansSynthetic(t *testing.T) {
	clusters, spacing := 7, 4.0
	data, points := make([][]float64, clusters*POINTS), make(plotter.XYs, clusters*POINTS)

	for c := 0; c < clusters; c++ {
		//A, B, C, D := rand.NormFloat64(), rand.NormFloat64(), rand.NormFloat64(), rand.NormFloat64()
		//x, y := spacing * rand.NormFloat64(), spacing * rand.NormFloat64()
		for p := 0; p < POINTS; p++ {
			point := make([]float64, 2)
			point[0], point[1] = spacing*float64(c)+rand.NormFloat64(), spacing*float64(c)+rand.NormFloat64()
			//point[0], point[1] = x + rand.NormFloat64(), y + rand.NormFloat64()
			//point[0], point[1] = A * point[0] + B * point[1], C * point[0] + D * point[1]
			index := POINTS*c + p
			data[index], points[index].X, points[index].Y = point, point[0], point[1]
		}
	}

	threshold := 1000
	_, means, err := KCmeans(data, 30, EuclideanDistance, threshold, 10)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("means = %v\n", len(means))
	centerPoints := make(plotter.XYs, len(means))
	for ii := range means {
		centerPoints[ii].X, centerPoints[ii].Y = means[ii][0], means[ii][1]
	}

	p, err := plot.New()
	p.Title.Text = "Clusters"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	scatter, err := plotter.NewScatter(points)
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(2)
	p.Add(scatter)
	scatter, err = plotter.NewScatter(centerPoints)
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(2)
	scatter.Color = color.RGBA{0, 0, 255, 255}
	p.Add(scatter)
	if err := p.Save(8, 8, "synthetic.png"); err != nil {
		panic(err)
	}
}
예제 #8
0
func TestIssue179(t *testing.T) {
	t.Skip("github.com/BurntSushi/xgbutil#30 issue not fixed")

	if !hasX11() {
		t.Skip("no X11 environment")
	}

	scatter, err := plotter.NewScatter(plotter.XYs{{1, 1}, {0, 1}, {0, 0}})
	if err != nil {
		t.Fatalf("error: %v\n", err)
	}
	p, err := plot.New()
	if err != nil {
		t.Fatalf("error: %v\n", err)
	}
	p.Add(scatter)
	p.HideAxes()

	c, err := New(5.08*vg.Centimeter, 5.08*vg.Centimeter, "test issue179")
	if err != nil {
		t.Fatalf("error: %v\n", err)
	}

	p.Draw(draw.New(c))
	b := bytes.NewBuffer([]byte{})
	err = jpeg.Encode(b, c.ximg, nil)
	if err != nil {
		t.Error(err)
	}

	f, err := os.Open(filepath.Join("..", "vgimg", "testdata", "issue179.jpg"))
	if err != nil {
		t.Error(err)
	}
	defer f.Close()

	want, err := ioutil.ReadAll(f)
	if err != nil {
		t.Error(err)
	}
	if !bytes.Equal(b.Bytes(), want) {
		t.Error("Image mismatch")
	}
}
예제 #9
0
파일: main.go 프로젝트: kc-cylon5/gogui
// 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
}
예제 #10
0
파일: plots.go 프로젝트: manell/benchmark
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)
	}
}
예제 #11
0
// http://cs.joensuu.fi/sipu/datasets/
func TestKCmeansA1(t *testing.T) {
	filePath, err := filepath.Abs("data/a1.txt")
	if err != nil {
		log.Fatal(err)
	}
	content, err := ioutil.ReadFile(filePath)
	if err != nil {
		log.Fatal(err)
	}

	lines := strings.Split(string(content), "\n")
	lines = lines[:len(lines)-1]
	data, points := make([][]float64, len(lines)), make(plotter.XYs, len(lines))
	for ii, line := range lines {
		line = strings.Trim(line, " ")
		vector := strings.Split(line, " ")
		floatVector := make([]float64, 2)
		vv := 0
		for jj := range vector {
			if vector[jj] == "" || vector[jj] == " " {
				continue
			}
			value, err := strconv.ParseFloat(vector[jj], 64)
			if err != nil {
				log.Fatal(err)
			}
			if value != 0 {
				floatVector[vv] = value
				vv++
			}
		}
		data[ii], points[ii].X, points[ii].Y = floatVector, floatVector[0], floatVector[1]
	}

	threshold := 1000
	_, means, err := KCmeans(data, 30, EuclideanDistance, threshold, 10)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("means = %v\n", len(means))

	p, err := plot.New()
	p.Title.Text = "A1 Clusters"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	scatter, err := plotter.NewScatter(points)
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(2)
	p.Add(scatter)
	_, means, err = Kmeans(data, 20, EuclideanDistance, threshold)
	if err != nil {
		log.Fatal(err)
	}
	centerPoints := make(plotter.XYs, len(means))
	for ii := range means {
		centerPoints[ii].X, centerPoints[ii].Y = means[ii][0], means[ii][1]
	}
	scatter, err = plotter.NewScatter(centerPoints)
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(2)
	scatter.Color = color.RGBA{0, 0, 255, 255}
	p.Add(scatter)
	if err := p.Save(8, 8, "a1.png"); err != nil {
		panic(err)
	}
}
예제 #12
0
func GetEllipse(piece byte, startX int, startY int, goalX int, goalY int, maxLength int) {
	start := GenerateMoveBoard(piece, startX, startY)
	result := matrix.Sum(start, GenerateMoveBoard(piece, goalX, goalY))

	theGoalX = goalX
	theGoalY = goalY

	// Get lowest #
	min := float64(maxLength)
	// min := float64(100)
	// for i := 0; i < 8; i++ {
	// 	for j := 0; j < 8; j++ {
	// 		if result.Get(i, j) < min {
	// 			min = result.Get(i, j)
	// 		}
	// 	}
	// }

	// Remove unnecessary #s
	for i := 0; i < 8; i++ {
		for j := 0; j < 8; j++ {
			if result.Get(i, j) > min {
				result.Set(i, j, 0)
			}
		}
	}

	var root *node.Node
	root = new(node.Node)
	root.SetX(startX)
	root.SetY(startY)
	root.SetStep(0)

	// fmt.Println("Ellipse: \n", result)

	nodes := make([][]*node.Node, maxLength+1, maxLength+1)
	nodes[0] = make([]*node.Node, 0, 20)
	nodes[0] = append(nodes[0], root)

	for i := 1; i <= maxLength; i++ {
		// fmt.Println("i: ", i)
		nodes[i] = make([]*node.Node, 0, 20)
		for _, baseNode := range nodes[i-1] {
			// TODO: Improve append to check for duplicate nodes
			nodes[i] = append(nodes[i], getNextLocations(piece, start, result, baseNode)...)
		}
	}

	// fmt.Println(root)

	myPlot, _ = plot.New()
	// Create the board
	createBoard(myPlot)

	createSubPlots(root, nil, maxLength)

	myPlot.X.Min = .5
	myPlot.X.Max = 8.5
	myPlot.Y.Min = .5
	myPlot.Y.Max = 8.5

	// Add the start and end points
	pts := make(plotter.XYs, 2)
	pts[0].X = float64(startX)
	pts[0].Y = float64(startY)
	pts[1].X = float64(goalX)
	pts[1].Y = float64(goalY)
	s, _ := plotter.NewScatter(pts)
	s.GlyphStyle.Color = color.RGBA{R: 0, B: 0, A: 255}
	myPlot.Add(s)

	myPlot.Title.Text = "Total: " + strconv.Itoa(total)

	myPlot.Save(8*vg.Inch, 8*vg.Inch, "results.png")
}
예제 #13
0
func KCMmeans(rawData [][]float64, k int, distanceFunction DistanceFunction, threshold int) ([]int, []Observation, error) {
	var minClusteredData []ClusteredObservation
	var means []Observation
	var err error
	max, trace := int64(0), make([]float64, k)
	for clusters := 1; clusters <= k; clusters++ {
		data := make([]ClusteredObservation, len(rawData))
		for ii, jj := range rawData {
			data[ii].Observation = jj
		}
		seeds := seed(data, clusters, distanceFunction)
		clusteredData, _ := kmeans(data, seeds, distanceFunction, threshold)

		counts := make([]int, clusters)
		for _, jj := range clusteredData {
			counts[jj.ClusterNumber]++
		}

		input := &bytes.Buffer{}
		for c := 0; c < clusters; c++ {
			/*err := binary.Write(input, binary.LittleEndian, rand.Float64())
			if err != nil {
				panic(err)
			}*/

			err := binary.Write(input, binary.LittleEndian, int64(counts[c]))
			if err != nil {
				panic(err)
			}

			for _, jj := range seeds[c] {
				err = binary.Write(input, binary.LittleEndian, jj)
				if err != nil {
					panic(err)
				}
			}

			for _, j := range clusteredData {
				if j.ClusterNumber == c {
					for ii, jj := range j.Observation {
						err = binary.Write(input, binary.LittleEndian, jj-seeds[c][ii])
						if err != nil {
							panic(err)
						}
					}
				}
			}
		}

		in, output := make(chan []byte, 1), &bytes.Buffer{}
		in <- input.Bytes()
		close(in)
		compress.BijectiveBurrowsWheelerCoder(in).MoveToFrontRunLengthCoder().AdaptiveCoder().Code(output)

		/*output := &bytes.Buffer{}
		writer := lzma.NewWriterLevel(output, lzma.BestCompression)
		writer.Write(input.Bytes())
		writer.Close()*/

		complexity := int64(output.Len())
		trace[clusters-1] = float64(complexity)
		fmt.Printf("%v %v\n", clusters, complexity)
		if complexity > max {
			max, minClusteredData, means = complexity, clusteredData, make([]Observation, len(seeds))
			for ii := range seeds {
				means[ii] = make([]float64, len(seeds[ii]))
				for jj := range seeds[ii] {
					means[ii][jj] = seeds[ii][jj]
				}
			}
		}
	}

	f := fft.FFTReal(trace)
	points, phase, complex := make(plotter.XYs, len(f)-1), make(plotter.XYs, len(f)-1), make(plotter.XYs, len(f))
	for i, j := range f[1:] {
		points[i].X, points[i].Y = float64(i), cmplx.Abs(j)
		phase[i].X, phase[i].Y = float64(i), cmplx.Phase(j)
		complex[i].X, complex[i].Y = real(j), imag(j)
	}

	p, err := plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "FFT Real"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	scatter, err := plotter.NewScatter(points)
	if err != nil {
		panic(err)
	}
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(1)
	p.Add(scatter)
	if err := p.Save(8, 8, "fft_real.png"); err != nil {
		panic(err)
	}

	p, err = plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "FFT Phase"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	scatter, err = plotter.NewScatter(phase)
	if err != nil {
		panic(err)
	}
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(1)
	scatter.Color = color.RGBA{0, 0, 255, 255}
	p.Add(scatter)
	if err := p.Save(8, 8, "fft_phase.png"); err != nil {
		panic(err)
	}

	p, err = plot.New()
	if err != nil {
		panic(err)
	}
	p.Title.Text = "FFT Complex"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"
	scatter, err = plotter.NewScatter(complex)
	if err != nil {
		panic(err)
	}
	scatter.Shape = draw.CircleGlyph{}
	scatter.Radius = vg.Points(1)
	scatter.Color = color.RGBA{0, 0, 255, 255}
	p.Add(scatter)
	if err := p.Save(8, 8, "fft_complex.png"); err != nil {
		panic(err)
	}

	labels := make([]int, len(minClusteredData))
	for ii, jj := range minClusteredData {
		labels[ii] = jj.ClusterNumber
	}
	return labels, means, err
}
예제 #14
0
파일: gob_test.go 프로젝트: zzn01/plot
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")
	// }

}