Select Git revision
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
plot.go 3.00 KiB
// 31 Dec 2021
// This is for doing some plotting. For the moment, this is in the ackwork package,
// but maybe it should be in its own. It definitely goes in its own file, since
// it is tied to one of the chart packages I have tried out.
package ackwork
import (
"fmt"
"io"
"math"
"path/filepath"
"github.com/wcharczuk/go-chart/v2"
"github.com/wcharczuk/go-chart/v2/drawing"
"gitlab.rrz.uni-hamburg.de/Bae5157/axticks"
)
// makepngName takes a name. If it does not end in png, append .png to the name.
// If it ends in something else, replace the ending with png.
// We have stalinistically decided that we will only write png output.
// svg is nicer, but the files can become silly big.
func makepngName(fname string) string {
const dotpng = ".png"
ext := filepath.Ext(fname)
switch ext {
case "":
return fname + dotpng
case ".png":
fallthrough
case ".PNG":
return fname
default:
return fname[0:len(fname)-len(ext)] + dotpng
}
return "hello"
}
// maketicks gives reasonable default tick locations
func maketicks(axisDscrpt axticks.AxisDscrpt, prcsn int) []chart.Tick {
xmin, delta, prcsn := axisDscrpt.Xmin, axisDscrpt.Delta, axisDscrpt.Prcsn
rnge := axisDscrpt.Xmax - axisDscrpt.Xmin
ntick := int(math.Round((rnge / delta) + 1))
t := make([]chart.Tick, ntick)
const fstr = "%.*f"
t[0].Value, t[0].Label = xmin, fmt.Sprintf(fstr, prcsn, xmin)
for i := 1; i < ntick; i++ {
t[i].Value = t[i-1].Value + delta
t[i].Label = fmt.Sprintf("%.*f", prcsn, t[i].Value)
}
return t
}
// plotWrt writes out a plot to the given io.writercloser and
// closes the file when finished.
func plotWrite(xdata, ydata []float64, plotOut io.WriteCloser, plotme bool) error {
if !plotme {
return nil
}
var xAxisDscrpt, yAxisDscrpt axticks.AxisDscrpt
var err error
if yAxisDscrpt, err = axticks.Tickpos(ydata); err != nil {
return fmt.Errorf("plot making y axis: %w", err)
}
if xAxisDscrpt, err = axticks.Tickpos(xdata); err != nil {
return fmt.Errorf("plot making x axis: %w", err)
}
xaxis := chart.XAxis{
Name: "step",
Range: &chart.ContinuousRange{
Min: xAxisDscrpt.Xmin,
Max: xAxisDscrpt.Xmax,
},
Ticks: maketicks(xAxisDscrpt, yAxisDscrpt.Prcsn),
}
yaxis := chart.YAxis{
Name: "cost (arb units)",
NameStyle: chart.Style{
TextRotationDegrees: 360}, // Zero does not work
TickStyle: chart.Style{
TextRotationDegrees: 0,
},
AxisType: chart.YAxisSecondary,
Range: &chart.ContinuousRange{
Min: yAxisDscrpt.Xmin,
Max: yAxisDscrpt.Xmax,
},
Ticks: maketicks(yAxisDscrpt, yAxisDscrpt.Prcsn),
}
graph := chart.Chart{
Width: 800,
Series: []chart.Series{
chart.ContinuousSeries{
XValues: xdata,
YValues: ydata,
Style: chart.Style{
StrokeWidth: 5,
DotWidth: 0,
},
},
},
YAxis: yaxis,
XAxis: xaxis,
Background: chart.Style{
Padding: chart.Box{
Left: 75,
Right: 25,
},
FillColor: drawing.ColorTransparent,
},
}
if err := graph.Render(chart.PNG, plotOut); err != nil {
return fmt.Errorf("While plotting %w", err)
}
return nil
}