go-hep.org/x/hep@v0.38.1/groot/rhist/h2_gen.go (about)

     1  // Copyright ©2018 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  // Automatically generated. DO NOT EDIT.
     6  
     7  package rhist
     8  
     9  import (
    10  	"fmt"
    11  	"math"
    12  	"reflect"
    13  
    14  	"go-hep.org/x/hep/groot/rbytes"
    15  	"go-hep.org/x/hep/groot/rcont"
    16  	"go-hep.org/x/hep/groot/root"
    17  	"go-hep.org/x/hep/groot/rtypes"
    18  	"go-hep.org/x/hep/groot/rvers"
    19  	"go-hep.org/x/hep/hbook"
    20  )
    21  
    22  // H2F implements ROOT TH2F
    23  type H2F struct {
    24  	th2
    25  	arr rcont.ArrayF
    26  }
    27  
    28  func newH2F() *H2F {
    29  	return &H2F{
    30  		th2: *newH2(),
    31  	}
    32  }
    33  
    34  // NewH2FFrom creates a new H2F from hbook 2-dim histogram.
    35  func NewH2FFrom(h *hbook.H2D) *H2F {
    36  	var (
    37  		hroot  = newH2F()
    38  		bins   = h.Binning.Bins
    39  		nxbins = h.Binning.Nx
    40  		nybins = h.Binning.Ny
    41  		xedges = make([]float64, 0, nxbins+1)
    42  		yedges = make([]float64, 0, nybins+1)
    43  	)
    44  
    45  	hroot.th2.th1.entries = float64(h.Entries())
    46  	hroot.th2.th1.tsumw = h.SumW()
    47  	hroot.th2.th1.tsumw2 = h.SumW2()
    48  	hroot.th2.th1.tsumwx = h.SumWX()
    49  	hroot.th2.th1.tsumwx2 = h.SumWX2()
    50  	hroot.th2.tsumwy = h.SumWY()
    51  	hroot.th2.tsumwy2 = h.SumWY2()
    52  	hroot.th2.tsumwxy = h.SumWXY()
    53  
    54  	ncells := (nxbins + 2) * (nybins + 2)
    55  	hroot.th2.th1.ncells = ncells
    56  
    57  	hroot.th2.th1.xaxis.nbins = nxbins
    58  	hroot.th2.th1.xaxis.xmin = h.XMin()
    59  	hroot.th2.th1.xaxis.xmax = h.XMax()
    60  
    61  	hroot.th2.th1.yaxis.nbins = nybins
    62  	hroot.th2.th1.yaxis.xmin = h.YMin()
    63  	hroot.th2.th1.yaxis.xmax = h.YMax()
    64  
    65  	hroot.arr.Data = make([]float32, ncells)
    66  	hroot.th2.th1.sumw2.Data = make([]float64, ncells)
    67  
    68  	ibin := func(ix, iy int) int { return iy*nxbins + ix }
    69  
    70  	for ix := range h.Binning.Nx {
    71  		for iy := range h.Binning.Ny {
    72  			i := ibin(ix, iy)
    73  			bin := bins[i]
    74  			if ix == 0 {
    75  				yedges = append(yedges, bin.YMin())
    76  			}
    77  			if iy == 0 {
    78  				xedges = append(xedges, bin.XMin())
    79  			}
    80  			hroot.setDist2D(ix+1, iy+1, bin.Dist.SumW(), bin.Dist.SumW2())
    81  		}
    82  	}
    83  
    84  	oflows := h.Binning.Outflows[:]
    85  	for i, v := range []struct{ ix, iy int }{
    86  		{0, 0},
    87  		{0, 1},
    88  		{0, nybins + 1},
    89  		{nxbins + 1, 0},
    90  		{nxbins + 1, 1},
    91  		{nxbins + 1, nybins + 1},
    92  		{1, 0},
    93  		{1, nybins + 1},
    94  	} {
    95  		hroot.setDist2D(v.ix, v.iy, oflows[i].SumW(), oflows[i].SumW2())
    96  	}
    97  
    98  	xedges = append(xedges, bins[ibin(h.Binning.Nx-1, 0)].XMax())
    99  	yedges = append(yedges, bins[ibin(0, h.Binning.Ny-1)].YMax())
   100  
   101  	hroot.th2.th1.SetName(h.Name())
   102  	if v, ok := h.Annotation()["title"]; ok && v != nil {
   103  		hroot.th2.th1.SetTitle(v.(string))
   104  	}
   105  	hroot.th2.th1.xaxis.xbins.Data = xedges
   106  	hroot.th2.th1.yaxis.xbins.Data = yedges
   107  
   108  	return hroot
   109  }
   110  
   111  func (*H2F) RVersion() int16 {
   112  	return rvers.H2F
   113  }
   114  
   115  func (*H2F) isH2() {}
   116  
   117  // Class returns the ROOT class name.
   118  func (*H2F) Class() string {
   119  	return "TH2F"
   120  }
   121  
   122  func (h *H2F) Array() rcont.ArrayF {
   123  	return h.arr
   124  }
   125  
   126  // Rank returns the number of dimensions of this histogram.
   127  func (h *H2F) Rank() int {
   128  	return 2
   129  }
   130  
   131  // NbinsX returns the number of bins in X.
   132  func (h *H2F) NbinsX() int {
   133  	return h.th1.xaxis.nbins
   134  }
   135  
   136  // XAxis returns the axis along X.
   137  func (h *H2F) XAxis() Axis {
   138  	return &h.th1.xaxis
   139  }
   140  
   141  // XBinCenter returns the bin center value in X.
   142  func (h *H2F) XBinCenter(i int) float64 {
   143  	return float64(h.th1.xaxis.BinCenter(i))
   144  }
   145  
   146  // XBinContent returns the bin content value in X.
   147  func (h *H2F) XBinContent(i int) float64 {
   148  	return float64(h.arr.Data[i])
   149  }
   150  
   151  // XBinError returns the bin error in X.
   152  func (h *H2F) XBinError(i int) float64 {
   153  	if len(h.th1.sumw2.Data) > 0 {
   154  		return math.Sqrt(float64(h.th1.sumw2.Data[i]))
   155  	}
   156  	return math.Sqrt(math.Abs(float64(h.arr.Data[i])))
   157  }
   158  
   159  // XBinLowEdge returns the bin lower edge value in X.
   160  func (h *H2F) XBinLowEdge(i int) float64 {
   161  	return h.th1.xaxis.BinLowEdge(i)
   162  }
   163  
   164  // XBinWidth returns the bin width in X.
   165  func (h *H2F) XBinWidth(i int) float64 {
   166  	return h.th1.xaxis.BinWidth(i)
   167  }
   168  
   169  // NbinsY returns the number of bins in Y.
   170  func (h *H2F) NbinsY() int {
   171  	return h.th1.yaxis.nbins
   172  }
   173  
   174  // YAxis returns the axis along Y.
   175  func (h *H2F) YAxis() Axis {
   176  	return &h.th1.yaxis
   177  }
   178  
   179  // YBinCenter returns the bin center value in Y.
   180  func (h *H2F) YBinCenter(i int) float64 {
   181  	return float64(h.th1.yaxis.BinCenter(i))
   182  }
   183  
   184  // YBinContent returns the bin content value in Y.
   185  func (h *H2F) YBinContent(i int) float64 {
   186  	return float64(h.arr.Data[i])
   187  }
   188  
   189  // YBinError returns the bin error in Y.
   190  func (h *H2F) YBinError(i int) float64 {
   191  	if len(h.th1.sumw2.Data) > 0 {
   192  		return math.Sqrt(float64(h.th1.sumw2.Data[i]))
   193  	}
   194  	return math.Sqrt(math.Abs(float64(h.arr.Data[i])))
   195  }
   196  
   197  // YBinLowEdge returns the bin lower edge value in Y.
   198  func (h *H2F) YBinLowEdge(i int) float64 {
   199  	return h.th1.yaxis.BinLowEdge(i)
   200  }
   201  
   202  // YBinWidth returns the bin width in Y.
   203  func (h *H2F) YBinWidth(i int) float64 {
   204  	return h.th1.yaxis.BinWidth(i)
   205  }
   206  
   207  // bin returns the regularized bin number given an (x,y) bin index pair.
   208  func (h *H2F) bin(ix, iy int) int {
   209  	nx := h.th1.xaxis.nbins + 1 // overflow bin
   210  	ny := h.th1.yaxis.nbins + 1 // overflow bin
   211  	switch {
   212  	case ix < 0:
   213  		ix = 0
   214  	case ix > nx:
   215  		ix = nx
   216  	}
   217  	switch {
   218  	case iy < 0:
   219  		iy = 0
   220  	case iy > ny:
   221  		iy = ny
   222  	}
   223  	return ix + (nx+1)*iy
   224  }
   225  
   226  func (h *H2F) dist2D(ix, iy int) hbook.Dist2D {
   227  	i := h.bin(ix, iy)
   228  	vx := h.XBinContent(i)
   229  	xerr := h.XBinError(i)
   230  	nx := h.entries(vx, xerr)
   231  	vy := h.YBinContent(i)
   232  	yerr := h.YBinError(i)
   233  	ny := h.entries(vy, yerr)
   234  
   235  	sumw := h.arr.Data[i]
   236  	sumw2 := 0.0
   237  	if len(h.th1.sumw2.Data) > 0 {
   238  		sumw2 = h.th1.sumw2.Data[i]
   239  	}
   240  	return hbook.Dist2D{
   241  		X: hbook.Dist1D{
   242  			Dist: hbook.Dist0D{
   243  				N:     nx,
   244  				SumW:  float64(sumw),
   245  				SumW2: float64(sumw2),
   246  			},
   247  		},
   248  		Y: hbook.Dist1D{
   249  			Dist: hbook.Dist0D{
   250  				N:     ny,
   251  				SumW:  float64(sumw),
   252  				SumW2: float64(sumw2),
   253  			},
   254  		},
   255  	}
   256  }
   257  
   258  func (h *H2F) setDist2D(ix, iy int, sumw, sumw2 float64) {
   259  	i := h.bin(ix, iy)
   260  	h.arr.Data[i] = float32(sumw)
   261  	h.th1.sumw2.Data[i] = sumw2
   262  }
   263  
   264  func (h *H2F) entries(height, err float64) int64 {
   265  	if height <= 0 {
   266  		return 0
   267  	}
   268  	v := height / err
   269  	return int64(v*v + 0.5)
   270  }
   271  
   272  // AsH2D creates a new hbook.H2D from this ROOT histogram.
   273  func (h *H2F) AsH2D() *hbook.H2D {
   274  	var (
   275  		nx = h.NbinsX()
   276  		ny = h.NbinsY()
   277  		hh = hbook.NewH2D(
   278  			nx, h.XAxis().XMin(), h.XAxis().XMax(),
   279  			ny, h.YAxis().XMin(), h.YAxis().XMax(),
   280  		)
   281  		xinrange = 1
   282  		yinrange = 1
   283  	)
   284  	hh.Ann = hbook.Annotation{
   285  		"name":  h.Name(),
   286  		"title": h.Title(),
   287  	}
   288  	hh.Binning.Outflows = [8]hbook.Dist2D{
   289  		h.dist2D(0, 0),
   290  		h.dist2D(0, yinrange),
   291  		h.dist2D(0, ny+1),
   292  		h.dist2D(nx+1, 0),
   293  		h.dist2D(nx+1, yinrange),
   294  		h.dist2D(nx+1, ny+1),
   295  		h.dist2D(xinrange, 0),
   296  		h.dist2D(xinrange, ny+1),
   297  	}
   298  
   299  	hh.Binning.Dist = hbook.Dist2D{
   300  		X: hbook.Dist1D{
   301  			Dist: hbook.Dist0D{
   302  				N:     int64(h.Entries()),
   303  				SumW:  float64(h.SumW()),
   304  				SumW2: float64(h.SumW2()),
   305  			},
   306  		},
   307  		Y: hbook.Dist1D{
   308  			Dist: hbook.Dist0D{
   309  				N:     int64(h.Entries()),
   310  				SumW:  float64(h.SumW()),
   311  				SumW2: float64(h.SumW2()),
   312  			},
   313  		},
   314  	}
   315  	hh.Binning.Dist.X.Stats.SumWX = float64(h.SumWX())
   316  	hh.Binning.Dist.X.Stats.SumWX2 = float64(h.SumWX2())
   317  	hh.Binning.Dist.Y.Stats.SumWX = float64(h.SumWY())
   318  	hh.Binning.Dist.Y.Stats.SumWX2 = float64(h.SumWY2())
   319  	hh.Binning.Dist.Stats.SumWXY = h.SumWXY()
   320  
   321  	for ix := range nx {
   322  		for iy := range ny {
   323  			var (
   324  				i    = iy*nx + ix
   325  				xmin = h.XBinLowEdge(ix + 1)
   326  				xmax = h.XBinWidth(ix+1) + xmin
   327  				ymin = h.YBinLowEdge(iy + 1)
   328  				ymax = h.YBinWidth(iy+1) + ymin
   329  				bin  = &hh.Binning.Bins[i]
   330  			)
   331  			bin.XRange.Min = xmin
   332  			bin.XRange.Max = xmax
   333  			bin.YRange.Min = ymin
   334  			bin.YRange.Max = ymax
   335  			bin.Dist = h.dist2D(ix+1, iy+1)
   336  		}
   337  	}
   338  
   339  	return hh
   340  }
   341  
   342  // MarshalYODA implements the YODAMarshaler interface.
   343  func (h *H2F) MarshalYODA() ([]byte, error) {
   344  	return h.AsH2D().MarshalYODA()
   345  }
   346  
   347  // UnmarshalYODA implements the YODAUnmarshaler interface.
   348  func (h *H2F) UnmarshalYODA(raw []byte) error {
   349  	var hh hbook.H2D
   350  	err := hh.UnmarshalYODA(raw)
   351  	if err != nil {
   352  		return err
   353  	}
   354  
   355  	*h = *NewH2FFrom(&hh)
   356  	return nil
   357  }
   358  
   359  func (h *H2F) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   360  	if w.Err() != nil {
   361  		return 0, w.Err()
   362  	}
   363  
   364  	hdr := w.WriteHeader(h.Class(), h.RVersion())
   365  	w.WriteObject(&h.th2)
   366  	w.WriteObject(&h.arr)
   367  
   368  	return w.SetHeader(hdr)
   369  }
   370  
   371  func (h *H2F) UnmarshalROOT(r *rbytes.RBuffer) error {
   372  	if r.Err() != nil {
   373  		return r.Err()
   374  	}
   375  
   376  	hdr := r.ReadHeader(h.Class(), h.RVersion())
   377  	if hdr.Vers < 1 {
   378  		return fmt.Errorf("rhist: TH2F version too old (%d<1)", hdr.Vers)
   379  	}
   380  
   381  	r.ReadObject(&h.th2)
   382  	r.ReadObject(&h.arr)
   383  
   384  	r.CheckHeader(hdr)
   385  	return r.Err()
   386  }
   387  
   388  func (h *H2F) RMembers() (mbrs []rbytes.Member) {
   389  	mbrs = append(mbrs, h.th2.RMembers()...)
   390  	mbrs = append(mbrs, rbytes.Member{
   391  		Name: "fArray", Value: &h.arr.Data,
   392  	})
   393  	return mbrs
   394  }
   395  
   396  func init() {
   397  	f := func() reflect.Value {
   398  		o := newH2F()
   399  		return reflect.ValueOf(o)
   400  	}
   401  	rtypes.Factory.Add("TH2F", f)
   402  }
   403  
   404  var (
   405  	_ root.Object        = (*H2F)(nil)
   406  	_ root.Named         = (*H2F)(nil)
   407  	_ H2                 = (*H2F)(nil)
   408  	_ rbytes.Marshaler   = (*H2F)(nil)
   409  	_ rbytes.Unmarshaler = (*H2F)(nil)
   410  	_ rbytes.RSlicer     = (*H2F)(nil)
   411  )
   412  
   413  // H2D implements ROOT TH2D
   414  type H2D struct {
   415  	th2
   416  	arr rcont.ArrayD
   417  }
   418  
   419  func newH2D() *H2D {
   420  	return &H2D{
   421  		th2: *newH2(),
   422  	}
   423  }
   424  
   425  // NewH2DFrom creates a new H2D from hbook 2-dim histogram.
   426  func NewH2DFrom(h *hbook.H2D) *H2D {
   427  	var (
   428  		hroot  = newH2D()
   429  		bins   = h.Binning.Bins
   430  		nxbins = h.Binning.Nx
   431  		nybins = h.Binning.Ny
   432  		xedges = make([]float64, 0, nxbins+1)
   433  		yedges = make([]float64, 0, nybins+1)
   434  	)
   435  
   436  	hroot.th2.th1.entries = float64(h.Entries())
   437  	hroot.th2.th1.tsumw = h.SumW()
   438  	hroot.th2.th1.tsumw2 = h.SumW2()
   439  	hroot.th2.th1.tsumwx = h.SumWX()
   440  	hroot.th2.th1.tsumwx2 = h.SumWX2()
   441  	hroot.th2.tsumwy = h.SumWY()
   442  	hroot.th2.tsumwy2 = h.SumWY2()
   443  	hroot.th2.tsumwxy = h.SumWXY()
   444  
   445  	ncells := (nxbins + 2) * (nybins + 2)
   446  	hroot.th2.th1.ncells = ncells
   447  
   448  	hroot.th2.th1.xaxis.nbins = nxbins
   449  	hroot.th2.th1.xaxis.xmin = h.XMin()
   450  	hroot.th2.th1.xaxis.xmax = h.XMax()
   451  
   452  	hroot.th2.th1.yaxis.nbins = nybins
   453  	hroot.th2.th1.yaxis.xmin = h.YMin()
   454  	hroot.th2.th1.yaxis.xmax = h.YMax()
   455  
   456  	hroot.arr.Data = make([]float64, ncells)
   457  	hroot.th2.th1.sumw2.Data = make([]float64, ncells)
   458  
   459  	ibin := func(ix, iy int) int { return iy*nxbins + ix }
   460  
   461  	for ix := range h.Binning.Nx {
   462  		for iy := range h.Binning.Ny {
   463  			i := ibin(ix, iy)
   464  			bin := bins[i]
   465  			if ix == 0 {
   466  				yedges = append(yedges, bin.YMin())
   467  			}
   468  			if iy == 0 {
   469  				xedges = append(xedges, bin.XMin())
   470  			}
   471  			hroot.setDist2D(ix+1, iy+1, bin.Dist.SumW(), bin.Dist.SumW2())
   472  		}
   473  	}
   474  
   475  	oflows := h.Binning.Outflows[:]
   476  	for i, v := range []struct{ ix, iy int }{
   477  		{0, 0},
   478  		{0, 1},
   479  		{0, nybins + 1},
   480  		{nxbins + 1, 0},
   481  		{nxbins + 1, 1},
   482  		{nxbins + 1, nybins + 1},
   483  		{1, 0},
   484  		{1, nybins + 1},
   485  	} {
   486  		hroot.setDist2D(v.ix, v.iy, oflows[i].SumW(), oflows[i].SumW2())
   487  	}
   488  
   489  	xedges = append(xedges, bins[ibin(h.Binning.Nx-1, 0)].XMax())
   490  	yedges = append(yedges, bins[ibin(0, h.Binning.Ny-1)].YMax())
   491  
   492  	hroot.th2.th1.SetName(h.Name())
   493  	if v, ok := h.Annotation()["title"]; ok && v != nil {
   494  		hroot.th2.th1.SetTitle(v.(string))
   495  	}
   496  	hroot.th2.th1.xaxis.xbins.Data = xedges
   497  	hroot.th2.th1.yaxis.xbins.Data = yedges
   498  
   499  	return hroot
   500  }
   501  
   502  func (*H2D) RVersion() int16 {
   503  	return rvers.H2D
   504  }
   505  
   506  func (*H2D) isH2() {}
   507  
   508  // Class returns the ROOT class name.
   509  func (*H2D) Class() string {
   510  	return "TH2D"
   511  }
   512  
   513  func (h *H2D) Array() rcont.ArrayD {
   514  	return h.arr
   515  }
   516  
   517  // Rank returns the number of dimensions of this histogram.
   518  func (h *H2D) Rank() int {
   519  	return 2
   520  }
   521  
   522  // NbinsX returns the number of bins in X.
   523  func (h *H2D) NbinsX() int {
   524  	return h.th1.xaxis.nbins
   525  }
   526  
   527  // XAxis returns the axis along X.
   528  func (h *H2D) XAxis() Axis {
   529  	return &h.th1.xaxis
   530  }
   531  
   532  // XBinCenter returns the bin center value in X.
   533  func (h *H2D) XBinCenter(i int) float64 {
   534  	return float64(h.th1.xaxis.BinCenter(i))
   535  }
   536  
   537  // XBinContent returns the bin content value in X.
   538  func (h *H2D) XBinContent(i int) float64 {
   539  	return float64(h.arr.Data[i])
   540  }
   541  
   542  // XBinError returns the bin error in X.
   543  func (h *H2D) XBinError(i int) float64 {
   544  	if len(h.th1.sumw2.Data) > 0 {
   545  		return math.Sqrt(float64(h.th1.sumw2.Data[i]))
   546  	}
   547  	return math.Sqrt(math.Abs(float64(h.arr.Data[i])))
   548  }
   549  
   550  // XBinLowEdge returns the bin lower edge value in X.
   551  func (h *H2D) XBinLowEdge(i int) float64 {
   552  	return h.th1.xaxis.BinLowEdge(i)
   553  }
   554  
   555  // XBinWidth returns the bin width in X.
   556  func (h *H2D) XBinWidth(i int) float64 {
   557  	return h.th1.xaxis.BinWidth(i)
   558  }
   559  
   560  // NbinsY returns the number of bins in Y.
   561  func (h *H2D) NbinsY() int {
   562  	return h.th1.yaxis.nbins
   563  }
   564  
   565  // YAxis returns the axis along Y.
   566  func (h *H2D) YAxis() Axis {
   567  	return &h.th1.yaxis
   568  }
   569  
   570  // YBinCenter returns the bin center value in Y.
   571  func (h *H2D) YBinCenter(i int) float64 {
   572  	return float64(h.th1.yaxis.BinCenter(i))
   573  }
   574  
   575  // YBinContent returns the bin content value in Y.
   576  func (h *H2D) YBinContent(i int) float64 {
   577  	return float64(h.arr.Data[i])
   578  }
   579  
   580  // YBinError returns the bin error in Y.
   581  func (h *H2D) YBinError(i int) float64 {
   582  	if len(h.th1.sumw2.Data) > 0 {
   583  		return math.Sqrt(float64(h.th1.sumw2.Data[i]))
   584  	}
   585  	return math.Sqrt(math.Abs(float64(h.arr.Data[i])))
   586  }
   587  
   588  // YBinLowEdge returns the bin lower edge value in Y.
   589  func (h *H2D) YBinLowEdge(i int) float64 {
   590  	return h.th1.yaxis.BinLowEdge(i)
   591  }
   592  
   593  // YBinWidth returns the bin width in Y.
   594  func (h *H2D) YBinWidth(i int) float64 {
   595  	return h.th1.yaxis.BinWidth(i)
   596  }
   597  
   598  // bin returns the regularized bin number given an (x,y) bin index pair.
   599  func (h *H2D) bin(ix, iy int) int {
   600  	nx := h.th1.xaxis.nbins + 1 // overflow bin
   601  	ny := h.th1.yaxis.nbins + 1 // overflow bin
   602  	switch {
   603  	case ix < 0:
   604  		ix = 0
   605  	case ix > nx:
   606  		ix = nx
   607  	}
   608  	switch {
   609  	case iy < 0:
   610  		iy = 0
   611  	case iy > ny:
   612  		iy = ny
   613  	}
   614  	return ix + (nx+1)*iy
   615  }
   616  
   617  func (h *H2D) dist2D(ix, iy int) hbook.Dist2D {
   618  	i := h.bin(ix, iy)
   619  	vx := h.XBinContent(i)
   620  	xerr := h.XBinError(i)
   621  	nx := h.entries(vx, xerr)
   622  	vy := h.YBinContent(i)
   623  	yerr := h.YBinError(i)
   624  	ny := h.entries(vy, yerr)
   625  
   626  	sumw := h.arr.Data[i]
   627  	sumw2 := 0.0
   628  	if len(h.th1.sumw2.Data) > 0 {
   629  		sumw2 = h.th1.sumw2.Data[i]
   630  	}
   631  	return hbook.Dist2D{
   632  		X: hbook.Dist1D{
   633  			Dist: hbook.Dist0D{
   634  				N:     nx,
   635  				SumW:  float64(sumw),
   636  				SumW2: float64(sumw2),
   637  			},
   638  		},
   639  		Y: hbook.Dist1D{
   640  			Dist: hbook.Dist0D{
   641  				N:     ny,
   642  				SumW:  float64(sumw),
   643  				SumW2: float64(sumw2),
   644  			},
   645  		},
   646  	}
   647  }
   648  
   649  func (h *H2D) setDist2D(ix, iy int, sumw, sumw2 float64) {
   650  	i := h.bin(ix, iy)
   651  	h.arr.Data[i] = float64(sumw)
   652  	h.th1.sumw2.Data[i] = sumw2
   653  }
   654  
   655  func (h *H2D) entries(height, err float64) int64 {
   656  	if height <= 0 {
   657  		return 0
   658  	}
   659  	v := height / err
   660  	return int64(v*v + 0.5)
   661  }
   662  
   663  // AsH2D creates a new hbook.H2D from this ROOT histogram.
   664  func (h *H2D) AsH2D() *hbook.H2D {
   665  	var (
   666  		nx = h.NbinsX()
   667  		ny = h.NbinsY()
   668  		hh = hbook.NewH2D(
   669  			nx, h.XAxis().XMin(), h.XAxis().XMax(),
   670  			ny, h.YAxis().XMin(), h.YAxis().XMax(),
   671  		)
   672  		xinrange = 1
   673  		yinrange = 1
   674  	)
   675  	hh.Ann = hbook.Annotation{
   676  		"name":  h.Name(),
   677  		"title": h.Title(),
   678  	}
   679  	hh.Binning.Outflows = [8]hbook.Dist2D{
   680  		h.dist2D(0, 0),
   681  		h.dist2D(0, yinrange),
   682  		h.dist2D(0, ny+1),
   683  		h.dist2D(nx+1, 0),
   684  		h.dist2D(nx+1, yinrange),
   685  		h.dist2D(nx+1, ny+1),
   686  		h.dist2D(xinrange, 0),
   687  		h.dist2D(xinrange, ny+1),
   688  	}
   689  
   690  	hh.Binning.Dist = hbook.Dist2D{
   691  		X: hbook.Dist1D{
   692  			Dist: hbook.Dist0D{
   693  				N:     int64(h.Entries()),
   694  				SumW:  float64(h.SumW()),
   695  				SumW2: float64(h.SumW2()),
   696  			},
   697  		},
   698  		Y: hbook.Dist1D{
   699  			Dist: hbook.Dist0D{
   700  				N:     int64(h.Entries()),
   701  				SumW:  float64(h.SumW()),
   702  				SumW2: float64(h.SumW2()),
   703  			},
   704  		},
   705  	}
   706  	hh.Binning.Dist.X.Stats.SumWX = float64(h.SumWX())
   707  	hh.Binning.Dist.X.Stats.SumWX2 = float64(h.SumWX2())
   708  	hh.Binning.Dist.Y.Stats.SumWX = float64(h.SumWY())
   709  	hh.Binning.Dist.Y.Stats.SumWX2 = float64(h.SumWY2())
   710  	hh.Binning.Dist.Stats.SumWXY = h.SumWXY()
   711  
   712  	for ix := range nx {
   713  		for iy := range ny {
   714  			var (
   715  				i    = iy*nx + ix
   716  				xmin = h.XBinLowEdge(ix + 1)
   717  				xmax = h.XBinWidth(ix+1) + xmin
   718  				ymin = h.YBinLowEdge(iy + 1)
   719  				ymax = h.YBinWidth(iy+1) + ymin
   720  				bin  = &hh.Binning.Bins[i]
   721  			)
   722  			bin.XRange.Min = xmin
   723  			bin.XRange.Max = xmax
   724  			bin.YRange.Min = ymin
   725  			bin.YRange.Max = ymax
   726  			bin.Dist = h.dist2D(ix+1, iy+1)
   727  		}
   728  	}
   729  
   730  	return hh
   731  }
   732  
   733  // MarshalYODA implements the YODAMarshaler interface.
   734  func (h *H2D) MarshalYODA() ([]byte, error) {
   735  	return h.AsH2D().MarshalYODA()
   736  }
   737  
   738  // UnmarshalYODA implements the YODAUnmarshaler interface.
   739  func (h *H2D) UnmarshalYODA(raw []byte) error {
   740  	var hh hbook.H2D
   741  	err := hh.UnmarshalYODA(raw)
   742  	if err != nil {
   743  		return err
   744  	}
   745  
   746  	*h = *NewH2DFrom(&hh)
   747  	return nil
   748  }
   749  
   750  func (h *H2D) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   751  	if w.Err() != nil {
   752  		return 0, w.Err()
   753  	}
   754  
   755  	hdr := w.WriteHeader(h.Class(), h.RVersion())
   756  	w.WriteObject(&h.th2)
   757  	w.WriteObject(&h.arr)
   758  
   759  	return w.SetHeader(hdr)
   760  }
   761  
   762  func (h *H2D) UnmarshalROOT(r *rbytes.RBuffer) error {
   763  	if r.Err() != nil {
   764  		return r.Err()
   765  	}
   766  
   767  	hdr := r.ReadHeader(h.Class(), h.RVersion())
   768  	if hdr.Vers < 1 {
   769  		return fmt.Errorf("rhist: TH2D version too old (%d<1)", hdr.Vers)
   770  	}
   771  
   772  	r.ReadObject(&h.th2)
   773  	r.ReadObject(&h.arr)
   774  
   775  	r.CheckHeader(hdr)
   776  	return r.Err()
   777  }
   778  
   779  func (h *H2D) RMembers() (mbrs []rbytes.Member) {
   780  	mbrs = append(mbrs, h.th2.RMembers()...)
   781  	mbrs = append(mbrs, rbytes.Member{
   782  		Name: "fArray", Value: &h.arr.Data,
   783  	})
   784  	return mbrs
   785  }
   786  
   787  func init() {
   788  	f := func() reflect.Value {
   789  		o := newH2D()
   790  		return reflect.ValueOf(o)
   791  	}
   792  	rtypes.Factory.Add("TH2D", f)
   793  }
   794  
   795  var (
   796  	_ root.Object        = (*H2D)(nil)
   797  	_ root.Named         = (*H2D)(nil)
   798  	_ H2                 = (*H2D)(nil)
   799  	_ rbytes.Marshaler   = (*H2D)(nil)
   800  	_ rbytes.Unmarshaler = (*H2D)(nil)
   801  	_ rbytes.RSlicer     = (*H2D)(nil)
   802  )
   803  
   804  // H2I implements ROOT TH2I
   805  type H2I struct {
   806  	th2
   807  	arr rcont.ArrayI
   808  }
   809  
   810  func newH2I() *H2I {
   811  	return &H2I{
   812  		th2: *newH2(),
   813  	}
   814  }
   815  
   816  // NewH2IFrom creates a new H2I from hbook 2-dim histogram.
   817  func NewH2IFrom(h *hbook.H2D) *H2I {
   818  	var (
   819  		hroot  = newH2I()
   820  		bins   = h.Binning.Bins
   821  		nxbins = h.Binning.Nx
   822  		nybins = h.Binning.Ny
   823  		xedges = make([]float64, 0, nxbins+1)
   824  		yedges = make([]float64, 0, nybins+1)
   825  	)
   826  
   827  	hroot.th2.th1.entries = float64(h.Entries())
   828  	hroot.th2.th1.tsumw = h.SumW()
   829  	hroot.th2.th1.tsumw2 = h.SumW2()
   830  	hroot.th2.th1.tsumwx = h.SumWX()
   831  	hroot.th2.th1.tsumwx2 = h.SumWX2()
   832  	hroot.th2.tsumwy = h.SumWY()
   833  	hroot.th2.tsumwy2 = h.SumWY2()
   834  	hroot.th2.tsumwxy = h.SumWXY()
   835  
   836  	ncells := (nxbins + 2) * (nybins + 2)
   837  	hroot.th2.th1.ncells = ncells
   838  
   839  	hroot.th2.th1.xaxis.nbins = nxbins
   840  	hroot.th2.th1.xaxis.xmin = h.XMin()
   841  	hroot.th2.th1.xaxis.xmax = h.XMax()
   842  
   843  	hroot.th2.th1.yaxis.nbins = nybins
   844  	hroot.th2.th1.yaxis.xmin = h.YMin()
   845  	hroot.th2.th1.yaxis.xmax = h.YMax()
   846  
   847  	hroot.arr.Data = make([]int32, ncells)
   848  	hroot.th2.th1.sumw2.Data = make([]float64, ncells)
   849  
   850  	ibin := func(ix, iy int) int { return iy*nxbins + ix }
   851  
   852  	for ix := range h.Binning.Nx {
   853  		for iy := range h.Binning.Ny {
   854  			i := ibin(ix, iy)
   855  			bin := bins[i]
   856  			if ix == 0 {
   857  				yedges = append(yedges, bin.YMin())
   858  			}
   859  			if iy == 0 {
   860  				xedges = append(xedges, bin.XMin())
   861  			}
   862  			hroot.setDist2D(ix+1, iy+1, bin.Dist.SumW(), bin.Dist.SumW2())
   863  		}
   864  	}
   865  
   866  	oflows := h.Binning.Outflows[:]
   867  	for i, v := range []struct{ ix, iy int }{
   868  		{0, 0},
   869  		{0, 1},
   870  		{0, nybins + 1},
   871  		{nxbins + 1, 0},
   872  		{nxbins + 1, 1},
   873  		{nxbins + 1, nybins + 1},
   874  		{1, 0},
   875  		{1, nybins + 1},
   876  	} {
   877  		hroot.setDist2D(v.ix, v.iy, oflows[i].SumW(), oflows[i].SumW2())
   878  	}
   879  
   880  	xedges = append(xedges, bins[ibin(h.Binning.Nx-1, 0)].XMax())
   881  	yedges = append(yedges, bins[ibin(0, h.Binning.Ny-1)].YMax())
   882  
   883  	hroot.th2.th1.SetName(h.Name())
   884  	if v, ok := h.Annotation()["title"]; ok && v != nil {
   885  		hroot.th2.th1.SetTitle(v.(string))
   886  	}
   887  	hroot.th2.th1.xaxis.xbins.Data = xedges
   888  	hroot.th2.th1.yaxis.xbins.Data = yedges
   889  
   890  	return hroot
   891  }
   892  
   893  func (*H2I) RVersion() int16 {
   894  	return rvers.H2I
   895  }
   896  
   897  func (*H2I) isH2() {}
   898  
   899  // Class returns the ROOT class name.
   900  func (*H2I) Class() string {
   901  	return "TH2I"
   902  }
   903  
   904  func (h *H2I) Array() rcont.ArrayI {
   905  	return h.arr
   906  }
   907  
   908  // Rank returns the number of dimensions of this histogram.
   909  func (h *H2I) Rank() int {
   910  	return 2
   911  }
   912  
   913  // NbinsX returns the number of bins in X.
   914  func (h *H2I) NbinsX() int {
   915  	return h.th1.xaxis.nbins
   916  }
   917  
   918  // XAxis returns the axis along X.
   919  func (h *H2I) XAxis() Axis {
   920  	return &h.th1.xaxis
   921  }
   922  
   923  // XBinCenter returns the bin center value in X.
   924  func (h *H2I) XBinCenter(i int) float64 {
   925  	return float64(h.th1.xaxis.BinCenter(i))
   926  }
   927  
   928  // XBinContent returns the bin content value in X.
   929  func (h *H2I) XBinContent(i int) float64 {
   930  	return float64(h.arr.Data[i])
   931  }
   932  
   933  // XBinError returns the bin error in X.
   934  func (h *H2I) XBinError(i int) float64 {
   935  	if len(h.th1.sumw2.Data) > 0 {
   936  		return math.Sqrt(float64(h.th1.sumw2.Data[i]))
   937  	}
   938  	return math.Sqrt(math.Abs(float64(h.arr.Data[i])))
   939  }
   940  
   941  // XBinLowEdge returns the bin lower edge value in X.
   942  func (h *H2I) XBinLowEdge(i int) float64 {
   943  	return h.th1.xaxis.BinLowEdge(i)
   944  }
   945  
   946  // XBinWidth returns the bin width in X.
   947  func (h *H2I) XBinWidth(i int) float64 {
   948  	return h.th1.xaxis.BinWidth(i)
   949  }
   950  
   951  // NbinsY returns the number of bins in Y.
   952  func (h *H2I) NbinsY() int {
   953  	return h.th1.yaxis.nbins
   954  }
   955  
   956  // YAxis returns the axis along Y.
   957  func (h *H2I) YAxis() Axis {
   958  	return &h.th1.yaxis
   959  }
   960  
   961  // YBinCenter returns the bin center value in Y.
   962  func (h *H2I) YBinCenter(i int) float64 {
   963  	return float64(h.th1.yaxis.BinCenter(i))
   964  }
   965  
   966  // YBinContent returns the bin content value in Y.
   967  func (h *H2I) YBinContent(i int) float64 {
   968  	return float64(h.arr.Data[i])
   969  }
   970  
   971  // YBinError returns the bin error in Y.
   972  func (h *H2I) YBinError(i int) float64 {
   973  	if len(h.th1.sumw2.Data) > 0 {
   974  		return math.Sqrt(float64(h.th1.sumw2.Data[i]))
   975  	}
   976  	return math.Sqrt(math.Abs(float64(h.arr.Data[i])))
   977  }
   978  
   979  // YBinLowEdge returns the bin lower edge value in Y.
   980  func (h *H2I) YBinLowEdge(i int) float64 {
   981  	return h.th1.yaxis.BinLowEdge(i)
   982  }
   983  
   984  // YBinWidth returns the bin width in Y.
   985  func (h *H2I) YBinWidth(i int) float64 {
   986  	return h.th1.yaxis.BinWidth(i)
   987  }
   988  
   989  // bin returns the regularized bin number given an (x,y) bin index pair.
   990  func (h *H2I) bin(ix, iy int) int {
   991  	nx := h.th1.xaxis.nbins + 1 // overflow bin
   992  	ny := h.th1.yaxis.nbins + 1 // overflow bin
   993  	switch {
   994  	case ix < 0:
   995  		ix = 0
   996  	case ix > nx:
   997  		ix = nx
   998  	}
   999  	switch {
  1000  	case iy < 0:
  1001  		iy = 0
  1002  	case iy > ny:
  1003  		iy = ny
  1004  	}
  1005  	return ix + (nx+1)*iy
  1006  }
  1007  
  1008  func (h *H2I) dist2D(ix, iy int) hbook.Dist2D {
  1009  	i := h.bin(ix, iy)
  1010  	vx := h.XBinContent(i)
  1011  	xerr := h.XBinError(i)
  1012  	nx := h.entries(vx, xerr)
  1013  	vy := h.YBinContent(i)
  1014  	yerr := h.YBinError(i)
  1015  	ny := h.entries(vy, yerr)
  1016  
  1017  	sumw := h.arr.Data[i]
  1018  	sumw2 := 0.0
  1019  	if len(h.th1.sumw2.Data) > 0 {
  1020  		sumw2 = h.th1.sumw2.Data[i]
  1021  	}
  1022  	return hbook.Dist2D{
  1023  		X: hbook.Dist1D{
  1024  			Dist: hbook.Dist0D{
  1025  				N:     nx,
  1026  				SumW:  float64(sumw),
  1027  				SumW2: float64(sumw2),
  1028  			},
  1029  		},
  1030  		Y: hbook.Dist1D{
  1031  			Dist: hbook.Dist0D{
  1032  				N:     ny,
  1033  				SumW:  float64(sumw),
  1034  				SumW2: float64(sumw2),
  1035  			},
  1036  		},
  1037  	}
  1038  }
  1039  
  1040  func (h *H2I) setDist2D(ix, iy int, sumw, sumw2 float64) {
  1041  	i := h.bin(ix, iy)
  1042  	h.arr.Data[i] = int32(sumw)
  1043  	h.th1.sumw2.Data[i] = sumw2
  1044  }
  1045  
  1046  func (h *H2I) entries(height, err float64) int64 {
  1047  	if height <= 0 {
  1048  		return 0
  1049  	}
  1050  	v := height / err
  1051  	return int64(v*v + 0.5)
  1052  }
  1053  
  1054  // AsH2D creates a new hbook.H2D from this ROOT histogram.
  1055  func (h *H2I) AsH2D() *hbook.H2D {
  1056  	var (
  1057  		nx = h.NbinsX()
  1058  		ny = h.NbinsY()
  1059  		hh = hbook.NewH2D(
  1060  			nx, h.XAxis().XMin(), h.XAxis().XMax(),
  1061  			ny, h.YAxis().XMin(), h.YAxis().XMax(),
  1062  		)
  1063  		xinrange = 1
  1064  		yinrange = 1
  1065  	)
  1066  	hh.Ann = hbook.Annotation{
  1067  		"name":  h.Name(),
  1068  		"title": h.Title(),
  1069  	}
  1070  	hh.Binning.Outflows = [8]hbook.Dist2D{
  1071  		h.dist2D(0, 0),
  1072  		h.dist2D(0, yinrange),
  1073  		h.dist2D(0, ny+1),
  1074  		h.dist2D(nx+1, 0),
  1075  		h.dist2D(nx+1, yinrange),
  1076  		h.dist2D(nx+1, ny+1),
  1077  		h.dist2D(xinrange, 0),
  1078  		h.dist2D(xinrange, ny+1),
  1079  	}
  1080  
  1081  	hh.Binning.Dist = hbook.Dist2D{
  1082  		X: hbook.Dist1D{
  1083  			Dist: hbook.Dist0D{
  1084  				N:     int64(h.Entries()),
  1085  				SumW:  float64(h.SumW()),
  1086  				SumW2: float64(h.SumW2()),
  1087  			},
  1088  		},
  1089  		Y: hbook.Dist1D{
  1090  			Dist: hbook.Dist0D{
  1091  				N:     int64(h.Entries()),
  1092  				SumW:  float64(h.SumW()),
  1093  				SumW2: float64(h.SumW2()),
  1094  			},
  1095  		},
  1096  	}
  1097  	hh.Binning.Dist.X.Stats.SumWX = float64(h.SumWX())
  1098  	hh.Binning.Dist.X.Stats.SumWX2 = float64(h.SumWX2())
  1099  	hh.Binning.Dist.Y.Stats.SumWX = float64(h.SumWY())
  1100  	hh.Binning.Dist.Y.Stats.SumWX2 = float64(h.SumWY2())
  1101  	hh.Binning.Dist.Stats.SumWXY = h.SumWXY()
  1102  
  1103  	for ix := range nx {
  1104  		for iy := range ny {
  1105  			var (
  1106  				i    = iy*nx + ix
  1107  				xmin = h.XBinLowEdge(ix + 1)
  1108  				xmax = h.XBinWidth(ix+1) + xmin
  1109  				ymin = h.YBinLowEdge(iy + 1)
  1110  				ymax = h.YBinWidth(iy+1) + ymin
  1111  				bin  = &hh.Binning.Bins[i]
  1112  			)
  1113  			bin.XRange.Min = xmin
  1114  			bin.XRange.Max = xmax
  1115  			bin.YRange.Min = ymin
  1116  			bin.YRange.Max = ymax
  1117  			bin.Dist = h.dist2D(ix+1, iy+1)
  1118  		}
  1119  	}
  1120  
  1121  	return hh
  1122  }
  1123  
  1124  // MarshalYODA implements the YODAMarshaler interface.
  1125  func (h *H2I) MarshalYODA() ([]byte, error) {
  1126  	return h.AsH2D().MarshalYODA()
  1127  }
  1128  
  1129  // UnmarshalYODA implements the YODAUnmarshaler interface.
  1130  func (h *H2I) UnmarshalYODA(raw []byte) error {
  1131  	var hh hbook.H2D
  1132  	err := hh.UnmarshalYODA(raw)
  1133  	if err != nil {
  1134  		return err
  1135  	}
  1136  
  1137  	*h = *NewH2IFrom(&hh)
  1138  	return nil
  1139  }
  1140  
  1141  func (h *H2I) MarshalROOT(w *rbytes.WBuffer) (int, error) {
  1142  	if w.Err() != nil {
  1143  		return 0, w.Err()
  1144  	}
  1145  
  1146  	hdr := w.WriteHeader(h.Class(), h.RVersion())
  1147  	w.WriteObject(&h.th2)
  1148  	w.WriteObject(&h.arr)
  1149  
  1150  	return w.SetHeader(hdr)
  1151  }
  1152  
  1153  func (h *H2I) UnmarshalROOT(r *rbytes.RBuffer) error {
  1154  	if r.Err() != nil {
  1155  		return r.Err()
  1156  	}
  1157  
  1158  	hdr := r.ReadHeader(h.Class(), h.RVersion())
  1159  	if hdr.Vers < 1 {
  1160  		return fmt.Errorf("rhist: TH2I version too old (%d<1)", hdr.Vers)
  1161  	}
  1162  
  1163  	r.ReadObject(&h.th2)
  1164  	r.ReadObject(&h.arr)
  1165  
  1166  	r.CheckHeader(hdr)
  1167  	return r.Err()
  1168  }
  1169  
  1170  func (h *H2I) RMembers() (mbrs []rbytes.Member) {
  1171  	mbrs = append(mbrs, h.th2.RMembers()...)
  1172  	mbrs = append(mbrs, rbytes.Member{
  1173  		Name: "fArray", Value: &h.arr.Data,
  1174  	})
  1175  	return mbrs
  1176  }
  1177  
  1178  func init() {
  1179  	f := func() reflect.Value {
  1180  		o := newH2I()
  1181  		return reflect.ValueOf(o)
  1182  	}
  1183  	rtypes.Factory.Add("TH2I", f)
  1184  }
  1185  
  1186  var (
  1187  	_ root.Object        = (*H2I)(nil)
  1188  	_ root.Named         = (*H2I)(nil)
  1189  	_ H2                 = (*H2I)(nil)
  1190  	_ rbytes.Marshaler   = (*H2I)(nil)
  1191  	_ rbytes.Unmarshaler = (*H2I)(nil)
  1192  	_ rbytes.RSlicer     = (*H2I)(nil)
  1193  )