From 3c8678a8d3cdd2f8d819132723600951cded8d20 Mon Sep 17 00:00:00 2001 From: surtur Date: Mon, 18 Jul 2022 22:36:47 +0200 Subject: [PATCH] go,tmpl: plot mean values --- algo/algo.go | 16 +++++++++++---- algo/plot.go | 45 ++++++++++++++++++++++++++--------------- report/pic.go | 6 ++++-- report/pics.tmpl | 25 ++++++++++++++--------- report/report_base.tmpl | 6 ++++-- 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/algo/algo.go b/algo/algo.go index 9f0e7ae..7a9bbbc 100644 --- a/algo/algo.go +++ b/algo/algo.go @@ -41,24 +41,28 @@ func DoRandomSearch(wg *sync.WaitGroup, m *sync.Mutex) { } pCh := make(chan report.PicList, funcCount*len(bench.Dimensions)) + pMeanCh := make(chan report.PicList, funcCount*len(bench.Dimensions)) for i := range algoStats { - go plotAllDims(algoStats[i], "plot", ".svg", pCh) + go plotAllDims(algoStats[i], "plot", ".svg", pCh, pMeanCh) } pLs := []report.PicList{} + pLsMean := []report.PicList{} for range algoStats { pL := <-pCh + pLMean := <-pMeanCh pLs = append(pLs, pL) + pLsMean = append(pLsMean, pLMean) } algoName := "Random Search" // protect access to shared data. m.Lock() - report.SavePicsToFile(pLs, algoName) + report.SavePicsToFile(pLs, pLsMean, algoName) stats.SaveTable(algoName, algoStats) m.Unlock() @@ -90,24 +94,28 @@ func DoStochasticHillClimbing(wg *sync.WaitGroup, m *sync.Mutex) { } pCh := make(chan report.PicList, funcCount*len(bench.Dimensions)) + pMeanCh := make(chan report.PicList, funcCount*len(bench.Dimensions)) for _, algoStat := range algoStats { - go plotAllDims(algoStat, "plot", ".svg", pCh) + go plotAllDims(algoStat, "plot", ".svg", pCh, pMeanCh) } pLs := []report.PicList{} + pLsMean := []report.PicList{} for range algoStats { pL := <-pCh + pLMean := <-pMeanCh pLs = append(pLs, pL) + pLsMean = append(pLsMean, pLMean) } algoName := "Stochastic Hill Climbing" // protect access to shared data. m.Lock() - report.SavePicsToFile(pLs, algoName) + report.SavePicsToFile(pLs, pLsMean, algoName) stats.SaveTable(algoName, algoStats) m.Unlock() diff --git a/algo/plot.go b/algo/plot.go index 0143c00..6b30949 100644 --- a/algo/plot.go +++ b/algo/plot.go @@ -20,13 +20,13 @@ import ( const preferredFontStyle = "Mono" -func plotMeanVals(vals []stats.BenchRound, fes int) *plot.Plot { +func plotMeanVals(vals []stats.BenchRound, title string, fes int) *plot.Plot { plotter.DefaultFont.Typeface = preferredFontStyle - plotter.DefaultLineStyle.Width = vg.Points(1.5) + plotter.DefaultLineStyle.Width = vg.Points(2.0) p := plot.New() - p.Title.Text = "Mean" + p.Title.Text = "Mean - " + title p.X.Label.Text = "Generations" p.X.Label.TextStyle.Font.Variant = preferredFontStyle @@ -37,10 +37,10 @@ func plotMeanVals(vals []stats.BenchRound, fes int) *plot.Plot { p.Y.Label.TextStyle.Font.Weight = 1 // Medium p.Y.Tick.Label.Font.Variant = preferredFontStyle - p.Title.TextStyle.Font.Size = 11.5 + p.Title.TextStyle.Font.Size = 14.5 p.Title.TextStyle.Font.Variant = "Sans" p.Title.TextStyle.Font.Weight = 2 // SemiBold - p.Title.Padding = 5 * vg.Millimeter + p.Title.Padding = 3 * vg.Millimeter // get mean vals. meanVals := stats.GetMeanVals(vals, fes) @@ -74,7 +74,7 @@ func plotMeanVals(vals []stats.BenchRound, fes int) *plot.Plot { // violating gocognit 30, TODO(me): still split this up. // nolint: gocognit -func plotAllDims(algoStats []stats.Stats, fPrefix, fExt string, ch chan report.PicList) { +func plotAllDims(algoStats []stats.Stats, fPrefix, fExt string, ch chan report.PicList, chMean chan report.PicList) { start := time.Now() picsDir := report.GetPicsDir() @@ -87,10 +87,13 @@ func plotAllDims(algoStats []stats.Stats, fPrefix, fExt string, ch chan report.P pL := report.NewPicList() pics := make([]report.Pic, 0) + pLMean := report.NewPicList() + picsMean := make([]report.Pic, 0) // since the algoStats only contains results of a single algo, it's safe to // set the value like this. pL.Algo = algoStats[0].Algo + pLMean.Algo = algoStats[0].Algo pWidth := 13 * vg.Centimeter pHeight := 13 * vg.Centimeter @@ -102,15 +105,16 @@ func plotAllDims(algoStats []stats.Stats, fPrefix, fExt string, ch chan report.P p := plot.New() pic := report.NewPic() - p.Title.Text = s.Algo + ", D=" + fmt.Sprint(s.Dimens) + - ", func=" + s.BenchFuncStats[0].BenchName + - ", G=" + fmt.Sprint(s.Generations) + - ", I=" + fmt.Sprint(s.Iterations) + p.Title.Text = "D: " + fmt.Sprint(s.Dimens) + + ", G: " + fmt.Sprint(s.Generations) + + ", I: " + fmt.Sprint(s.Iterations) + // pic.Caption = p.Title.Text + pic.Caption = "" - pic.Caption = p.Title.Text // since a single stat slice of algoStats only contains results of a // single bench func, it's safe to set the value like this. pL.Bench = s.BenchFuncStats[0].BenchName + pLMean.Bench = s.BenchFuncStats[0].BenchName p.X.Label.Text = "Generations" p.X.Label.TextStyle.Font.Variant = preferredFontStyle @@ -121,10 +125,10 @@ func plotAllDims(algoStats []stats.Stats, fPrefix, fExt string, ch chan report.P p.Y.Label.TextStyle.Font.Weight = 1 // Medium p.Y.Tick.Label.Font.Variant = preferredFontStyle - p.Title.TextStyle.Font.Size = 11.5 + p.Title.TextStyle.Font.Size = 14.5 p.Title.TextStyle.Font.Variant = "Sans" p.Title.TextStyle.Font.Weight = 2 // SemiBold - p.Title.Padding = 5 * vg.Millimeter + p.Title.Padding = 3 * vg.Millimeter for _, dim := range s.BenchFuncStats { // infinite thanks to this SO comment for the interface "hack": @@ -174,14 +178,18 @@ func plotAllDims(algoStats []stats.Stats, fPrefix, fExt string, ch chan report.P // NEVER EVER ATTEMPT TO INITIALISE THIS WITH `pic`! picMean := report.NewPic() - picMean.Caption = "D:~" + fmt.Sprint(s.Dimens) + ", G:~" + - fmt.Sprint(s.Generations) + ", I:~" + fmt.Sprint(s.Iterations) + meanTitle := "D: " + fmt.Sprint(s.Dimens) + ", G: " + + fmt.Sprint(s.Generations) + ", I: " + fmt.Sprint(s.Iterations) + // picMean.Caption = "D:~" + fmt.Sprint(s.Dimens) + ", G:~" + + // fmt.Sprint(s.Generations) + ", I:~" + fmt.Sprint(s.Iterations) + picMean.Caption = "" // set pic file path (later used in tmpl generation) pic.FilePath = filename picMean.FilePath = filenameMean - pMean := plotMeanVals(dim.Solution, s.Generations) + // get the *mean* plot. + pMean := plotMeanVals(dim.Solution, meanTitle, s.Generations) elapsed := time.Since(start) info := "saving img to file: " + filename + "(-Mean)" + fExt + @@ -213,10 +221,15 @@ func plotAllDims(algoStats []stats.Stats, fPrefix, fExt string, ch chan report.P ); err != nil { panic(err) } + + // save mean pic. + picsMean = append(picsMean, *picMean) } } pL.Pics = pics + pLMean.Pics = picsMean ch <- *pL + chMean <- *pLMean } diff --git a/report/pic.go b/report/pic.go index ed1beb6..fd7ea63 100644 --- a/report/pic.go +++ b/report/pic.go @@ -42,12 +42,12 @@ func NewPicList() *PicList { // SavePicsToFile saves each pic list for all bench funcs of a specified algo // to a file. -func SavePicsToFile(pls []PicList, algoName string) { +func SavePicsToFile(pls, plsMean []PicList, algoName string) { var paths []string ptf := picTexFiles{Algo: algoName} - for _, p := range pls { + for i, p := range pls { safeName := util.SanitiseFName(p.Algo + "-" + p.Bench) texPicsFile := GetTexDir() + "pics-" + safeName + ".tex" tmplPics := template.New("pics") @@ -73,11 +73,13 @@ func SavePicsToFile(pls []PicList, algoName string) { Algo string Bench string Pics []Pic + PicsMean []Pic Timestamp time.Time }{ Algo: p.Algo, Bench: p.Bench, Pics: p.Pics, + PicsMean: plsMean[i].Pics, Timestamp: time.Now(), }) diff --git a/report/pics.tmpl b/report/pics.tmpl index 487d2fa..427aa78 100644 --- a/report/pics.tmpl +++ b/report/pics.tmpl @@ -8,16 +8,23 @@ % project homepage: https://git.dotya.ml/wanderer/math-optim/ \subsubsection{ {{- printf "%s - %s" .Algo .Bench -}} } - -{{- range $i, $v := .Pics }} - -\begin{figure}[!hbt] - \includesvg[width=0.30\textwidth]{ {{- printf "{%s}" $v.FilePath -}} } - +\begin{figure}[h!] \centering - \caption{ {{- $v.Caption -}} } +{{- range $i, $v := .Pics }} + \begin{subfigure}{0.30\textwidth} + % note: this accomodates 3 plots a row comfortably..should the requirements + % change, this would have to be reworked. + {\includesvg[scale=0.45]{ {{- printf "%s" $v.FilePath -}} }} + \end{subfigure} + \hfill +{{- end -}} +{{ range $k, $w := .PicsMean }} + \begin{subfigure}{0.30\textwidth} + \vspace{2em} + {\includesvg[scale=0.45]{ {{- printf "%s" $w.FilePath -}} }} + \end{subfigure} + \hfill +{{- end }} \end{figure} -{{- end }} - % vim: ft=gotexttmpl.tex ts=2 sts=2 sw=2 bs=2 expandtab diff --git a/report/report_base.tmpl b/report/report_base.tmpl index 0ae42ea..1b158ba 100644 --- a/report/report_base.tmpl +++ b/report/report_base.tmpl @@ -16,9 +16,11 @@ \usepackage{graphicx} \usepackage{textcomp} \usepackage{hyperref} -\usepackage{etoolbox} -\usepackage{longtable} +\usepackage{subcaption} % for subcaption +\usepackage{sansmath} +\sansmath \usepackage{svg} +\svgsetup{inkscapelatex=false} % this is important to not have jumbled plot labels \usepackage{meta} \usepackage[affil-it]{authblk}