From 02e7e64ec3833e9b4d038b108c10aa686aa4b273 Mon Sep 17 00:00:00 2001
From: "Andrew E. Torda" <torda@zbh.uni-hamburg.de>
Date: Wed, 2 Feb 2022 18:49:03 +0100
Subject: [PATCH] Now makes two plots, function values and X trajectory

---
 Makefile         | 10 +++++++++
 README           |  5 ++++-
 example_input    |  4 ++++
 go.mod           |  1 -
 mc_work/ToDo     |  2 ++
 mc_work/dorun.go | 58 +++++++++++++++++++++++++++++++-----------------
 mc_work/plot.go  | 16 ++++---------
 ui/scrnplt.go    | 27 ++++++++++++++--------
 8 files changed, 80 insertions(+), 43 deletions(-)
 create mode 100644 Makefile
 create mode 100644 example_input

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..008059b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+# Use the normal go build system for everything, but we want to automate some simple
+# commands.
+
+all:
+	go build ./...
+
+clean:
+	go clean
+	rm -rf */*_delme.*
+	rm -rf */test_tmp*
diff --git a/README b/README
index 4903deb..9d3e1c2 100644
--- a/README
+++ b/README
@@ -1,3 +1,6 @@
 When playing with the axis ticks,
 replace gitlab.rrz.uni-hamburg.de/Bae5157/axticks => ../axticks
