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 )