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 )