go-hep.org/x/hep@v0.38.1/hplot/ratioplot.go (about)

     1  // Copyright ©2020 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package hplot
     6  
     7  import (
     8  	"gonum.org/v1/plot"
     9  	"gonum.org/v1/plot/vg"
    10  	"gonum.org/v1/plot/vg/draw"
    11  )
    12  
    13  type RatioPlot struct {
    14  	Top    *Plot
    15  	Bottom *Plot
    16  
    17  	// Tiles controls the layout of the 2x1 ratio-plot grid.
    18  	// Tiles can be used to customize the padding between plots.
    19  	Tiles draw.Tiles
    20  
    21  	// Ratio controls how the vertical space is partioned between
    22  	// the top and bottom plots.
    23  	// The top plot will take (1-ratio)*height.
    24  	// Default is 0.3.
    25  	Ratio float64
    26  }
    27  
    28  func NewRatioPlot() *RatioPlot {
    29  	rp := &RatioPlot{
    30  		Top:    New(),
    31  		Bottom: New(),
    32  		Ratio:  0.3,
    33  		Tiles:  draw.Tiles{Rows: 2, Cols: 1},
    34  	}
    35  
    36  	const pad = 1
    37  	for _, v := range []*vg.Length{
    38  		&rp.Tiles.PadTop, &rp.Tiles.PadBottom,
    39  		&rp.Tiles.PadRight, &rp.Tiles.PadLeft,
    40  		&rp.Tiles.PadX, &rp.Tiles.PadY,
    41  	} {
    42  		if *v == 0 {
    43  			*v = pad
    44  		}
    45  	}
    46  
    47  	// hide X-axis labels
    48  	rp.Top.X.Tick.Marker = NoTicks{}
    49  	return rp
    50  }
    51  
    52  // Draw draws a ratio plot to a draw.Canvas.
    53  //
    54  // Plotters are drawn in the order in which they were
    55  // added to the plot.  Plotters that  implement the
    56  // GlyphBoxer interface will have their GlyphBoxes
    57  // taken into account when padding the plot so that
    58  // none of their glyphs are clipped.
    59  func (rp *RatioPlot) Draw(dc draw.Canvas) {
    60  	var (
    61  		top, bot = rp.align(dc)
    62  	)
    63  
    64  	rp.Top.Draw(top)
    65  	rp.Bottom.Draw(bot)
    66  }
    67  
    68  func (rp *RatioPlot) align(dc draw.Canvas) (top, bot draw.Canvas) {
    69  	var (
    70  		ratio = vg.Length(rp.Ratio)
    71  		h     = dc.Size().Y
    72  		ps    = [][]*plot.Plot{
    73  			{rp.Top.Plot},
    74  			{rp.Bottom.Plot},
    75  		}
    76  		cs = plot.Align(ps, rp.Tiles, dc)
    77  	)
    78  
    79  	top = cs[0][0]
    80  	bot = cs[1][0]
    81  
    82  	top.Rectangle.Min.Y = ratio * h
    83  	top.Rectangle.Max.Y = h
    84  	bot.Rectangle.Max.Y = ratio * h
    85  
    86  	return top, bot
    87  }
    88  
    89  var (
    90  	_ Drawer = (*RatioPlot)(nil)
    91  )