-in the go.mod file
\ No newline at end of file
+in the go.mod file
+
+A chart from go-chart in png format can be displayed by fyne.
+A chart in svg format leads to parse errors.
\ No newline at end of file
diff --git a/example_input b/example_input
new file mode 100644
index 0000000..a87508e
--- /dev/null
+++ b/example_input
@@ -0,0 +1,4 @@
+ini_temp 0.18
+final_temp 0.01
+x_ini 7,1,7
+n_step 100000
diff --git a/go.mod b/go.mod
index d3a0ec0..47a7d07 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,6 @@ module example.com/ackley_mc
 go 1.16
 
 require (
-	fyne.io/fyne v1.4.3
 	fyne.io/fyne/v2 v2.1.2
 	github.com/wcharczuk/go-chart/v2 v2.1.0
 	gitlab.rrz.uni-hamburg.de/Bae5157/axticks v0.0.0-20220120103412-d663ebb46145
diff --git a/mc_work/ToDo b/mc_work/ToDo
index 3438e9d..7d7a839 100644
--- a/mc_work/ToDo
+++ b/mc_work/ToDo
@@ -1,5 +1,7 @@
 In dorun.go
 
+* do we have the random number seed as a settable parameter ?
+
 * make the csv files optional
 
 * Change the tests so all files are written to a temporary directory
diff --git a/mc_work/dorun.go b/mc_work/dorun.go
index 4b9cfd5..6c5a1cd 100644
--- a/mc_work/dorun.go
+++ b/mc_work/dorun.go
@@ -12,7 +12,7 @@ import (
 	"sync"
 
 	"example.com/ackley_mc/ackley"
-	//	"example.com/ackley_mc/ui"
+//	"example.com/ackley_mc/ui"
 )
 
 const (
@@ -32,7 +32,7 @@ func getSeed() int64 {
 	seedLocker.Unlock()
 	return r
 }
-
+func breaker (...interface{}) {}
 type withBytes interface {
 	Bytes() []byte
 }
@@ -49,7 +49,7 @@ type cprm struct { // parameters calculated from input
 	plotXtrj   []float32      // for plotting trajectories
 	coolme     bool           // Cooling ? or just constant temperature ?
 	fplotWrt   io.Writer      // Where to write the plot of function values
-	xplotme    bool           // Are we plotting X trajectories
+	xplotWrt   io.Writer      // Where to write the plot of x trajectories
 }
 
 // isNotSane checks for obviously silly parameters
@@ -89,7 +89,7 @@ func setupRun(mcPrm *mcPrm, cprm *cprm) error {
 		coolrate *= math.Log(fnlTmp / iniTmp)
 		cprm.coolMult = math.Exp(-coolrate)
 	}
-	if mcPrm.fOutName != "" { // We are going to write to a file
+	if mcPrm.fOutName != "" { // We are going to write text, .csv
 		if mcPrm.fOutName, err = setSuffix(mcPrm.fOutName, ".csv"); err != nil {
 			return err
 		}
@@ -100,8 +100,8 @@ func setupRun(mcPrm *mcPrm, cprm *cprm) error {
 		cprm.doTxtFval = true // other parts of code can see that we are writing to file
 	}
 
-	if mcPrm.fPltName != "" { // Then we are writing to a file
-		if mcPrm.fPltName, err = setSuffix(mcPrm.fPltName, ".svg"); err != nil {
+	if mcPrm.fPltName != "" { // Function value plot to file
+		if mcPrm.fPltName, err = setSuffix(mcPrm.fPltName, ".png"); err != nil {
 			return fmt.Errorf("plot filename: %w", err)
 		}
 		if cprm.fplotWrt, err = os.Create(mcPrm.fPltName); err != nil {
@@ -119,13 +119,17 @@ func setupRun(mcPrm *mcPrm, cprm *cprm) error {
 	}
 
 	if mcPrm.xPltName != "" {
-		if mcPrm.xPltName, err = setSuffix(mcPrm.xPltName, ".svg"); err != nil {
+		if mcPrm.xPltName, err = setSuffix(mcPrm.xPltName, ".png"); err != nil {
 			return fmt.Errorf("plot filename: %w", err)
 		}
-		cprm.xplotme = true
-		n_dim := len(mcPrm.xIni)
-		cprm.plotXtrj = make([]float32, 0, int(n_alloc)*n_dim)
+		if cprm.xplotWrt, err = os.Create(mcPrm.xPltName); err != nil {
+			return err
+		}
+	} else { // Write to buffer, to plot on screen
+		var w bytes.Buffer
+		cprm.xplotWrt = &w // I think we can remove the preceding line
 	}
+	cprm.plotXtrj = make([]float32, 0, int(n_alloc)*len(mcPrm.xIni))
 	if err = isNotSane(mcPrm); err != nil {
 		return err
 	}
@@ -166,14 +170,12 @@ func printfVal(fOut io.Writer, x []float32, n uint32, tmprtr float64, fOld float
 // saveStep is called when we accept a change. It writes or saves for
 // later plotting.
 func saveStep(cprm *cprm, n uint32, tmprtr float64, x []float32, fTrial float64) {
-	if cprm.fplotWrt != nil || cprm.xplotme {
-		cprm.plotnstp = append(cprm.plotnstp, float64(n))
-	}
-	if cprm.fplotWrt != nil { // Function values
+	cprm.plotnstp = append(cprm.plotnstp, float64(n)) // num steps
+	if cprm.fplotWrt != nil { // Function values  // function values
 		cprm.plotf = append(cprm.plotf, fTrial)
 		cprm.plotTmprtr = append(cprm.plotTmprtr, tmprtr)
 	}
-	if cprm.xplotme { // The trajectory
+	if cprm.xplotWrt != nil { // The trajectory
 		cprm.plotXtrj = append(cprm.plotXtrj, x...)
 	}
 	if cprm.doTxtFval {
@@ -266,16 +268,32 @@ func doRun(mcPrm *mcPrm) error {
 		saveStep(&cprm, mcPrm.nStep, tmprtr, x, fOld)
 	}
 	defer fmt.Println("n accepted:", nAcc, "of", mcPrm.nStep+1)
+	breaker()
 	if err := plotfWrt(&cprm); err != nil {
 		return err
 	}
-
-	if bBuf, ok := cprm.fplotWrt.(withBytes); ok  {
-		fmt.Println("bBuf for plotting is this big", len(bBuf.Bytes()))
-	}
-	if err := plotxWrt(&cprm, mcPrm.xPltName, len(mcPrm.xIni)); err != nil {
+    if err := plotxWrt (&cprm, len(mcPrm.xIni)); err != nil {
 		return err
 	}
+	{
+		var fdata, xdata []byte
+		if funcBuf, ok := cprm.fplotWrt.(withBytes); ok  {
+			fmt.Println("funcBuf for plotting is this big", len(funcBuf.Bytes()))
+			fdata = funcBuf.Bytes()
+		}
+		if xBuf, ok := cprm.xplotWrt.(withBytes); ok {
+			fmt.Println ("xBuf for plotting is this big", len(xBuf.Bytes()))
+			xdata = xBuf.Bytes()
+		}
+		breaker(fdata, xdata)
+//		ui.Scrnplt(fdata, xdata)
+	}
+
+
+		
+/*	if bBuf,  := plotxWrt(&cprm, mcPrm.xPltName, len(mcPrm.xIni)); err != nil {
+		return err
+	} */
 
 	return nil
 }
diff --git a/mc_work/plot.go b/mc_work/plot.go
index 0263060..ee33a9a 100644
--- a/mc_work/plot.go
+++ b/mc_work/plot.go
@@ -143,7 +143,7 @@ func plotfWrt(cprm *cprm) error {
 		},
 	}
 
-	if err := graph.Render(chart.SVG, cprm.fplotWrt); err != nil {
+	if err := graph.Render(chart.PNG, cprm.fplotWrt); err != nil {
 		return fmt.Errorf("Render: %w", err)
 	}
 
@@ -154,11 +154,8 @@ func plotfWrt(cprm *cprm) error {
 // For each dimension, allocate space. Copy elements over from the long array.
 // Then call the plotter on each series in turn. I think I have to make a
 // slice of continuous series and then add them into the chart structure.
-func plotxWrt(cprm *cprm, xPltName string, ndim int) error {
-	if !cprm.xplotme {
-		return nil
-	}
-
+func plotxWrt(cprm *cprm, ndim int) error {
+	if cprm.xplotWrt == nil { return nil }
 	type f64 []float64
 	len_used := len(cprm.plotnstp)
 	xdata := make([]f64, ndim)
@@ -196,12 +193,7 @@ func plotxWrt(cprm *cprm, xPltName string, ndim int) error {
 			},
 		},
 	}
-	xPlt, err := os.Create(xPltName)
-	if err != nil {
-		return err
-	}
-	defer xPlt.Close()
-	if err := graph.Render(chart.SVG, xPlt); err != nil {
+	if err := graph.Render(chart.PNG, cprm.xplotWrt); err != nil {
 		return fmt.Errorf("plotting X trajectories: %w", err)
 	}
 	return nil
diff --git a/ui/scrnplt.go b/ui/scrnplt.go
index 470aa0e..ed51887 100644
--- a/ui/scrnplt.go
+++ b/ui/scrnplt.go
@@ -8,24 +8,33 @@ import (
 	"bytes"
 	"fmt"
 	"image/color" // need this for the green ?
-		"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2"
 	"fyne.io/fyne/v2/app"
 	"fyne.io/fyne/v2/canvas"
 	"fyne.io/fyne/v2/container"
+//	"fyne.io/fyne/v2/layout"
 )
 
-func Scrnplt (b []byte) {
-	fmt.Println ("scrnplt says buf size", len(b), "first few bytes:", string(b[:10]))
+func breaker(...interface{}) {}
+func Scrnplt(fdata []byte, xdata []byte) {
+	fmt.Println("scrnplt says fbuf size", len(fdata), "first few bytes:", string(fdata[:10]))
+	fmt.Println("scrnplt says xbuf size", len(xdata), "first few bytes:", string(xdata[:10]))
 	a := app.New()
 	w := a.NewWindow("container")
-	image := canvas.NewImageFromReader(bytes.NewReader(b), "boo.svg")
+	fImage := canvas.NewImageFromReader(bytes.NewReader(fdata), "func.png")
+	fImage.FillMode = canvas.ImageFillContain
+	xImage := canvas.NewImageFromReader(bytes.NewReader(xdata), "xdata.png")
+	xImage.FillMode = canvas.ImageFillContain
+
 	green := color.NRGBA{R: 0, G: 180, B: 0, A: 255}
-	text1 := canvas.NewText("Hello", green); print(text1)
+	text1 := canvas.NewText("Hello", green)
 	text2 := canvas.NewText("There", green)
-	text2.Move(fyne.NewPos(20, 20))
-	content := container.NewWithoutLayout( image) // no more text 1, text2
-	// content := container.New(layout.NewGridLayout(2), text1, text2)
-
+//top, bottom, left, right
+//	content = container.NewMax(image, text1)
+	content := container.NewHSplit(fImage, xImage)
+	content.SetOffset(0.95)
+	breaker(text1, content, text2)
+	w.Resize(fyne.NewSize(500, 320))
 	w.SetContent(content)
 
 	w.ShowAndRun()
-- 
GitLab