From 8dedd91fcb1dca313bca6177080531f4eb19509a Mon Sep 17 00:00:00 2001 From: "Andrew E. Torda" <torda@zbh.uni-hamburg.de> Date: Sat, 5 Feb 2022 17:28:53 +0100 Subject: [PATCH] Changed the plot functions. We now have a basic plot from which the two real plots start and then append their specific information. --- Makefile | 3 + mc_work/ToDo | 5 +- mc_work/dorun.go | 4 +- mc_work/plot.go | 137 +++++++++++++++++++----------------------- mc_work/set_suffix.go | 2 + ui/scrnplt.go | 9 ++- 6 files changed, 78 insertions(+), 82 deletions(-) diff --git a/Makefile b/Makefile index 008059b..923682c 100644 --- a/Makefile +++ b/Makefile @@ -8,3 +8,6 @@ clean: go clean rm -rf */*_delme.* rm -rf */test_tmp* + rm -rf /tmp/go-build[0-9]* + rm -rf /tmp/go.*.mod + rm -rf /tmp/go.*.sum diff --git a/mc_work/ToDo b/mc_work/ToDo index 7d7a839..c5fe2bc 100644 --- a/mc_work/ToDo +++ b/mc_work/ToDo @@ -6,4 +6,7 @@ In dorun.go * Change the tests so all files are written to a temporary directory -Note.. Benchmarking suggests that most of the time is spent in Ackley function, and, to be exact, in the cosine and exp() function. \ No newline at end of file +Note.. Benchmarking suggests that most of the time is spent in Ackley function, and, to be exact, in the cosine and exp() function. + +In the plottin functions, +Put a secondary axis on the X trajectory or check out multiplots so that the two plots line up with each other. diff --git a/mc_work/dorun.go b/mc_work/dorun.go index 6c5a1cd..fa9b100 100644 --- a/mc_work/dorun.go +++ b/mc_work/dorun.go @@ -268,7 +268,7 @@ 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 } @@ -285,7 +285,7 @@ func doRun(mcPrm *mcPrm) error { fmt.Println ("xBuf for plotting is this big", len(xBuf.Bytes())) xdata = xBuf.Bytes() } - breaker(fdata, xdata) + nothing (fdata, xdata) // ui.Scrnplt(fdata, xdata) } diff --git a/mc_work/plot.go b/mc_work/plot.go index ee33a9a..7e8b1a9 100644 --- a/mc_work/plot.go +++ b/mc_work/plot.go @@ -22,6 +22,11 @@ import ( "gitlab.rrz.uni-hamburg.de/Bae5157/axticks" ) +const ( + chrtWdth = 800 + chrtHt = 400 +) + // maketicks gives reasonable default tick locations func maketicks(axisDscrpt axticks.AxisDscrpt) []chart.Tick { xmin, xmax, delta, prcsn := axisDscrpt.Xmin, axisDscrpt.Xmax, axisDscrpt.Delta, axisDscrpt.Prcsn @@ -41,22 +46,6 @@ func maketicks(axisDscrpt axticks.AxisDscrpt) []chart.Tick { return t } -// maketicks this version works, but usually leaves you wanting one tick more. -/*func alt_maketicks(axisDscrpt axticks.AxisDscrpt, prcsn int) []chart.Tick { - xmin, xmax, delta, prcsn := axisDscrpt.Xmin, axisDscrpt.Xmax, axisDscrpt.Delta, axisDscrpt.Prcsn - var t []chart.Tick - const fstr = "%.*f" - xv, xl := xmin, fmt.Sprintf(fstr, prcsn, xmin) - if xmin > 3.56 && xmin < 3.58 { - fmt.Println (axisDscrpt) - } - for ; xv <= xmax; xv, xl = xv+delta, fmt.Sprintf("%.*f", prcsn, xv) { - t = append(t, chart.Tick {Value: xv, Label: xl}) - } - - return t -}*/ - // range2 just lets us append methods to a range/continuousrange structure type range2 struct { chart.ContinuousRange @@ -77,27 +66,14 @@ func (rng *range2) GetTicks(r chart.Renderer, cs chart.Style, vf chart.ValueForm } } -// plotfWrt writes out a plot of function values to the given -// io.Writer. It used to ask for a string. -func plotfWrt(cprm *cprm) error { - if cprm.fplotWrt == nil { - return nil - } - xdata := cprm.plotnstp // We just unpack for readability - ydata := cprm.plotf - tmprtrData := cprm.plotTmprtr - +// plotbase returns a chart that serves as the basis for both the function +// values and the X trajectories. This lets us set up the x-axis once and +// put the temperature on both plots so they come out the same size. +func plotbase(cprm *cprm) *chart.Chart { xaxis := chart.XAxis{ Name: "step", Range: &range2{}, } - - fvalAxis := chart.YAxis{ - Name: "cost (arb units)", - NameStyle: chart.Style{TextRotationDegrees: 360}, // Zero does not work - AxisType: chart.YAxisSecondary, - Range: &range2{}, - } var tmprtrAxis chart.YAxis if cprm.coolme { // If we are not cooling, we do not plot tmprtrAxis = chart.YAxis{ // the temperature axis. @@ -109,39 +85,54 @@ func plotfWrt(cprm *cprm) error { tmprtrAxis = chart.YAxis{} // to mess up the scaling on the tmprtrAxis.Style = chart.Hidden() // other axis } - + xdata := cprm.plotnstp + leftAxis := chart.YAxis{ + NameStyle: chart.Style{TextRotationDegrees: 360}, // Zero does not work + AxisType: chart.YAxisSecondary, + Range: &range2{}, + } graph := chart.Chart{ - Width: 800, - Title: "cost function", + Width: chrtWdth, Height: chrtHt, Series: []chart.Series{ + chart.ContinuousSeries{ + Name: "temperature", + XValues: xdata, + YValues: cprm.plotTmprtr, + }, chart.ContinuousSeries{ // The function values - Name: "cost", + Name: "specify me", YAxis: chart.YAxisSecondary, XValues: xdata, - YValues: ydata, Style: chart.Style{ - StrokeWidth: 5, + StrokeWidth: 4, DotWidth: 0, }, }, - chart.ContinuousSeries{ - Name: "temperature", - XValues: xdata, - YValues: tmprtrData, - }, }, YAxis: tmprtrAxis, - YAxisSecondary: fvalAxis, + YAxisSecondary: leftAxis, XAxis: xaxis, Background: chart.Style{ - Padding: chart.Box{ - Left: 50, - Right: 75, - }, + Padding: chart.Box{Left: 75, Right: 75}, FillColor: drawing.ColorTransparent, }, } + return &graph +} + +// plotfWrt plots the function values and temperature to an io.Writer that +// it finds in the cprm structure. It might be writing to a file or a buffer. +func plotfWrt(cprm *cprm) error { + graph := plotbase(cprm) + graph.YAxisSecondary.Name = "cost (arb units)" + if funcSeries, ok := graph.Series[1].(chart.ContinuousSeries); ok { + funcSeries.Name = "cost" + funcSeries.YValues = cprm.plotf + graph.Series[1] = funcSeries + } else { + panic("prog bug type assertion function plot") + } if err := graph.Render(chart.PNG, cprm.fplotWrt); err != nil { return fmt.Errorf("Render: %w", err) @@ -151,16 +142,21 @@ func plotfWrt(cprm *cprm) error { } // plotxWrt -// 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. +// For each dimension, allocate space. The X's are stored in a single +// array, so here we allocate an array of arrays for each dimension and +// copy the elements. We then take the graph object and toss out the first +// continuousSeries. Then, we make a series of ContinousSeries, appending +// each in turn to the []graph.Series. func plotxWrt(cprm *cprm, ndim int) error { - if cprm.xplotWrt == nil { return nil } + if cprm.xplotWrt == nil { + return nil + } + graph := plotbase(cprm) type f64 []float64 len_used := len(cprm.plotnstp) xdata := make([]f64, ndim) for i := 0; i < ndim; i++ { - xdata[i] = make([]float64, len_used) + xdata[i] = make([]float64, len_used, len_used) } var n int for i := 0; i < len_used; i++ { @@ -169,29 +165,18 @@ func plotxWrt(cprm *cprm, ndim int) error { n++ } } - series := make([]chart.Series, ndim) - for i := 0; i < ndim; i++ { - series[i] = chart.ContinuousSeries{ - Name: fmt.Sprintf("dimension %d", i), - XValues: cprm.plotnstp, - YValues: xdata[i], + graph.Title = fmt.Sprintf("X trajectories %d dimension", ndim) + graph.YAxisSecondary.Name = "X coord" + if baseSeries, ok := graph.Series[1].(chart.ContinuousSeries); ok { + graph.Series = graph.Series[:1] + for i := 0; i < ndim; i++ { + tmp := baseSeries + tmp.Name = fmt.Sprintf("dim %d", i) + tmp.YValues = xdata[i] + graph.Series = append(graph.Series, tmp) } - } - graph := chart.Chart{ - Title: fmt.Sprintf("X trajectories %d dimension", ndim), - XAxis: chart.XAxis{Name: "step", Range: &range2{}}, - YAxis: chart.YAxis{ - Name: "x coord", - Range: &range2{}, - AxisType: chart.YAxisSecondary, - NameStyle: chart.Style{TextRotationDegrees: 360}, - }, - Series: series, - Background: chart.Style{ - Padding: chart.Box{ - Left: 75, - }, - }, + } else { + panic("program bug, type assertion on y axis xtrajectories") } if err := graph.Render(chart.PNG, cprm.xplotWrt); err != nil { return fmt.Errorf("plotting X trajectories: %w", err) diff --git a/mc_work/set_suffix.go b/mc_work/set_suffix.go index 81fc9be..c0bf8d0 100644 --- a/mc_work/set_suffix.go +++ b/mc_work/set_suffix.go @@ -48,3 +48,5 @@ func removeQuotes(s string) string { } return s } + +func nothing (...interface{}){} diff --git a/ui/scrnplt.go b/ui/scrnplt.go index ed51887..72a8bcf 100644 --- a/ui/scrnplt.go +++ b/ui/scrnplt.go @@ -17,7 +17,10 @@ import ( func breaker(...interface{}) {} func Scrnplt(fdata []byte, xdata []byte) { - fmt.Println("scrnplt says fbuf size", len(fdata), "first few bytes:", string(fdata[:10])) + if len(fdata) == 0 && len (xdata) == 0 { return } + +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") @@ -31,8 +34,8 @@ func Scrnplt(fdata []byte, xdata []byte) { text2 := canvas.NewText("There", green) //top, bottom, left, right // content = container.NewMax(image, text1) - content := container.NewHSplit(fImage, xImage) - content.SetOffset(0.95) + content := container.NewVSplit(fImage, xImage) + content.SetOffset(0.50) breaker(text1, content, text2) w.Resize(fyne.NewSize(500, 320)) w.SetContent(content) -- GitLab