Skip to content

Commit

Permalink
hplot: properly handle hstacks with bands and log-y
Browse files Browse the repository at this point in the history
Fixes #749.
  • Loading branch information
sbinet committed Jun 5, 2020
1 parent 4cf183c commit 24781f7
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 22 deletions.
197 changes: 191 additions & 6 deletions hplot/README.md
Expand Up @@ -875,10 +875,9 @@ func ExampleHStack_withBand() {
hh1.LineStyle.Color = color.Black
hh1.Band.FillColor = color.NRGBA{G: 210, A: 200}

hh2 := hplot.NewH1D(h2, hplot.WithBand(true))
hh2 := hplot.NewH1D(h2, hplot.WithBand(false))
hh2.FillColor = colors[1]
hh2.LineStyle.Width = 0
hh2.Band.FillColor = color.NRGBA{B: 220, A: 200}

hh3 := hplot.NewH1D(h3, hplot.WithBand(true))
hh3.FillColor = colors[2]
Expand All @@ -887,12 +886,28 @@ func ExampleHStack_withBand() {

hs := []*hplot.H1D{hh1, hh2, hh3}

tp := hplot.NewTiledPlot(draw.Tiles{Cols: 1, Rows: 2})
hh4 := hplot.NewH1D(h1)
hh4.FillColor = colors[0]
hh4.LineStyle.Color = color.Black

hh5 := hplot.NewH1D(h2)
hh5.FillColor = colors[1]
hh5.LineStyle.Width = 0

hh6 := hplot.NewH1D(h3)
hh6.FillColor = colors[2]
hh6.LineStyle.Color = color.Black

hsHistoNoBand := []*hplot.H1D{hh4, hh5, hh6}

tp := hplot.NewTiledPlot(draw.Tiles{Cols: 2, Rows: 2})
tp.Align = true

{
p := tp.Plot(0, 0)
p.Title.Text = "With Band, Stack: OFF"
p.Title.Text = "Histos With or Without Band, Stack: OFF"
p.Title.Padding = 10
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hs, hplot.WithBand(true))
hstack.Stack = hplot.HStackOff
Expand All @@ -904,9 +919,27 @@ func ExampleHStack_withBand() {
p.Legend.Left = true
}

{
p := tp.Plot(0, 1)
p.Title.Text = "Histos Without Band, Stack: OFF"
p.Title.Padding = 10
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hsHistoNoBand, hplot.WithBand(true))
hstack.Stack = hplot.HStackOff
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

{
p := tp.Plot(1, 0)
p.Title.Text = "With Band, Stack: ON"
p.Title.Text = "Histos With or Without Band, Stack: ON"
p.Title.Padding = 10
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hs, hplot.WithBand(true))
Expand All @@ -919,7 +952,159 @@ func ExampleHStack_withBand() {
p.Legend.Left = true
}

err := tp.Save(15*vg.Centimeter, 15*vg.Centimeter, "testdata/hstack_band.png")
{
p := tp.Plot(1, 1)
p.Title.Text = "Histos Without Band, Stack: ON"
p.Title.Padding = 10
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hsHistoNoBand, hplot.WithBand(true))
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

err := tp.Save(25*vg.Centimeter, 15*vg.Centimeter, "testdata/hstack_band.png")
if err != nil {
log.Fatalf("error: %+v", err)
}
}
```

### Stack of 1D histograms with a band, with a log-y scale

![hstack-logy-example](https://github.com/go-hep/hep/raw/master/hplot/testdata/hstack_logy_golden.png)

[embedmd]:# (example_hstack_test.go go /func ExampleHStack_withLogY/ /\n}/)
```go
func ExampleHStack_withLogY() {
h1 := hbook.NewH1D(50, -8, 12)
h2 := hbook.NewH1D(50, -8, 12)
h3 := hbook.NewH1D(50, -8, 12)

const seed = 1234
fillH1(h1, 2000, -2, 1, seed)
fillH1(h2, 2000, +3, 3, seed)
fillH1(h3, 2000, +4, 1, seed)

colors := []color.Color{
color.NRGBA{122, 195, 106, 150},
color.NRGBA{90, 155, 212, 150},
color.NRGBA{250, 167, 91, 150},
}
logy := hplot.WithLogY(true)

hh1 := hplot.NewH1D(h1, hplot.WithBand(true), logy)
hh1.FillColor = colors[0]
hh1.LineStyle.Color = color.Black
hh1.Band.FillColor = color.NRGBA{G: 210, A: 200}

hh2 := hplot.NewH1D(h2, hplot.WithBand(false), logy)
hh2.FillColor = colors[1]
hh2.LineStyle.Width = 0

hh3 := hplot.NewH1D(h3, hplot.WithBand(true), logy)
hh3.FillColor = colors[2]
hh3.LineStyle.Color = color.Black
hh3.Band.FillColor = color.NRGBA{R: 220, A: 200}

hs := []*hplot.H1D{hh1, hh2, hh3}

hh4 := hplot.NewH1D(h1, logy)
hh4.FillColor = colors[0]
hh4.LineStyle.Color = color.Black

hh5 := hplot.NewH1D(h2, logy)
hh5.FillColor = colors[1]
hh5.LineStyle.Width = 0

hh6 := hplot.NewH1D(h3, logy)
hh6.FillColor = colors[2]
hh6.LineStyle.Color = color.Black

hsHistoNoBand := []*hplot.H1D{hh4, hh5, hh6}

tp := hplot.NewTiledPlot(draw.Tiles{Cols: 2, Rows: 2})
tp.Align = true

{
p := tp.Plot(0, 0)
p.Title.Text = "Histos With or Without Band, Stack: OFF"
p.Title.Padding = 10
p.Y.Scale = plot.LogScale{}
p.Y.Tick.Marker = plot.LogTicks{}
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hs, hplot.WithBand(true), logy)
hstack.Stack = hplot.HStackOff
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

{
p := tp.Plot(0, 1)
p.Title.Text = "Histos Without Band, Stack: OFF"
p.Title.Padding = 10
p.Y.Scale = plot.LogScale{}
p.Y.Tick.Marker = plot.LogTicks{}
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hsHistoNoBand, hplot.WithBand(true), logy)
hstack.Stack = hplot.HStackOff
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

{
p := tp.Plot(1, 0)
p.Title.Text = "Histos With or Without Band, Stack: ON"
p.Title.Padding = 10
p.Y.Scale = plot.LogScale{}
p.Y.Tick.Marker = plot.LogTicks{}
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hs, hplot.WithBand(true), logy)
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

{
p := tp.Plot(1, 1)
p.Title.Text = "Histos Without Band, Stack: ON"
p.Title.Padding = 10
p.Y.Scale = plot.LogScale{}
p.Y.Tick.Marker = plot.LogTicks{}
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hsHistoNoBand, hplot.WithBand(true), logy)
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

err := tp.Save(25*vg.Centimeter, 15*vg.Centimeter, "testdata/hstack_logy.png")
if err != nil {
log.Fatalf("error: %+v", err)
}
Expand Down
132 changes: 132 additions & 0 deletions hplot/example_hstack_test.go
Expand Up @@ -12,6 +12,7 @@ import (
"go-hep.org/x/hep/hplot"
"golang.org/x/exp/rand"
"gonum.org/v1/gonum/stat/distuv"
"gonum.org/v1/plot"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"
)
Expand Down Expand Up @@ -149,6 +150,7 @@ func ExampleHStack_withBand() {
p := tp.Plot(0, 0)
p.Title.Text = "Histos With or Without Band, Stack: OFF"
p.Title.Padding = 10
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hs, hplot.WithBand(true))
hstack.Stack = hplot.HStackOff
Expand Down Expand Up @@ -181,6 +183,7 @@ func ExampleHStack_withBand() {
p := tp.Plot(1, 0)
p.Title.Text = "Histos With or Without Band, Stack: ON"
p.Title.Padding = 10
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hs, hplot.WithBand(true))
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
Expand Down Expand Up @@ -214,6 +217,135 @@ func ExampleHStack_withBand() {
}
}

func ExampleHStack_withLogY() {
h1 := hbook.NewH1D(50, -8, 12)
h2 := hbook.NewH1D(50, -8, 12)
h3 := hbook.NewH1D(50, -8, 12)

const seed = 1234
fillH1(h1, 2000, -2, 1, seed)
fillH1(h2, 2000, +3, 3, seed)
fillH1(h3, 2000, +4, 1, seed)

colors := []color.Color{
color.NRGBA{122, 195, 106, 150},
color.NRGBA{90, 155, 212, 150},
color.NRGBA{250, 167, 91, 150},
}
logy := hplot.WithLogY(true)

hh1 := hplot.NewH1D(h1, hplot.WithBand(true), logy)
hh1.FillColor = colors[0]
hh1.LineStyle.Color = color.Black
hh1.Band.FillColor = color.NRGBA{G: 210, A: 200}

hh2 := hplot.NewH1D(h2, hplot.WithBand(false), logy)
hh2.FillColor = colors[1]
hh2.LineStyle.Width = 0

hh3 := hplot.NewH1D(h3, hplot.WithBand(true), logy)
hh3.FillColor = colors[2]
hh3.LineStyle.Color = color.Black
hh3.Band.FillColor = color.NRGBA{R: 220, A: 200}

hs := []*hplot.H1D{hh1, hh2, hh3}

hh4 := hplot.NewH1D(h1, logy)
hh4.FillColor = colors[0]
hh4.LineStyle.Color = color.Black

hh5 := hplot.NewH1D(h2, logy)
hh5.FillColor = colors[1]
hh5.LineStyle.Width = 0

hh6 := hplot.NewH1D(h3, logy)
hh6.FillColor = colors[2]
hh6.LineStyle.Color = color.Black

hsHistoNoBand := []*hplot.H1D{hh4, hh5, hh6}

tp := hplot.NewTiledPlot(draw.Tiles{Cols: 2, Rows: 2})
tp.Align = true

{
p := tp.Plot(0, 0)
p.Title.Text = "Histos With or Without Band, Stack: OFF"
p.Title.Padding = 10
p.Y.Scale = plot.LogScale{}
p.Y.Tick.Marker = plot.LogTicks{}
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hs, hplot.WithBand(true), logy)
hstack.Stack = hplot.HStackOff
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

{
p := tp.Plot(0, 1)
p.Title.Text = "Histos Without Band, Stack: OFF"
p.Title.Padding = 10
p.Y.Scale = plot.LogScale{}
p.Y.Tick.Marker = plot.LogTicks{}
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hsHistoNoBand, hplot.WithBand(true), logy)
hstack.Stack = hplot.HStackOff
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

{
p := tp.Plot(1, 0)
p.Title.Text = "Histos With or Without Band, Stack: ON"
p.Title.Padding = 10
p.Y.Scale = plot.LogScale{}
p.Y.Tick.Marker = plot.LogTicks{}
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hs, hplot.WithBand(true), logy)
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

{
p := tp.Plot(1, 1)
p.Title.Text = "Histos Without Band, Stack: ON"
p.Title.Padding = 10
p.Y.Scale = plot.LogScale{}
p.Y.Tick.Marker = plot.LogTicks{}
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
hstack := hplot.NewHStack(hsHistoNoBand, hplot.WithBand(true), logy)
hstack.Band.FillColor = color.NRGBA{R: 100, G: 100, B: 100, A: 200}
p.Add(hstack, hplot.NewGrid())
p.Legend.Add("h1", hs[0])
p.Legend.Add("h2", hs[1])
p.Legend.Add("h3", hs[2])
p.Legend.Top = true
p.Legend.Left = true
}

err := tp.Save(25*vg.Centimeter, 15*vg.Centimeter, "testdata/hstack_logy.png")
if err != nil {
log.Fatalf("error: %+v", err)
}
}

func fillH1(h *hbook.H1D, n int, mu, sigma float64, seed uint64) {
dist := distuv.Normal{
Mu: mu,
Expand Down

0 comments on commit 24781f7

Please sign in to comment.