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

     1  // Copyright ©2017 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 rhist
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  
    11  	"go-hep.org/x/hep/groot/rbase"
    12  	"go-hep.org/x/hep/groot/rbytes"
    13  	"go-hep.org/x/hep/groot/rcont"
    14  	"go-hep.org/x/hep/groot/root"
    15  	"go-hep.org/x/hep/groot/rtypes"
    16  	"go-hep.org/x/hep/groot/rvers"
    17  )
    18  
    19  type th1 struct {
    20  	rbase.Named
    21  	attline   rbase.AttLine
    22  	attfill   rbase.AttFill
    23  	attmarker rbase.AttMarker
    24  	ncells    int          // number of bins + under/over-flows
    25  	xaxis     taxis        // x axis descriptor
    26  	yaxis     taxis        // y axis descriptor
    27  	zaxis     taxis        // z axis descriptor
    28  	boffset   int16        // (1000*offset) for bar charts or legos
    29  	bwidth    int16        // (1000*width) for bar charts or legos
    30  	entries   float64      // number of entries
    31  	tsumw     float64      // total sum of weights
    32  	tsumw2    float64      // total sum of squares of weights
    33  	tsumwx    float64      // total sum of weight*x
    34  	tsumwx2   float64      // total sum of weight*x*x
    35  	max       float64      // maximum value for plotting
    36  	min       float64      // minimum value for plotting
    37  	norm      float64      // normalization factor
    38  	contour   rcont.ArrayD // array to display contour levels
    39  	sumw2     rcont.ArrayD // array of sum of squares of weights
    40  	opt       string       // histogram options
    41  	funcs     rcont.List   // list of functions (fits and user)
    42  	buffer    []float64    // entry buffer
    43  	erropt    int32        // option for bin statistical errors
    44  	oflow     int32        // per object flag to use under/overflows in statistics
    45  }
    46  
    47  func newH1() *th1 {
    48  	return &th1{
    49  		Named:     *rbase.NewNamed("", ""),
    50  		attline:   *rbase.NewAttLine(),
    51  		attfill:   *rbase.NewAttFill(),
    52  		attmarker: *rbase.NewAttMarker(),
    53  		xaxis:     *NewAxis("xaxis"),
    54  		yaxis:     *NewAxis("yaxis"),
    55  		zaxis:     *NewAxis("zaxis"),
    56  		bwidth:    1000,
    57  		max:       -1111,
    58  		min:       -1111,
    59  		funcs:     *rcont.NewList("", nil),
    60  		oflow:     2, // kNeutral
    61  	}
    62  }
    63  
    64  func (*th1) RVersion() int16 {
    65  	return rvers.H1
    66  }
    67  
    68  func (h *th1) Class() string {
    69  	return "TH1"
    70  }
    71  
    72  // Entries returns the number of entries for this histogram.
    73  func (h *th1) Entries() float64 {
    74  	return h.entries
    75  }
    76  
    77  // SumW returns the total sum of weights
    78  func (h *th1) SumW() float64 {
    79  	return h.tsumw
    80  }
    81  
    82  // SumW2 returns the total sum of squares of weights
    83  func (h *th1) SumW2() float64 {
    84  	return h.tsumw2
    85  }
    86  
    87  // SumWX returns the total sum of weights*x
    88  func (h *th1) SumWX() float64 {
    89  	return h.tsumwx
    90  }
    91  
    92  // SumWX2 returns the total sum of weights*x*x
    93  func (h *th1) SumWX2() float64 {
    94  	return h.tsumwx2
    95  }
    96  
    97  // SumW2s returns the array of sum of squares of weights
    98  func (h *th1) SumW2s() []float64 {
    99  	return h.sumw2.Data
   100  }
   101  
   102  func (h *th1) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   103  	if w.Err() != nil {
   104  		return 0, w.Err()
   105  	}
   106  
   107  	hdr := w.WriteHeader(h.Class(), h.RVersion())
   108  	w.WriteObject(&h.Named)
   109  	w.WriteObject(&h.attline)
   110  	w.WriteObject(&h.attfill)
   111  	w.WriteObject(&h.attmarker)
   112  
   113  	w.WriteI32(int32(h.ncells))
   114  
   115  	w.WriteObject(&h.xaxis)
   116  	w.WriteObject(&h.yaxis)
   117  	w.WriteObject(&h.zaxis)
   118  	w.WriteI16(h.boffset)
   119  	w.WriteI16(h.bwidth)
   120  	w.WriteF64(h.entries)
   121  	w.WriteF64(h.tsumw)
   122  	w.WriteF64(h.tsumw2)
   123  	w.WriteF64(h.tsumwx)
   124  	w.WriteF64(h.tsumwx2)
   125  	w.WriteF64(h.max)
   126  	w.WriteF64(h.min)
   127  	w.WriteF64(h.norm)
   128  	w.WriteObject(&h.contour)
   129  	w.WriteObject(&h.sumw2)
   130  	w.WriteString(h.opt)
   131  	w.WriteObject(&h.funcs)
   132  
   133  	w.WriteI32(int32(len(h.buffer)))
   134  	w.WriteI8(0) // FIXME(sbinet)
   135  	w.WriteArrayF64(h.buffer)
   136  	w.WriteI32(h.erropt)
   137  	if h.RVersion() > 7 {
   138  		w.WriteI32(h.oflow)
   139  	}
   140  
   141  	return w.SetHeader(hdr)
   142  }
   143  
   144  func (h *th1) UnmarshalROOT(r *rbytes.RBuffer) error {
   145  	if r.Err() != nil {
   146  		return r.Err()
   147  	}
   148  
   149  	hdr := r.ReadHeader(h.Class(), h.RVersion())
   150  
   151  	r.ReadObject(&h.Named)
   152  	r.ReadObject(&h.attline)
   153  	r.ReadObject(&h.attfill)
   154  	r.ReadObject(&h.attmarker)
   155  
   156  	h.ncells = int(r.ReadI32())
   157  
   158  	r.ReadObject(&h.xaxis)
   159  	r.ReadObject(&h.yaxis)
   160  	r.ReadObject(&h.zaxis)
   161  
   162  	h.boffset = r.ReadI16()
   163  	h.bwidth = r.ReadI16()
   164  	h.entries = r.ReadF64()
   165  	h.tsumw = r.ReadF64()
   166  	h.tsumw2 = r.ReadF64()
   167  	h.tsumwx = r.ReadF64()
   168  	h.tsumwx2 = r.ReadF64()
   169  	if hdr.Vers < 2 {
   170  		h.max = float64(r.ReadF32())
   171  		h.min = float64(r.ReadF32())
   172  		h.norm = float64(r.ReadF32())
   173  		n := int(r.ReadI32())
   174  		h.contour.Data = rbytes.ResizeF64(h.contour.Data, n)
   175  		r.ReadArrayF64(h.contour.Data)
   176  	} else {
   177  		h.max = r.ReadF64()
   178  		h.min = r.ReadF64()
   179  		h.norm = r.ReadF64()
   180  		r.ReadObject(&h.contour)
   181  	}
   182  
   183  	r.ReadObject(&h.sumw2)
   184  	h.opt = r.ReadString()
   185  	r.ReadObject(&h.funcs)
   186  
   187  	if hdr.Vers > 3 {
   188  		n := int(r.ReadI32())
   189  		_ = r.ReadI8()
   190  		h.buffer = rbytes.ResizeF64(h.buffer, n)
   191  		r.ReadArrayF64(h.buffer)
   192  		if hdr.Vers > 6 {
   193  			h.erropt = r.ReadI32()
   194  		}
   195  		if hdr.Vers > 7 {
   196  			h.oflow = r.ReadI32()
   197  		}
   198  	}
   199  
   200  	r.CheckHeader(hdr)
   201  	return r.Err()
   202  }
   203  
   204  func (h *th1) RMembers() (mbrs []rbytes.Member) {
   205  	mbrs = append(mbrs, h.Named.RMembers()...)
   206  	mbrs = append(mbrs, h.attline.RMembers()...)
   207  	mbrs = append(mbrs, h.attfill.RMembers()...)
   208  	mbrs = append(mbrs, h.attmarker.RMembers()...)
   209  	mbrs = append(mbrs, []rbytes.Member{
   210  		{Name: "fNcells", Value: &h.ncells},
   211  		{Name: "fXaxis", Value: &h.xaxis},
   212  		{Name: "fYaxis", Value: &h.yaxis},
   213  		{Name: "fZaxis", Value: &h.zaxis},
   214  		{Name: "fBarOffset", Value: &h.boffset},
   215  		{Name: "fBarWidth", Value: &h.bwidth},
   216  		{Name: "fEntries", Value: &h.entries},
   217  		{Name: "fTsumw", Value: &h.tsumw},
   218  		{Name: "fTsumw2", Value: &h.tsumw2},
   219  		{Name: "fTsumwx", Value: &h.tsumwx},
   220  		{Name: "fTsumwx2", Value: &h.tsumwx2},
   221  		{Name: "fMaximum", Value: &h.max},
   222  		{Name: "fMinimum", Value: &h.min},
   223  		{Name: "fNormFactor", Value: &h.norm},
   224  		{Name: "fContour", Value: &h.contour.Data},
   225  		{Name: "fSumw2", Value: &h.sumw2.Data},
   226  		{Name: "fOption", Value: &h.opt},
   227  		{Name: "fFunctions", Value: &h.funcs},
   228  		{Name: "fBufferSize", Value: len(h.buffer)}, // FIXME(sbinet)
   229  		{Name: "fBuffer", Value: &h.buffer},
   230  		{Name: "fBinStatErrOpt", Value: &h.erropt},
   231  		{Name: "fStatOverflows", Value: &h.oflow},
   232  	}...)
   233  
   234  	return mbrs
   235  }
   236  
   237  // Keys implements the ObjectFinder interface.
   238  func (h *th1) Keys() []string {
   239  	var keys []string
   240  	for i := range h.funcs.Len() {
   241  		o, ok := h.funcs.At(i).(root.Named)
   242  		if !ok {
   243  			continue
   244  		}
   245  		keys = append(keys, o.Name())
   246  	}
   247  	return keys
   248  }
   249  
   250  // Get implements the ObjectFinder interface.
   251  func (h *th1) Get(name string) (root.Object, error) {
   252  	for i := range h.funcs.Len() {
   253  		o, ok := h.funcs.At(i).(root.Named)
   254  		if !ok {
   255  			continue
   256  		}
   257  		if o.Name() == name {
   258  			return h.funcs.At(i), nil
   259  		}
   260  	}
   261  
   262  	return nil, fmt.Errorf("no object named %q", name)
   263  }
   264  
   265  type th2 struct {
   266  	th1
   267  	scale   float64 // scale factor
   268  	tsumwy  float64 // total sum of weight*y
   269  	tsumwy2 float64 // total sum of weight*y*y
   270  	tsumwxy float64 // total sum of weight*x*y
   271  }
   272  
   273  func newH2() *th2 {
   274  	return &th2{
   275  		th1: *newH1(),
   276  	}
   277  }
   278  
   279  func (*th2) RVersion() int16 {
   280  	return rvers.H2
   281  }
   282  
   283  func (*th2) Class() string {
   284  	return "TH2"
   285  }
   286  
   287  func (h *th2) MarshalROOT(w *rbytes.WBuffer) (int, error) {
   288  	if w.Err() != nil {
   289  		return 0, w.Err()
   290  	}
   291  
   292  	hdr := w.WriteHeader(h.Class(), h.RVersion())
   293  
   294  	w.WriteObject(&h.th1)
   295  	w.WriteF64(h.scale)
   296  	w.WriteF64(h.tsumwy)
   297  	w.WriteF64(h.tsumwy2)
   298  	w.WriteF64(h.tsumwxy)
   299  
   300  	return w.SetHeader(hdr)
   301  }
   302  
   303  func (h *th2) UnmarshalROOT(r *rbytes.RBuffer) error {
   304  	if r.Err() != nil {
   305  		return r.Err()
   306  	}
   307  
   308  	hdr := r.ReadHeader(h.Class(), h.RVersion())
   309  	if hdr.Vers < 3 {
   310  		return fmt.Errorf("rhist: TH2 version too old (%d<3)", hdr.Vers)
   311  	}
   312  
   313  	r.ReadObject(&h.th1)
   314  	h.scale = r.ReadF64()
   315  	h.tsumwy = r.ReadF64()
   316  	h.tsumwy2 = r.ReadF64()
   317  	h.tsumwxy = r.ReadF64()
   318  
   319  	r.CheckHeader(hdr)
   320  	return r.Err()
   321  }
   322  
   323  func (h *th2) RMembers() (mbrs []rbytes.Member) {
   324  	mbrs = append(mbrs, h.th1.RMembers()...)
   325  	mbrs = append(mbrs, []rbytes.Member{
   326  		{Name: "fScalefactor", Value: &h.scale},
   327  		{Name: "fTsumwy", Value: &h.tsumwy},
   328  		{Name: "fTsumwy2", Value: &h.tsumwy2},
   329  		{Name: "fTsumwxy", Value: &h.tsumwxy},
   330  	}...)
   331  
   332  	return mbrs
   333  }
   334  
   335  // SumWY returns the total sum of weights*y
   336  func (h *th2) SumWY() float64 {
   337  	return h.tsumwy
   338  }
   339  
   340  // SumWY2 returns the total sum of weights*y*y
   341  func (h *th2) SumWY2() float64 {
   342  	return h.tsumwy2
   343  }
   344  
   345  // SumWXY returns the total sum of weights*x*y
   346  func (h *th2) SumWXY() float64 {
   347  	return h.tsumwxy
   348  }
   349  
   350  func init() {
   351  	{
   352  		f := func() reflect.Value {
   353  			o := newH1()
   354  			return reflect.ValueOf(o)
   355  		}
   356  		rtypes.Factory.Add("TH1", f)
   357  	}
   358  	{
   359  		f := func() reflect.Value {
   360  			o := newH2()
   361  			return reflect.ValueOf(o)
   362  		}
   363  		rtypes.Factory.Add("TH2", f)
   364  	}
   365  }
   366  
   367  var (
   368  	_ root.Object        = (*th1)(nil)
   369  	_ root.Named         = (*th1)(nil)
   370  	_ root.ObjectFinder  = (*th1)(nil)
   371  	_ rbytes.Marshaler   = (*th1)(nil)
   372  	_ rbytes.Unmarshaler = (*th1)(nil)
   373  	_ rbytes.RSlicer     = (*th1)(nil)
   374  
   375  	_ root.Object        = (*th2)(nil)
   376  	_ root.Named         = (*th2)(nil)
   377  	_ root.ObjectFinder  = (*th2)(nil)
   378  	_ rbytes.Marshaler   = (*th2)(nil)
   379  	_ rbytes.Unmarshaler = (*th2)(nil)
   380  )