func AddLinePoints(plt *plot.Plot, vs ...interface{}) error {
	var ps []plot.Plotter
	type item struct {
		name  string
		value [2]plot.Thumbnailer
	}
	var items []item
	name := ""
	var i int
	for _, v := range vs {
		switch t := v.(type) {
		case string:
			name = t
		case plotter.XYer:
			l, s, err := plotter.NewLinePoints(t)
			if err != nil {
				return err
			}
			l.Color = Color(i)
			l.Dashes = Dashes(i)
			s.Color = Color(i)
			s.Shape = Shape(i)
			i++
			ps = append(ps, l, s)
			if name != "" {
				items = append(items, item{name: name, value: [2]plot.Thumbnailer{l, s}})
				name = ""
			}
		default:
			panic(fmt.Sprintf("plotutil: AddLinePoints handles strings and plotter.XYers, got %T", t))
		}
	}
	plt.Add(ps...)
	for _, item := range items {
		v := item.value[:]
		plt.Legend.Add(item.name, v[0], v[1])
	}
	return nil
}
AddLinePoints adds Line and Scatter plotters to a
plot.  The variadic arguments must be either strings
or plotter.XYers.  Each plotter.XYer is added to
the plot using the next color, dashes, and glyph
shape via the Color, Dashes, and Shape functions.
If a plotter.XYer is immediately preceeded by
a string then a legend entry is added to the plot
using the string as the name.

If an error occurs then none of the plotters are added
to the plot, and the error is returned.
package plotutil
import (
	"errors"
	"fmt"
	"gonum.org/v1/plot"
	"gonum.org/v1/plot/plotter"
	"gonum.org/v1/plot/vg"
)
type combineXYs struct{ xs, ys plotter.Valuer }
func (c combineXYs) Len() int                    { return c.xs.Len() }
func (c combineXYs) XY(i int) (float64, float64) { return c.xs.Value(i), c.ys.Value(i) }
type item struct {
	name  string
	value plot.Thumbnailer
}
func AddStackedAreaPlots(plt *plot.Plot, xs plotter.Valuer, vs ...interface{}) error {
	var ps []plot.Plotter
	var names []item
	name := ""
	var i int
	for _, v := range vs {
		switch t := v.(type) {
		case string:
			name = t
		case plotter.Valuer:
			if xs.Len() != t.Len() {
				return errors.New("X/Y length mismatch")
			}
			l, err := plotter.NewLine(combineXYs{xs: xs, ys: t})
			if err != nil {
				return err
			}
			l.LineStyle.Width = vg.Points(0)
			color := Color(i)
			i++
			l.FillColor = color
			ps = append(ps, l)
			if name != "" {
				names = append(names, item{name: name, value: l})
				name = ""
			}
		default:
			panic(fmt.Sprintf("plotutil: AddStackedAreaPlots handles strings and plotter.Valuers, got %T", t))
		}
	}
	plt.Add(ps...)
	for _, v := range names {
		plt.Legend.Add(v.name, v.value)
	}
	return nil
}
func AddBoxPlots(plt *plot.Plot, width vg.Length, vs ...interface{}) error {
	var ps []plot.Plotter
	var names []string
	name := ""
	for _, v := range vs {
		switch t := v.(type) {
		case string:
			name = t
		case plotter.Valuer:
			b, err := plotter.NewBoxPlot(width, float64(len(names)), t)
			if err != nil {
				return err
			}
			ps = append(ps, b)
			names = append(names, name)
			name = ""
		default:
			panic(fmt.Sprintf("plotutil: AddBoxPlots handles strings and plotter.Valuers, got %T", t))
		}
	}
	plt.Add(ps...)
	plt.NominalX(names...)
	return nil
}
func AddScatters(plt *plot.Plot, vs ...interface{}) error {
	var ps []plot.Plotter
	var items []item
	name := ""
	var i int
	for _, v := range vs {
		switch t := v.(type) {
		case string:
			name = t
		case plotter.XYer:
			s, err := plotter.NewScatter(t)
			if err != nil {
				return err
			}
			s.Color = Color(i)
			s.Shape = Shape(i)
			i++
			ps = append(ps, s)
			if name != "" {
				items = append(items, item{name: name, value: s})
				name = ""
			}
		default:
			panic(fmt.Sprintf("plotutil: AddScatters handles strings and plotter.XYers, got %T", t))
		}
	}
	plt.Add(ps...)
	for _, v := range items {
		plt.Legend.Add(v.name, v.value)
	}
	return nil
}
func AddLines(plt *plot.Plot, vs ...interface{}) error {
	var ps []plot.Plotter
	var items []item
	name := ""
	var i int
	for _, v := range vs {
		switch t := v.(type) {
		case string:
			name = t
		case plotter.XYer:
			l, err := plotter.NewLine(t)
			if err != nil {
				return err
			}
			l.Color = Color(i)
			l.Dashes = Dashes(i)
			i++
			ps = append(ps, l)
			if name != "" {
				items = append(items, item{name: name, value: l})
				name = ""
			}
		case *plotter.Function:
			t.Color = Color(i)
			t.Dashes = Dashes(i)
			i++
			ps = append(ps, t)
			if name != "" {
				items = append(items, item{name: name, value: t})
				name = ""
			}
		default:
			panic(fmt.Sprintf("plotutil: AddLines handles strings, plotter.XYers and *plotter.Function, got %T", t))
		}
	}
	plt.Add(ps...)
	for _, v := range items {
		plt.Legend.Add(v.name, v.value)
	}
	return nil
}