From 6f9b667cbe28f81995418a865facea3085a8ac59 Mon Sep 17 00:00:00 2001
From: "Andrew E. Torda" <torda@zbh.uni-hamburg.de>
Date: Fri, 18 Feb 2022 09:57:35 +0100
Subject: [PATCH] Boring changes to make data types simple int's and float64's
 so that I can use the binding function in fyne. It is otherwise too painful
 to have to do lots of casts.

---
 mc_work/dorun.go          |  8 ++++----
 mc_work/mc_work.go        |  4 ++--
 mc_work/rdprm.go          | 22 +++++++---------------
 mc_work/realmain_nogfx.go |  2 +-
 ui/output_tab.go          | 29 +++++++++++++++++++----------
 ui/param_tab.go           | 30 ++++++++++++++++++++----------
 6 files changed, 53 insertions(+), 42 deletions(-)

diff --git a/mc_work/dorun.go b/mc_work/dorun.go
index 4c05d43..3a2d7ce 100644
--- a/mc_work/dorun.go
+++ b/mc_work/dorun.go
@@ -159,7 +159,7 @@ func newx(xold []float32, xT []float32, rand *rand.Rand, xDlta float64) {
 
 // printfVal is the loop to print out the function value and coordinates
 // probably for later plotting.
-func printfVal(fOut io.Writer, x []float32, n uint32, tmprtr float64, fOld float64) {
+func printfVal(fOut io.Writer, x []float32, n int, tmprtr float64, fOld float64) {
 	fmt.Fprintf(fOut, "%d,%.4g,%.5g", n, tmprtr, fOld)
 	for _, xx := range x {
 		fmt.Fprintf(fOut, ",%.2g", xx)
@@ -169,7 +169,7 @@ 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) {
+func saveStep(cprm *cprm, n int, tmprtr float64, x []float32, fTrial float64) {
 	cprm.plotnstp = append(cprm.plotnstp, float64(n)) // num steps
 	if cprm.fplotWrt != nil {                         // Function values  // function values
 		cprm.plotf = append(cprm.plotf, fTrial)
@@ -184,7 +184,7 @@ func saveStep(cprm *cprm, n uint32, tmprtr float64, x []float32, fTrial float64)
 }
 
 // nRunAdj will try to adjust the step size, given our history of accept/reject.
-func nRunAdj(mcPrm *McPrm, nstep uint32, runAcc float64, xDlta float64) float64 {
+func nRunAdj(mcPrm *McPrm, nstep int, runAcc float64, xDlta float64) float64 {
 	const step = "step"
 	if runAcc < accRateIdeal-0.01 { // acceptance rate too low
 		xDlta *= 0.9
@@ -236,7 +236,7 @@ func DoRun(mcPrm *McPrm) ([]byte, []byte, error) {
 	xDlta := mcPrm.XDlta // Adaptable step size
 	saveStep(&cprm, 0, tmprtr, x, fOld)
 
-	for n := uint32(0); n < mcPrm.NStep; n++ {
+	for n := 0; n < mcPrm.NStep; n++ {
 		var accept bool
 		nRunAcc--
 		if nRunAcc == 0 { // Do we want to try adjusting the step size ?
diff --git a/mc_work/mc_work.go b/mc_work/mc_work.go
index 476888a..b3ad67f 100644
--- a/mc_work/mc_work.go
+++ b/mc_work/mc_work.go
@@ -13,8 +13,8 @@ type McPrm struct {
 	IniTmp, FnlTmp float64   // Initial and final temperatures
 	XIni           []float32 // initial x slice
 	XDlta          float64   // change x by up to +- xDlta in trial moves
-	NStep          uint32    // number of steps
-	NRun           uint32    // number of separate runs
+	NStep          int       // number of steps
+	NRun           int       // number of separate runs
 	fOutName       string    // where we write output to
 	fPltName       string    // where we plot to (function values)
 	xPltName       string    // where we plot x trajectories to
diff --git a/mc_work/rdprm.go b/mc_work/rdprm.go
index e3b8ad2..c972a11 100644
--- a/mc_work/rdprm.go
+++ b/mc_work/rdprm.go
@@ -36,14 +36,6 @@ var cmdDflt = []struct {
 // digest digests the map, fills out our structure and sets the seed.
 func digest(prmMap map[string]string, mcPrm *McPrm) error {
 	var err error
-/*	getf := func(s string) float32 {
-		if err != nil {
-			return 0.0
-		}
-		var r float64
-		r, err = strconv.ParseFloat(s, 32)
-		return float32(r)
-	} */
 	getf64 := func(s string) float64 {
 		if err != nil {
 			return 0.0
@@ -52,13 +44,13 @@ func digest(prmMap map[string]string, mcPrm *McPrm) error {
 		r, err = strconv.ParseFloat(s, 64)
 		return r
 	}
-	getu := func(s string) uint32 {
+	geti := func(s string) int {
 		if err != nil {
 			return 0
 		}
-		var u uint64
-		u, err = strconv.ParseUint(s, 10, 32)
-		return uint32(u)
+		var u int64
+		u, err = strconv.ParseInt(s, 10, 32)
+		return int(u)
 	}
 	getx := func(s string) []float32 {
 		if err != nil {
@@ -83,13 +75,13 @@ func digest(prmMap map[string]string, mcPrm *McPrm) error {
 	mcPrm.IniTmp = getf64(prmMap["ini_temp"])
 	mcPrm.FnlTmp = getf64(prmMap["final_temp"])
 	mcPrm.XDlta = getf64(prmMap["x_delta"])
-	mcPrm.NStep = getu(prmMap["n_step"])
-	mcPrm.NRun = getu(prmMap["n_run"])
+	mcPrm.NStep = geti(prmMap["n_step"])
+	mcPrm.NRun = geti(prmMap["n_run"])
 	mcPrm.XIni = getx(prmMap["x_ini"])
 	mcPrm.fOutName = prmMap["foutname"]
 	mcPrm.fPltName = prmMap["fpltname"]
 	mcPrm.xPltName = prmMap["xpltname"]
-	seed = int64(getu(prmMap["seed"]))
+	seed = int64(geti(prmMap["seed"]))
 	if err != nil { // Only returns the first error encountered
 		return err
 	}
diff --git a/mc_work/realmain_nogfx.go b/mc_work/realmain_nogfx.go
index a63116e..8551c43 100644
--- a/mc_work/realmain_nogfx.go
+++ b/mc_work/realmain_nogfx.go
@@ -20,7 +20,7 @@ func realmain(fp io.Reader) error {
 	if err := RdPrm(fp, &mcPrm); err != nil {
 		return err
 	}
-	if _, _, err := doRun(&mcPrm); err != nil {
+	if _, _, err := DoRun(&mcPrm); err != nil {
 		return err
 	}
 
diff --git a/ui/output_tab.go b/ui/output_tab.go
index f8dbdc7..41a44f4 100644
--- a/ui/output_tab.go
+++ b/ui/output_tab.go
@@ -30,35 +30,44 @@ type workstatus struct {
 	status       status
 }
 
+// showIniTab is just a card to be shown before we have any calculations
+// done.
 func showIniTab(cntr *fyne.Container) {
 	cntr.Add(widget.NewCard("No results yet", "go back to the input", nil))
 }
 
-func showCalcTab(cntr *fyne.Container) {
-	for _, c := range cntr.Objects {
-		cntr.Remove(c)
+// emptyContainer gets rid of any old contents
+func  emptyContainer (cntr *fyne.Container)  {
+	for _, o := range cntr.Objects {
+		cntr.Remove(o)
 	}
+}
+
+// showCalcTab is shown while calculating. Have to check if the refresh()
+// is actually necessary.
+func showCalcTab(cntr *fyne.Container) {
+	emptyContainer (cntr)
 	cntr.Add(widget.NewCard("calculating", "busy", nil))
 	cntr.Refresh()
 }
 
 // showResultsTab show the two plots
-
 func showResultsTab(cntr *fyne.Container, fdata, xdata []byte) {
-	for _, c := range cntr.Objects {
-		cntr.Remove(c)
-	}
+	emptyContainer (cntr)
+	pictureSize := fyne.Size{Width: 500, Height: 250}
 	fImage := canvas.NewImageFromReader(bytes.NewReader(fdata), "func.png")
 	fImage.FillMode = canvas.ImageFillContain
-	fImage.SetMinSize( fyne.Size{500, 300})
+	fImage.SetMinSize( pictureSize)
 	xImage := canvas.NewImageFromReader(bytes.NewReader(xdata), "xdata.png")
 	xImage.FillMode = canvas.ImageFillContain
-	xImage.SetMinSize( fyne.Size{500, 300})
+	xImage.SetMinSize( pictureSize)
 	content := container.NewGridWithRows(2, fImage, xImage)
 	cntr.Add(content)
-
 }
 
+// outputTab is run as a background process. After showing the initial
+// screen, it sits and waits on notifications. When it gets one,
+// it redraws its tab.
 func outputTab(chn chan workstatus, cntr *fyne.Container) {
 	showIniTab(cntr)
 	for s := range chn {
diff --git a/ui/param_tab.go b/ui/param_tab.go
index 504f283..c38f127 100644
--- a/ui/param_tab.go
+++ b/ui/param_tab.go
@@ -50,17 +50,19 @@ func s2f32(s string) ([]float32, error) {
 	return x, nil
 }
 
+// validateXini checks if we can convert a string to a slice of float32's.
+// Unfortunately, fyne calls this function every time the cursor is moved
+// in the field. I think this is a little bug on their part.
 func validateXini(s string) error {
-	fmt.Println("validation called")
 	_, err := s2f32(s)
 	return err
 }
 
-// paramScreen sets up a screen full of parameters we can adjust. It returns a the screen
-// and a function to be called to refresh it if parameters are changed elsewhere, like
-// reading from a file.
+// paramScreen sets up a screen full of parameters we can adjust.
+// It returns the screen and a function to be called to refresh it.
+// This is necessary, since there is a button to read parameters from
+// a file, which means all the values should be updated.
 func paramScreen(mcPrm *mcwork.McPrm) (*fyne.Container, func()) {
-
 	iniTmp := binding.BindFloat(&mcPrm.IniTmp)
 	iniTmpEntry := widget.NewEntryWithData(binding.FloatToString(iniTmp))
 	iniTmpLabel := widget.NewLabel("initial temp")
@@ -87,21 +89,30 @@ func paramScreen(mcPrm *mcwork.McPrm) (*fyne.Container, func()) {
 	xIniEntry.Validator = validateXini
 	xIniLabel := widget.NewLabel("X ini")
 
+	nStepBnd := binding.BindInt(&mcPrm.NStep)
+	nStepEntry := widget.NewEntryWithData(binding.IntToString(nStepBnd))
+	nStepLabel := widget.NewLabel("num steps")
+	
 	r := container.NewGridWithColumns(2,
 		iniTmpLabel, iniTmpEntry,
 		fnlTmpLabel, fnlTmpEntry,
 		xDltaLabel, xDltaEntry,
-		xIniLabel, xIniEntry)
+		xIniLabel, xIniEntry,
+		nStepEntry, nStepLabel)
 	refreshPScreen := func() {
 		iniTmp.Reload()
 		fnlTmp.Reload()
 		xDlta.Reload()
 		xIniEntry.SetText(fslicestrng(mcPrm.XIni))
+		nStepBnd.Reload()
 	}
 	return r, refreshPScreen
 }
 
-func checkok(c *fyne.Container, parent fyne.Window) error {
+
+// checkOk does a last pass over all fields and calls any validators
+// it can find. A run can only be started if everything seems to be OK.
+func checkOk(c *fyne.Container, parent fyne.Window) error {
 	for _, obj := range c.Objects {
 		if ent, ok := obj.(*widget.Entry); ok {
 			if err := ent.Validate(); err != nil {
@@ -133,7 +144,7 @@ func rdwork(mcPrm *mcwork.McPrm, parent fyne.Window, refreshme func()) error {
 		} else {
 			fmt.Println("I think mcprm is", mcPrm)
 			refreshme()
-			dialog.NewInformation("OK confirmed", "read file, no errors", parent).Show()
+			dialog.NewInformation("OK", "read file, no errors", parent).Show()
 			return
 		}
 	}
@@ -160,11 +171,10 @@ func inputTab(mcPrm *mcwork.McPrm, parent fyne.Window, chn chan workstatus) (*fy
 		}
 	}
 	startrun := func() {
-		if err := checkok(paramBinding, parent); err != nil {
+		if err := checkOk(paramBinding, parent); err != nil {
 			dialog.NewError(err, parent).Show()
 			return
 		}
-		fmt.Println("I want to run with paremeters", mcPrm)
 		chn <- workstatus{status: calculating}
 		if fdata, xdata, err := mcwork.DoRun(mcPrm); err != nil {
 			dialog.NewError(err, parent).Show()
-- 
GitLab