func categoricalBarChart() {
	dumper := NewDumper("xbar2", 3, 2, 400, 300)
	defer dumper.Close()
	x := []float64{0, 1, 2, 3}
	europe := []float64{10, 15, 25, 20}
	asia := []float64{15, 30, 10, 20}
	africa := []float64{20, 5, 5, 5}
	blue := chart.Style{Symbol: '#', LineColor: color.NRGBA{0x00, 0x00, 0xff, 0xff}, LineWidth: 4, FillColor: color.NRGBA{0x40, 0x40, 0xff, 0xff}}
	green := chart.Style{Symbol: 'x', LineColor: color.NRGBA{0x00, 0xaa, 0x00, 0xff}, LineWidth: 4, FillColor: color.NRGBA{0x40, 0xff, 0x40, 0xff}}
	pink := chart.Style{Symbol: '0', LineColor: color.NRGBA{0x99, 0x00, 0x99, 0xff}, LineWidth: 4, FillColor: color.NRGBA{0xaa, 0x60, 0xaa, 0xff}}
	red := chart.Style{Symbol: '%', LineColor: color.NRGBA{0xcc, 0x00, 0x00, 0xff}, LineWidth: 4, FillColor: color.NRGBA{0xff, 0x40, 0x40, 0xff}}
	c := chart.BarChart{Title: "Income"}
	c.XRange.Category = []string{"none", "low", "average", "high"}
	c.ShowVal = 1
	c.AddDataPair("Europe", x, europe, blue)
	dumper.Plot(&c)
	c.ShowVal = 2
	c.AddDataPair("Asia", x, asia, pink)
	dumper.Plot(&c)
	c.ShowVal = 3
	c.AddDataPair("Africa", x, africa, green)
	dumper.Plot(&c)
	c.Stacked = true
	c.ShowVal = 1
	dumper.Plot(&c)
	c.ShowVal = 2
	dumper.Plot(&c)
	c.ShowVal = 3
	dumper.Plot(&c)
	dumper2 := NewDumper("xbar3", 3, 2, 400, 300)
	defer dumper2.Close()
	c = chart.BarChart{Title: "Income"}
	c.XRange.Category = []string{"none", "low", "average", "high"}
	c.Key.Hide = true
	c.YRange.ShowZero = true
	c.ShowVal = 3
	c.AddDataPair("Europe", x, []float64{-10, -15, -20, -5}, blue)
	dumper2.Plot(&c)
	c.AddDataPair("Asia", x, []float64{-15, -10, -5, -20}, pink)
	dumper2.Plot(&c)
	c.Stacked = true
	dumper2.Plot(&c)
	c = chart.BarChart{Title: "Income"}
	c.XRange.Category = []string{"none", "low", "average", "high"}
	c.Key.Hide = true
	c.YRange.ShowZero = true
	c.ShowVal = 3
	c.AddDataPair("Europe", x, []float64{-10, 15, -20, 5}, blue)
	dumper2.Plot(&c)
	c.AddDataPair("Asia", x, []float64{-15, 10, -5, 20}, pink)
	dumper2.Plot(&c)
	c.Stacked = true
	dumper2.Plot(&c)
	c = chart.BarChart{Title: "Income"}
	c.XRange.Category = []string{"none", "low", "average", "high"}
	c.Key.Hide = true
	c.YRange.ShowZero = true
	c.ShowVal = 3
	c.AddDataPair("Europe", x, []float64{-10, 15, -20, 5}, blue)
	c.AddDataPair("Asia", x, []float64{-15, 10, 5, 20}, pink)
	c.AddDataPair("Africa", x, []float64{10, -10, 15, -5}, green)
	dumper2.Plot(&c)
	c.Stacked = true
	dumper2.Plot(&c)
	c.AddDataPair("America", x, []float64{15, -5, -10, -20}, red)
	c.YRange.TicSetting.Delta = 0
	dumper2.Plot(&c)
}
Categorical Bar Charts
package main
import (
	"flag"
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"log"
	"math"
	"math/rand"
	"os"
	"sort"
	"time"
	"github.com/ajstarks/svgo"
	"github.com/vdobler/chart"
	"github.com/vdobler/chart/imgg"
	"github.com/vdobler/chart/svgg"
	"github.com/vdobler/chart/txtg"
)
var (
	data1  = []float64{15e-7, 30e-7, 35e-7, 50e-7, 70e-7, 75e-7, 80e-7, 32e-7, 35e-7, 70e-7, 65e-7}
	data10 = []float64{34567, 35432, 37888, 39991, 40566, 42123, 44678}
	data2 = []float64{10e-7, 11e-7, 12e-7, 22e-7, 25e-7, 33e-7}
	data3 = []float64{50e-7, 55e-7, 55e-7, 60e-7, 50e-7, 65e-7, 60e-7, 65e-7, 55e-7, 50e-7}
)
var Background = color.RGBA{0xff, 0xff, 0xff, 0xff}
type Dumper struct {
	N, M, W, H, Cnt           int
	S                         *svg.SVG
	I                         *image.RGBA
	svgFile, imgFile, txtFile *os.File
}
func NewDumper(name string, n, m, w, h int) *Dumper {
	var err error
	dumper := Dumper{N: n, M: m, W: w, H: h}
	dumper.svgFile, err = os.Create(name + ".svg")
	if err != nil {
		panic(err)
	}
	dumper.S = svg.New(dumper.svgFile)
	dumper.S.Start(n*w, m*h)
	dumper.S.Title(name)
	dumper.S.Rect(0, 0, n*w, m*h, "fill: #ffffff")
	dumper.imgFile, err = os.Create(name + ".png")
	if err != nil {
		panic(err)
	}
	dumper.I = image.NewRGBA(image.Rect(0, 0, n*w, m*h))
	bg := image.NewUniform(color.RGBA{0xff, 0xff, 0xff, 0xff})
	draw.Draw(dumper.I, dumper.I.Bounds(), bg, image.ZP, draw.Src)
	dumper.txtFile, err = os.Create(name + ".txt")
	if err != nil {
		panic(err)
	}
	return &dumper
}
func (d *Dumper) Close() {
	png.Encode(d.imgFile, d.I)
	d.imgFile.Close()
	d.S.End()
	d.svgFile.Close()
	d.txtFile.Close()
}
func (d *Dumper) Plot(c chart.Chart) {
	row, col := d.Cnt/d.N, d.Cnt%d.N
	igr := imgg.AddTo(d.I, col*d.W, row*d.H, d.W, d.H, color.RGBA{0xff, 0xff, 0xff, 0xff}, nil, nil)
	c.Plot(igr)
	sgr := svgg.AddTo(d.S, col*d.W, row*d.H, d.W, d.H, "", 12, color.RGBA{0xff, 0xff, 0xff, 0xff})
	c.Plot(sgr)
	tgr := txtg.New(100, 30)
	c.Plot(tgr)
	d.txtFile.Write([]byte(tgr.String() + "\n\n\n"))
	d.Cnt++
}
func stripChart() {
	dumper := NewDumper("xstrip1", 2, 2, 400, 300)
	defer dumper.Close()
	c := chart.StripChart{}
	c.AddData("Sample A", data1, chart.Style{})
	c.AddData("Sample B", data2, chart.Style{})
	c.AddData("Sample C", data3, chart.Style{})
	c.Title = "Sample Strip Chart (no Jitter)"
	c.XRange.Label = "X - Axis"
	c.Key.Pos = "icr"
	dumper.Plot(&c)
	c.Jitter = true
	c.Title = "Sample Strip Chart (with Jitter)"
	dumper.Plot(&c)
	c.Key.Hide = true
	dumper.Plot(&c)
	c.Jitter = false
	c.Title = "Sample Strip Chart (no Jitter)"
	dumper.Plot(&c)
}
func keyStyles() {
	dumper := NewDumper("xkey", 6, 6, 400, 300)
	defer dumper.Close()
	p := chart.ScatterChart{Title: "Key Placement"}
	p.XRange.TicSetting.Mirror, p.YRange.TicSetting.Mirror = 1, 1
	p.XRange.MinMode.Fixed, p.XRange.MaxMode.Fixed = true, true
	p.XRange.MinMode.Value, p.XRange.MaxMode.Value = -5, 5
	p.XRange.Min, p.XRange.Max = -5, 5
	p.XRange.TicSetting.Delta = 2
	p.YRange.MinMode.Fixed, p.YRange.MaxMode.Fixed = true, true
	p.YRange.MinMode.Value, p.YRange.MaxMode.Value = -5, 5
	p.YRange.Min, p.YRange.Max = -5, 5
	p.YRange.TicSetting.Delta = 3
	p.AddFunc("Sin", func(x float64) float64 { return math.Sin(x) }, chart.PlotStyleLines,
		chart.Style{LineColor: color.NRGBA{0xa0, 0x00, 0x00, 0xff}, LineWidth: 1, LineStyle: 1})
	p.AddFunc("Cos", func(x float64) float64 { return math.Cos(x) }, chart.PlotStyleLines,
		chart.Style{LineColor: color.NRGBA{0x00, 0xa0, 0x00, 0xff}, LineWidth: 1, LineStyle: 1})
	p.AddFunc("Tan", func(x float64) float64 { return math.Tan(x) }, chart.PlotStyleLines,
		chart.Style{LineColor: color.NRGBA{0x00, 0x00, 0xa0, 0xff}, LineWidth: 1, LineStyle: 1})
	for _, pos := range []string{"itl", "itc", "itr", "icl", "icc", "icr", "ibl", "ibc", "ibr",
		"otl", "otc", "otr", "olt", "olc", "olb", "obl", "obc", "obr", "ort", "orc", "orb"} {
		p.Key.Pos = pos
		p.Title = "Key Placement: " + pos
		dumper.Plot(&p)
	}
	p.Key.Pos = "itl"
	p.AddFunc("Log", func(x float64) float64 { return math.Log(x) }, chart.PlotStyleLines,
		chart.Style{LineColor: color.NRGBA{0xff, 0x60, 0x60, 0xff}, LineWidth: 1, LineStyle: 1})
	p.AddFunc("Exp", func(x float64) float64 { return math.Exp(x) }, chart.PlotStyleLines,
		chart.Style{LineColor: color.NRGBA{0x60, 0xff, 0x60, 0xff}, LineWidth: 1, LineStyle: 1})
	p.AddFunc("Atan", func(x float64) float64 { return math.Atan(x) }, chart.PlotStyleLines,
		chart.Style{LineColor: color.NRGBA{0x60, 0x60, 0xff, 0xff}, LineWidth: 1, LineStyle: 1})
	p.AddFunc("Y1", func(x float64) float64 { return math.Y1(x) }, chart.PlotStyleLines,
		chart.Style{LineColor: color.NRGBA{0xd0, 0xd0, 0x00, 0xff}, LineWidth: 1, LineStyle: 1})
	for _, cols := range []int{-4, -3, -2, -1, 0, 1, 2, 3, 4} {
		p.Key.Cols = cols
		p.Title = fmt.Sprintf("Key Cols: %d", cols)
		dumper.Plot(&p)
	}
}
func scatterTics() {
	dumper := NewDumper("xstrip1", 3, 3, 400, 300)
	defer dumper.Close()
	p := chart.ScatterChart{Title: "Sample Scatter Chart"}
	p.AddDataPair("Sample A", data10, data1, chart.PlotStylePoints, chart.Style{})
	p.XRange.TicSetting.Delta = 5000
	p.XRange.Label = "X - Value"
	p.YRange.Label = "Y - Value"
	dumper.Plot(&p)
	p.XRange.TicSetting.Hide, p.YRange.TicSetting.Hide = true, true
	dumper.Plot(&p)
	p.YRange.TicSetting.Hide = false
	p.XRange.TicSetting.Grid, p.YRange.TicSetting.Grid = chart.GridLines, chart.GridLines
	dumper.Plot(&p)
	p.XRange.TicSetting.Hide, p.YRange.TicSetting.Hide = false, false
	p.XRange.TicSetting.Mirror, p.YRange.TicSetting.Mirror = 1, 2
	dumper.Plot(&p)
	c := chart.ScatterChart{Title: "Own tics"}
	c.XRange.Fixed(0, 4*math.Pi, math.Pi)
	c.YRange.Fixed(-1.25, 1.25, 0.5)
	c.XRange.TicSetting.Format = func(f float64) string {
		w := int(180*f/math.Pi + 0.5)
		return fmt.Sprintf("%d°", w)
	}
	c.AddFunc("Sin(x)", func(x float64) float64 { return math.Sin(x) }, chart.PlotStyleLines,
		chart.Style{Symbol: '@', LineWidth: 2, LineColor: color.NRGBA{0x00, 0x00, 0xcc, 0xff}, LineStyle: 0})
	c.AddFunc("Cos(x)", func(x float64) float64 { return math.Cos(x) }, chart.PlotStyleLines,
		chart.Style{Symbol: '%', LineWidth: 2, LineColor: color.NRGBA{0x00, 0xcc, 0x00, 0xff}, LineStyle: 0})
	dumper.Plot(&c)
	c.Title = "Tic Variants"
	c.XRange.TicSetting.Tics = 1
	c.YRange.TicSetting.Tics = 2
	dumper.Plot(&c)
	c.Title = "Blocked Grid"
	c.XRange.TicSetting.Tics = 1
	c.YRange.TicSetting.Tics = 1
	c.XRange.TicSetting.Mirror, c.YRange.TicSetting.Mirror = 1, 1
	c.XRange.TicSetting.Grid = chart.GridBlocks
	c.YRange.TicSetting.Grid = chart.GridBlocks
	dumper.Plot(&c)
}
func scatterChart() {
	dumper := NewDumper("xscatter2", 1, 1, 800, 600)
	defer dumper.Close()
	pl := chart.ScatterChart{Title: "Scatter + Lines"}
	pl.XRange.Label, pl.YRange.Label = "X - Value", "Y - Value"
	pl.Key.Pos = "itl"
	pl.XRange.TicSetting.Grid = 1
	x := []float64{-4, -3.3, -1.8, -1, 0.2, 0.8, 1.8, 3.1, 4, 5.3, 6, 7, 8, 9}
	y := []float64{22, 18, -3, 0, 0.5, 2, 45, 12, 16.5, 24, 30, 55, 60, 70}
	pl.AddDataPair("Data", x, y, chart.PlotStyleLinesPoints,
		chart.Style{Symbol: '#', SymbolColor: color.NRGBA{0x00, 0x00, 0xff, 0xff}, LineStyle: chart.SolidLine})
	last := len(pl.Data) - 1
	pl.Data[last].Samples[6].DeltaX = 2.5
	pl.Data[last].Samples[6].OffX = 0.5
	pl.Data[last].Samples[6].DeltaY = 16
	pl.Data[last].Samples[6].OffY = 2
	pl.AddData("Points", []chart.EPoint{chart.EPoint{-4, 40, 0, 0, 0, 0}, chart.EPoint{-3, 45, 0, 0, 0, 0},
		chart.EPoint{-2, 35, 0, 0, 0, 0}}, chart.PlotStylePoints,
		chart.Style{Symbol: '0', SymbolColor: color.NRGBA{0xff, 0x00, 0xff, 0xff}})
	pl.AddFunc("Theory", func(x float64) float64 {
		if x > 5.25 && x < 5.75 {
			return 75
		}
		if x > 7.25 && x < 7.75 {
			return 500
		}
		return x * x
	}, chart.PlotStyleLines,
		chart.Style{Symbol: '%', LineWidth: 2, LineColor: color.NRGBA{0xa0, 0x00, 0x00, 0xff}, LineStyle: chart.DashDotDotLine})
	pl.AddFunc("30", func(x float64) float64 { return 30 }, chart.PlotStyleLines,
		chart.Style{Symbol: '+', LineWidth: 1, LineColor: color.NRGBA{0x00, 0xa0, 0x00, 0xff}, LineStyle: 1})
	pl.AddFunc("", func(x float64) float64 { return 7 }, chart.PlotStyleLines,
		chart.Style{Symbol: '@', LineWidth: 1, LineColor: color.NRGBA{0x00, 0x00, 0xa0, 0xff}, LineStyle: 1})
	pl.XRange.ShowZero = true
	pl.XRange.TicSetting.Mirror = 1
	pl.YRange.TicSetting.Mirror = 1
	pl.XRange.TicSetting.Grid = 1
	pl.XRange.Label = "X-Range"
	pl.YRange.Label = "Y-Range"
	pl.Key.Cols = 2
	pl.Key.Pos = "orb"
	dumper.Plot(&pl)
}
func functionPlots() {
	dumper := NewDumper("xscatter3", 2, 1, 500, 400)
	defer dumper.Close()
	p := chart.ScatterChart{Title: "Functions"}
	p.XRange.Label, p.YRange.Label = "X - Value", "Y - Value"
	p.Key.Pos = "ibl"
	p.XRange.MinMode.Fixed, p.XRange.MaxMode.Fixed = true, true
	p.XRange.MinMode.Value, p.XRange.MaxMode.Value = -10, 10
	p.YRange.MinMode.Fixed, p.YRange.MaxMode.Fixed = true, true
	p.YRange.MinMode.Value, p.YRange.MaxMode.Value = -10, 10
	p.XRange.TicSetting.Delta = 2
	p.YRange.TicSetting.Delta = 5
	p.XRange.TicSetting.Mirror = 1
	p.YRange.TicSetting.Mirror = 1
	p.AddFunc("i+n", func(x float64) float64 {
		if x > -7 && x < -5 {
			return math.Inf(-1)
		} else if x > -1.5 && x < 1.5 {
			return math.NaN()
		} else if x > 5 && x < 7 {
			return math.Inf(1)
		}
		return -0.75 * x
	},
		chart.PlotStyleLines, chart.Style{Symbol: 'o', LineWidth: 2, LineColor: color.NRGBA{0xa0, 0x00, 0x00, 0xff}, LineStyle: 1})
	p.AddFunc("sin", func(x float64) float64 { return 13 * math.Sin(x) }, chart.PlotStyleLines,
		chart.Style{Symbol: '#', LineWidth: 1, LineColor: color.NRGBA{0x00, 0x00, 0xa0, 0xff}, LineStyle: 1})
	p.AddFunc("2x", func(x float64) float64 { return 2 * x }, chart.PlotStyleLines,
		chart.Style{Symbol: 'X', LineWidth: 1, LineColor: color.NRGBA{0x00, 0xa0, 0x00, 0xff}, LineStyle: 1})
	dumper.Plot(&p)
	p = chart.ScatterChart{Title: "Functions"}
	p.Key.Hide = true
	p.XRange.MinMode.Fixed, p.XRange.MaxMode.Fixed = true, true
	p.XRange.MinMode.Value, p.XRange.MaxMode.Value = -2, 2
	p.YRange.MinMode.Fixed, p.YRange.MaxMode.Fixed = true, true
	p.YRange.MinMode.Value, p.YRange.MaxMode.Value = -2, 2
	p.XRange.TicSetting.Delta = 1
	p.YRange.TicSetting.Delta = 1
	p.XRange.TicSetting.Mirror = 1
	p.YRange.TicSetting.Mirror = 1
	p.NSamples = 5
	p.AddFunc("10x", func(x float64) float64 { return 10 * x }, chart.PlotStyleLines,
		chart.Style{Symbol: 'o', LineWidth: 2, LineColor: color.NRGBA{0x00, 0xa0, 0x00, 0xff}, LineStyle: 1})
	dumper.Plot(&p)
}
func autoscale() {
	dumper := NewDumper("xautoscale", 2, 2, 600, 400)
	defer dumper.Close()
	N := 200
	points := make([]chart.EPoint, N)
	for i := 0; i < N-1; i++ {
		points[i].X = rand.Float64()*10000 - 5000  
		points[i].Y = rand.Float64()*10000 - 5000  
		points[i].DeltaX = rand.Float64() * 400
		points[i].DeltaY = rand.Float64() * 400
	}
	points[N-1].X = -650
	points[N-1].Y = -2150
	points[N-1].DeltaX = 400
	points[N-1].DeltaY = 400
	points[N-1].OffX = 100
	points[N-1].OffY = -150
	s := chart.ScatterChart{Title: "Full Autoscaling"}
	s.Key.Hide = true
	s.XRange.TicSetting.Mirror = 1
	s.YRange.TicSetting.Mirror = 1
	s.AddData("Data", points, chart.PlotStylePoints, chart.Style{Symbol: 'o', SymbolColor: color.NRGBA{0x00, 0xee, 0x00, 0xff}})
	dumper.Plot(&s)
	s = chart.ScatterChart{Title: "Xmin: -1850, Xmax clipped to [500:900]"}
	s.Key.Hide = true
	s.XRange.TicSetting.Mirror = 1
	s.YRange.TicSetting.Mirror = 1
	s.XRange.MinMode.Fixed, s.XRange.MinMode.Value = true, -1850
	s.XRange.MaxMode.Constrained = true
	s.XRange.MaxMode.Lower, s.XRange.MaxMode.Upper = 500, 900
	s.AddData("Data", points, chart.PlotStylePoints, chart.Style{Symbol: '0', SymbolColor: color.NRGBA{0xee, 0x00, 0x00, 0xff}})
	dumper.Plot(&s)
	s = chart.ScatterChart{Title: "Xmin: -1850, Ymax clipped to [9000:11000]"}
	s.Key.Hide = true
	s.XRange.TicSetting.Mirror = 1
	s.YRange.TicSetting.Mirror = 1
	s.XRange.MinMode.Fixed, s.XRange.MinMode.Value = true, -1850
	s.YRange.MaxMode.Constrained = true
	s.YRange.MaxMode.Lower, s.YRange.MaxMode.Upper = 9000, 11000
	s.AddData("Data", points, chart.PlotStylePoints, chart.Style{Symbol: '0', SymbolColor: color.NRGBA{0x00, 0x00, 0xee, 0xff}})
	dumper.Plot(&s)
	s = chart.ScatterChart{Title: "Tiny fraction"}
	s.Key.Hide = true
	s.XRange.TicSetting.Mirror = 1
	s.YRange.TicSetting.Mirror = 1
	s.YRange.MinMode.Constrained = true
	s.YRange.MinMode.Lower, s.YRange.MinMode.Upper = -2250, -2050
	s.YRange.MaxMode.Constrained = true
	s.YRange.MaxMode.Lower, s.YRange.MaxMode.Upper = -1950, -1700
	s.XRange.MinMode.Constrained = true
	s.XRange.MinMode.Lower, s.XRange.MinMode.Upper = -900, -800
	s.XRange.MaxMode.Constrained = true
	s.XRange.MaxMode.Lower, s.XRange.MaxMode.Upper = -850, -650
	s.AddData("Data", points, chart.PlotStylePoints, chart.Style{Symbol: '0', SymbolColor: color.NRGBA{0xee, 0xcc, 0x00, 0xff}})
	dumper.Plot(&s)
}
func boxChart() {
	dumper := NewDumper("xbox1", 2, 2, 400, 300)
	defer dumper.Close()
	p := chart.BoxChart{Title: "Box Chart"}
	p.XRange.Label, p.YRange.Label = "Value", "Count"
	for x := 10; x <= 50; x += 5 {
		points := make([]float64, 70)
		a := rand.Float64() * 10
		v := rand.Float64()*5 + 2
		for i := 0; i < len(points); i++ {
			x := rand.NormFloat64()*v + a
			points[i] = x
		}
		p.AddSet(float64(x), points, true)
	}
	p.NextDataSet("Sample B", chart.Style{Symbol: 'x', LineColor: color.NRGBA{0x00, 0xc0, 0x00, 0xff}, LineWidth: 1, LineStyle: chart.SolidLine})
	for x := 12; x <= 50; x += 10 {
		points := make([]float64, 60)
		a := rand.Float64()*15 + 30
		v := rand.Float64()*5 + 2
		for i := 0; i < len(points); i++ {
			x := rand.NormFloat64()*v + a
			points[i] = x
		}
		p.AddSet(float64(x), points, true)
	}
	dumper.Plot(&p)
	p = chart.BoxChart{Title: "Categorical Box Chart"}
	p.XRange.Label, p.YRange.Label = "Population", "Count"
	p.XRange.Fixed(-1, 3, 1)
	p.XRange.Category = []string{"Rural", "Urban", "Island"}
	p.NextDataSet("", chart.Style{Symbol: '%', LineColor: color.NRGBA{0x00, 0x00, 0xcc, 0xff}, LineWidth: 1, LineStyle: chart.SolidLine})
	p.AddSet(0, bigauss(100, 0, 5, 10, 0, 0, 0, 50), true)
	p.AddSet(1, bigauss(100, 25, 5, 5, 2, 25, 0, 50), true)
	p.AddSet(2, bigauss(50, 50, 4, 8, 4, 16, 0, 50), true)
	dumper.Plot(&p)
}
func gauss(n int, s, a, l, u float64) []float64 {
	rand.Seed(12345)
	points := make([]float64, n)
	for i := 0; i < len(points); i++ {
		x := rand.NormFloat64()*s + a
		if x < l {
			x = l
		} else if x > u {
			x = u
		}
		points[i] = x
	}
	return points
}
func bigauss(n1, n2 int, s1, a1, s2, a2, l, u float64) []float64 {
	points := make([]float64, n1+n2)
	for i := 0; i < n1; i++ {
		x := rand.NormFloat64()*s1 + a1
		for x < l || x > u {
			x = rand.NormFloat64()*s1 + a1
		}
		points[i] = x
	}
	for i := n1; i < n1+n2; i++ {
		x := rand.NormFloat64()*s2 + a2
		for x < l || x > u {
			x = rand.NormFloat64()*s2 + a2
		}
		points[i] = x
	}
	return points
}
func kernels() {
	dumper := NewDumper("xkernels", 1, 1, 600, 400)
	defer dumper.Close()
	p := chart.ScatterChart{Title: "Kernels"}
	p.XRange.Label, p.YRange.Label = "u", "K(u)"
	p.XRange.MinMode.Fixed, p.XRange.MaxMode.Fixed = true, true
	p.XRange.MinMode.Value, p.XRange.MaxMode.Value = -2, 2
	p.YRange.MinMode.Fixed, p.YRange.MaxMode.Fixed = true, true
	p.YRange.MinMode.Value, p.YRange.MaxMode.Value = -0.1, 1.1
	p.XRange.TicSetting.Delta = 1
	p.YRange.TicSetting.Delta = 0.2
	p.XRange.TicSetting.Mirror = 1
	p.YRange.TicSetting.Mirror = 1
	p.AddFunc("Bisquare", chart.BisquareKernel,
		chart.PlotStyleLines, chart.Style{Symbol: 'o', LineWidth: 1, LineColor: color.NRGBA{0xa0, 0x00, 0x00, 0xff}, LineStyle: 1})
	p.AddFunc("Epanechnikov", chart.EpanechnikovKernel,
		chart.PlotStyleLines, chart.Style{Symbol: 'X', LineWidth: 1, LineColor: color.NRGBA{0x00, 0xa0, 0x00, 0xff}, LineStyle: 1})
	p.AddFunc("Rectangular", chart.RectangularKernel,
		chart.PlotStyleLines, chart.Style{Symbol: '=', LineWidth: 1, LineColor: color.NRGBA{0x00, 0x00, 0xa0, 0xff}, LineStyle: 1})
	p.AddFunc("Gauss", chart.GaussKernel,
		chart.PlotStyleLines, chart.Style{Symbol: '*', LineWidth: 1, LineColor: color.NRGBA{0xa0, 0x00, 0xa0, 0xff}, LineStyle: 1})
	dumper.Plot(&p)
}
func histChart(name, title string, stacked, counts, shifted bool) {
	dumper := NewDumper("xhist", 2, 2, 400, 300)
	defer dumper.Close()
	hc := chart.HistChart{Title: title, Stacked: stacked, Counts: counts, Shifted: shifted}
	hc.XRange.Label = "Sample Value"
	if counts {
		hc.YRange.Label = "Total Count"
	} else {
		hc.YRange.Label = "Rel. Frequency [%]"
	}
	hc.Key.Hide = true
	points := gauss(150, 10, 20, 0, 50)
	hc.AddData("Sample 1", points,
		chart.Style{   })
	hc.Kernel = chart.BisquareKernel  
	dumper.Plot(&hc)
	points2 := gauss(80, 4, 37, 0, 50)
	hc.AddData("Sample 2", points2,
		chart.Style{   })
	hc.YRange.TicSetting.Delta = 0
	dumper.Plot(&hc)
	points3 := gauss(60, 15, 0, 0, 50)
	hc.AddData("Sample 3", points3,
		chart.Style{   })
	hc.YRange.TicSetting.Delta = 0
	dumper.Plot(&hc)
	points4 := gauss(40, 30, 15, 0, 50)
	hc.AddData("Sample 4", points4, chart.Style{   })
	hc.Kernel = nil
	hc.YRange.TicSetting.Delta = 0
	dumper.Plot(&hc)
}
func barChart() {
	dumper := NewDumper("xbar1", 3, 2, 400, 300)
	defer dumper.Close()
	red := chart.Style{Symbol: 'o', LineColor: color.NRGBA{0xcc, 0x00, 0x00, 0xff},
		FillColor: color.NRGBA{0xff, 0x80, 0x80, 0xff},
		LineStyle: chart.SolidLine, LineWidth: 2}
	green := chart.Style{Symbol: '#', LineColor: color.NRGBA{0x00, 0xcc, 0x00, 0xff},
		FillColor: color.NRGBA{0x80, 0xff, 0x80, 0xff},
		LineStyle: chart.SolidLine, LineWidth: 2}
	barc := chart.BarChart{Title: "Simple Bar Chart"}
	barc.Key.Hide = true
	barc.XRange.ShowZero = true
	barc.AddDataPair("Amount",
		[]float64{-10, 10, 20, 30, 35, 40, 50},
		[]float64{90, 120, 180, 205, 230, 150, 190}, red)
	dumper.Plot(&barc)
	barc.XRange.TicSetting.Delta = 0
	barc = chart.BarChart{Title: "Simple Bar Chart"}
	barc.Key.Hide = true
	barc.XRange.ShowZero = true
	barc.AddDataPair("Test", []float64{-5, 15, 25, 35, 45, 55}, []float64{110, 80, 95, 80, 120, 140}, green)
	dumper.Plot(&barc)
	barc.XRange.TicSetting.Delta = 0
	barc.YRange.TicSetting.Delta = 0
	barc.Title = "Combined (ugly as bar positions do not match)"
	barc.AddDataPair("Amount", []float64{-10, 10, 20, 30, 35, 40, 50}, []float64{90, 120, 180, 205, 230, 150, 190}, red)
	dumper.Plot(&barc)
	barc.Title = "Stacked (still ugly)"
	barc.Stacked = true
	dumper.Plot(&barc)
	barc = chart.BarChart{Title: "Nicely Stacked"}
	barc.Key.Hide = true
	barc.XRange.Fixed(0, 60, 10)
	barc.AddDataPair("A", []float64{10, 30, 40, 50}, []float64{110, 95, 60, 120}, red)
	barc.AddDataPair("B", []float64{10, 30, 40, 50}, []float64{40, 130, 15, 100}, green)
	dumper.Plot(&barc)
	barc.Stacked = true
	dumper.Plot(&barc)
}