go-hep.org/x/hep@v0.38.1/groot/rtree/tree.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 rtree 6 7 import ( 8 "fmt" 9 "reflect" 10 "strings" 11 12 "go-hep.org/x/hep/groot/rbase" 13 "go-hep.org/x/hep/groot/rbytes" 14 "go-hep.org/x/hep/groot/rcont" 15 "go-hep.org/x/hep/groot/rdict" 16 "go-hep.org/x/hep/groot/riofs" 17 "go-hep.org/x/hep/groot/rmeta" 18 "go-hep.org/x/hep/groot/root" 19 "go-hep.org/x/hep/groot/rtypes" 20 "go-hep.org/x/hep/groot/rvers" 21 ) 22 23 // A ttree object is a list of Branch. 24 // 25 // To Create a TTree object one must: 26 // - Create the TTree header via the TTree constructor 27 // - Call the TBranch constructor for every branch. 28 // 29 // To Fill this object, use member function Fill with no parameters 30 // The Fill function loops on all defined TBranch 31 type ttree struct { 32 f *riofs.File // underlying file 33 dir riofs.Directory // directory holding this tree 34 35 rvers int16 36 named rbase.Named 37 attline rbase.AttLine 38 attfill rbase.AttFill 39 attmarker rbase.AttMarker 40 41 entries int64 // Number of entries 42 totBytes int64 // Total number of bytes in all branches before compression 43 zipBytes int64 // Total number of bytes in all branches after compression 44 savedBytes int64 // number of autosaved bytes 45 flushedBytes int64 // number of auto-flushed bytes 46 weight float64 // tree weight 47 timerInterval int32 // timer interval in milliseconds 48 scanField int32 // number of runs before prompting in Scan 49 update int32 // update frequency for entry-loop 50 51 defaultEntryOffsetLen int32 // initial length of the entry offset table in the basket buffers 52 maxEntries int64 // maximum number of entries in case of circular buffers 53 maxEntryLoop int64 // maximum number of entries to process 54 maxVirtualSize int64 // maximum total size of buffers kept in memory 55 autoSave int64 // autosave tree when autoSave entries written 56 autoFlush int64 // autoflush tree when autoFlush entries written 57 estimate int64 // number of entries to estimate histogram limits 58 59 clusters clusters 60 61 iobits tioFeatures // IO features to define for newly-written baskets and branches 62 63 branches []Branch // list of branches 64 leaves []Leaf // direct pointers to individual branch leaves 65 66 aliases *rcont.List // list of aliases for expressions based on the tree branches 67 indexValues *rcont.ArrayD // sorted index values 68 index *rcont.ArrayI // index of sorted values 69 treeIndex root.Object // pointer to the tree index (if any) // FIXME(sbinet): impl TVirtualIndex? 70 friends *rcont.List // pointer to the list of firend elements 71 userInfo *rcont.List // pointer to a list of user objects associated with this tree 72 branchRef root.Object // branch supporting the reftable (if any) // FIXME(sbinet): impl TBranchRef? 73 } 74 75 type clusters struct { 76 ranges []int64 // last entry to a cluster range 77 sizes []int64 // number of entries in each cluster for a given range 78 } 79 80 func (*ttree) RVersion() int16 { 81 return rvers.Tree 82 } 83 84 func (tree *ttree) Class() string { 85 return "TTree" 86 } 87 88 func (tree *ttree) Name() string { 89 return tree.named.Name() 90 } 91 92 func (tree *ttree) Title() string { 93 return tree.named.Title() 94 } 95 96 func (tree *ttree) Entries() int64 { 97 return tree.entries 98 } 99 100 func (tree *ttree) TotBytes() int64 { 101 return tree.totBytes 102 } 103 104 func (tree *ttree) ZipBytes() int64 { 105 return tree.zipBytes 106 } 107 108 func (tree *ttree) Branches() []Branch { 109 return tree.branches 110 } 111 112 func (tree *ttree) Branch(name string) Branch { 113 for _, br := range tree.branches { 114 if br.Name() == name { 115 return br 116 } 117 for _, b1 := range br.Branches() { 118 if b1.Name() == name { 119 return b1 120 } 121 122 for _, b2 := range b1.Branches() { 123 if b2.Name() == name { 124 return b2 125 } 126 } 127 } 128 } 129 130 // search using leaves. 131 for _, leaf := range tree.leaves { 132 b := leaf.Branch() 133 if b.Name() == name { 134 return b 135 } 136 } 137 138 return nil 139 } 140 141 func (tree *ttree) Leaves() []Leaf { 142 return tree.leaves 143 } 144 145 func (tree *ttree) Leaf(name string) Leaf { 146 for _, leaf := range tree.leaves { 147 if leaf.Name() == name { 148 return leaf 149 } 150 } 151 return nil 152 } 153 154 func (tree *ttree) SetFile(f *riofs.File) { tree.f = f } 155 func (tree *ttree) getFile() *riofs.File { return tree.f } 156 157 func (tree *ttree) MarshalROOT(w *rbytes.WBuffer) (int, error) { 158 if w.Err() != nil { 159 return 0, w.Err() 160 } 161 162 hdr := w.WriteHeader(tree.Class(), tree.RVersion()) 163 w.WriteObject(&tree.named) 164 w.WriteObject(&tree.attline) 165 w.WriteObject(&tree.attfill) 166 w.WriteObject(&tree.attmarker) 167 168 w.WriteI64(tree.entries) 169 w.WriteI64(tree.totBytes) 170 w.WriteI64(tree.zipBytes) 171 w.WriteI64(tree.savedBytes) 172 w.WriteI64(tree.flushedBytes) 173 w.WriteF64(tree.weight) 174 w.WriteI32(tree.timerInterval) 175 w.WriteI32(tree.scanField) 176 w.WriteI32(tree.update) 177 w.WriteI32(tree.defaultEntryOffsetLen) 178 w.WriteI32(int32(len(tree.clusters.ranges))) 179 180 w.WriteI64(tree.maxEntries) 181 w.WriteI64(tree.maxEntryLoop) 182 w.WriteI64(tree.maxVirtualSize) 183 w.WriteI64(tree.autoSave) 184 185 w.WriteI64(tree.autoFlush) 186 w.WriteI64(tree.estimate) 187 188 w.WriteI8(0) 189 w.WriteArrayI64(tree.clusters.ranges) 190 w.WriteI8(0) 191 w.WriteArrayI64(tree.clusters.sizes) 192 193 w.WriteObject(&tree.iobits) 194 195 { 196 branches := rcont.NewObjArray() 197 if len(tree.branches) > 0 { 198 elems := make([]root.Object, len(tree.branches)) 199 for i, v := range tree.branches { 200 elems[i] = v 201 } 202 branches.SetElems(elems) 203 } 204 w.WriteObject(branches) 205 } 206 { 207 leaves := rcont.NewObjArray() 208 if len(tree.leaves) > 0 { 209 elems := make([]root.Object, len(tree.leaves)) 210 for i, v := range tree.leaves { 211 elems[i] = v 212 } 213 leaves.SetElems(elems) 214 } 215 w.WriteObject(leaves) 216 } 217 218 { 219 var obj root.Object 220 if tree.aliases != nil { 221 obj = tree.aliases 222 } 223 w.WriteObjectAny(obj) 224 } 225 226 { 227 var obj root.Object 228 if tree.indexValues != nil { 229 obj = tree.indexValues 230 } 231 w.WriteObjectAny(obj) 232 } 233 234 { 235 var obj root.Object 236 if tree.index != nil { 237 obj = tree.index 238 } 239 w.WriteObjectAny(obj) 240 } 241 242 { 243 var obj root.Object 244 if tree.treeIndex != nil { 245 obj = tree.treeIndex 246 } 247 w.WriteObjectAny(obj) 248 } 249 250 { 251 var obj root.Object 252 if tree.friends != nil { 253 obj = tree.friends 254 } 255 w.WriteObjectAny(obj) 256 } 257 258 { 259 var obj root.Object 260 if tree.userInfo != nil { 261 obj = tree.userInfo 262 } 263 w.WriteObjectAny(obj) 264 } 265 266 { 267 var obj root.Object 268 if tree.branchRef != nil { 269 obj = tree.branchRef 270 } 271 w.WriteObjectAny(obj) 272 } 273 274 return w.SetHeader(hdr) 275 } 276 277 // ROOTUnmarshaler is the interface implemented by an object that can 278 // unmarshal itself from a ROOT buffer 279 func (tree *ttree) UnmarshalROOT(r *rbytes.RBuffer) error { 280 if r.Err() != nil { 281 return r.Err() 282 } 283 284 hdr := r.ReadHeader(tree.Class(), tree.RVersion()) 285 tree.rvers = hdr.Vers 286 287 r.ReadObject(&tree.named) 288 r.ReadObject(&tree.attline) 289 r.ReadObject(&tree.attfill) 290 r.ReadObject(&tree.attmarker) 291 292 switch { 293 default: 294 panic(fmt.Errorf( 295 "rtree: tree [%s] with version [%v] is not supported (too old)", 296 tree.Name(), 297 hdr.Vers, 298 )) 299 case hdr.Vers > 4: 300 301 switch { 302 case hdr.Vers > 5: 303 tree.entries = r.ReadI64() 304 tree.totBytes = r.ReadI64() 305 tree.zipBytes = r.ReadI64() 306 tree.savedBytes = r.ReadI64() 307 default: 308 tree.entries = int64(r.ReadF64()) 309 tree.totBytes = int64(r.ReadF64()) 310 tree.zipBytes = int64(r.ReadF64()) 311 tree.savedBytes = int64(r.ReadF64()) 312 } 313 314 if hdr.Vers >= 18 { 315 tree.flushedBytes = r.ReadI64() 316 } 317 318 if hdr.Vers >= 16 { 319 tree.weight = r.ReadF64() 320 } 321 tree.timerInterval = r.ReadI32() 322 tree.scanField = r.ReadI32() 323 tree.update = r.ReadI32() 324 325 if hdr.Vers >= 17 { 326 tree.defaultEntryOffsetLen = r.ReadI32() 327 } 328 329 nclus := 0 330 if hdr.Vers >= 19 { // FIXME 331 nclus = int(r.ReadI32()) // fNClusterRange 332 } 333 334 if hdr.Vers > 5 { 335 tree.maxEntries = r.ReadI64() 336 } 337 switch { 338 case hdr.Vers > 5: 339 tree.maxEntryLoop = r.ReadI64() 340 tree.maxVirtualSize = r.ReadI64() 341 tree.autoSave = r.ReadI64() 342 default: 343 tree.maxEntryLoop = int64(r.ReadI32()) 344 tree.maxVirtualSize = int64(r.ReadI32()) 345 tree.autoSave = int64(r.ReadI32()) 346 } 347 348 if hdr.Vers >= 18 { 349 tree.autoFlush = r.ReadI64() 350 } 351 352 switch { 353 case hdr.Vers > 5: 354 tree.estimate = r.ReadI64() 355 default: 356 tree.estimate = int64(r.ReadI32()) 357 } 358 359 if hdr.Vers >= 19 { // FIXME 360 tree.clusters.ranges = make([]int64, nclus) 361 tree.clusters.sizes = make([]int64, nclus) 362 _ = r.ReadI8() 363 r.ReadArrayI64(tree.clusters.ranges) // fClusterRangeEnd 364 _ = r.ReadI8() 365 r.ReadArrayI64(tree.clusters.sizes) // fClusterSize 366 } 367 368 if hdr.Vers >= 20 { 369 if err := tree.iobits.UnmarshalROOT(r); err != nil { 370 return err 371 } 372 } 373 374 var branches rcont.ObjArray 375 if err := branches.UnmarshalROOT(r); err != nil { 376 return err 377 } 378 tree.branches = make([]Branch, branches.Last()+1) 379 for i := range tree.branches { 380 tree.branches[i] = branches.At(i).(Branch) 381 tree.branches[i].setTree(tree) 382 } 383 384 var leaves rcont.ObjArray 385 if err := leaves.UnmarshalROOT(r); err != nil { 386 return err 387 } 388 tree.leaves = make([]Leaf, leaves.Last()+1) 389 for i := range tree.leaves { 390 leaf := leaves.At(i).(Leaf) 391 tree.leaves[i] = leaf 392 // FIXME(sbinet) 393 //tree.leaves[i].SetBranch(tree.branches[i]) 394 } 395 396 if hdr.Vers > 5 { 397 if v := r.ReadObjectAny(); v != nil { 398 tree.aliases = v.(*rcont.List) 399 } 400 } 401 if v := r.ReadObjectAny(); v != nil { 402 tree.indexValues = v.(*rcont.ArrayD) 403 } 404 if v := r.ReadObjectAny(); v != nil { 405 tree.index = v.(*rcont.ArrayI) 406 } 407 if hdr.Vers > 5 { 408 if v := r.ReadObjectAny(); v != nil { 409 tree.treeIndex = v 410 } 411 if v := r.ReadObjectAny(); v != nil { 412 tree.friends = v.(*rcont.List) 413 } 414 if v := r.ReadObjectAny(); v != nil { 415 tree.userInfo = v.(*rcont.List) 416 } 417 if v := r.ReadObjectAny(); v != nil { 418 tree.branchRef = v 419 } 420 } 421 } 422 423 r.CheckHeader(hdr) 424 425 // attach streamers to branches 426 for i := range tree.branches { 427 br := tree.branches[i] 428 bre, ok := br.(*tbranchElement) 429 if !ok { 430 continue 431 } 432 cls := bre.class 433 si, err := r.StreamerInfo(cls, int(bre.clsver)) 434 if err != nil { 435 panic(fmt.Errorf("rtree: could not find streamer (type=%q, vers=%d) for branch %q: %w", cls, bre.clsver, br.Name(), err)) 436 } 437 tree.attachStreamer(br, si, r) 438 } 439 440 return r.Err() 441 } 442 443 func (tree *ttree) attachStreamer(br Branch, info rbytes.StreamerInfo, ctx rbytes.StreamerInfoContext) { 444 if info == nil { 445 return 446 } 447 448 if len(info.Elements()) == 1 { 449 switch elem := info.Elements()[0].(type) { 450 case *rdict.StreamerBase: 451 if elem.Name() == "TObjArray" { 452 switch info.Name() { 453 case "TClonesArray": 454 cls := "" 455 version := -1 456 if bre, ok := br.(*tbranchElement); ok { 457 cls = bre.clones 458 version = int(bre.clsver) 459 } 460 si, err := ctx.StreamerInfo(cls, version) 461 if err != nil { 462 panic(err) 463 } 464 tree.attachStreamer(br, si, ctx) 465 return 466 default: 467 // FIXME(sbinet): can only determine streamer by reading some value? 468 return 469 } 470 } 471 case *rdict.StreamerSTL: 472 if elem.Name() == "This" { 473 tree.attachStreamerElement(br, elem, ctx) 474 return 475 } 476 } 477 } 478 479 br.setStreamer(info, ctx) 480 481 for _, sub := range br.Branches() { 482 name := sub.Name() 483 if strings.HasPrefix(name, br.Name()+".") { 484 name = name[len(br.Name())+1:] 485 } 486 487 if strings.Contains(name, "[") { 488 idx := strings.Index(name, "[") 489 name = name[:idx] 490 } 491 var se rbytes.StreamerElement 492 for _, elmt := range info.Elements() { 493 if elmt.Name() == name { 494 se = elmt 495 break 496 } 497 } 498 tree.attachStreamerElement(sub, se, ctx) 499 } 500 } 501 502 func (tree *ttree) attachStreamerElement(br Branch, se rbytes.StreamerElement, ctx rbytes.StreamerInfoContext) { 503 if se == nil { 504 return 505 } 506 507 br.setStreamerElement(se, ctx) 508 if len(br.Branches()) == 0 { 509 return 510 } 511 512 var members []rbytes.StreamerElement 513 switch se := se.(type) { 514 case *rdict.StreamerObject, *rdict.StreamerObjectAny, *rdict.StreamerObjectPointer, *rdict.StreamerObjectAnyPointer: 515 typename := strings.TrimRight(se.TypeName(), "*") 516 typevers := -1 517 // FIXME(sbinet): always load latest version? 518 info, err := ctx.StreamerInfo(typename, typevers) 519 if err != nil { 520 panic(err) 521 } 522 members = info.Elements() 523 case *rdict.StreamerSTL: 524 var ( 525 typename = strings.TrimSpace(se.TypeName()) 526 enames = rmeta.CxxTemplateFrom(typename).Args 527 typevers = -1 528 ) 529 switch se.STLType() { 530 case rmeta.STLbitset: 531 members = []rbytes.StreamerElement{se} 532 533 case rmeta.STLvector, rmeta.STLlist, 534 rmeta.STLset, rmeta.STLunorderedset, 535 rmeta.STLdeque: 536 typename = strings.TrimSpace(strings.TrimRight(enames[0], "*")) 537 info, err := ctx.StreamerInfo(typename, typevers) 538 if err != nil { 539 if _, ok := rmeta.CxxBuiltins[typename]; !ok { 540 panic(err) 541 } 542 } 543 if err == nil { 544 members = info.Elements() 545 } 546 547 case rmeta.STLmap, rmeta.STLunorderedmap: 548 // FIXME(sbinet): split it further or not? 549 members = []rbytes.StreamerElement{se} 550 551 default: 552 // FIXME(sbinet): always load latest version? 553 info, err := ctx.StreamerInfo(typename, typevers) 554 if err != nil { 555 if _, ok := rmeta.CxxBuiltins[typename]; !ok { 556 panic(err) 557 } 558 } 559 if err == nil { 560 members = info.Elements() 561 } 562 } 563 } 564 565 if members == nil { 566 return 567 } 568 569 for _, sub := range br.Branches() { 570 name := sub.Name() 571 if strings.HasPrefix(name, br.Name()+".") { // drop parent branch's name 572 name = name[len(br.Name())+1:] 573 } 574 submembers := members 575 for strings.Contains(name, ".") { // drop nested struct names, one at a time 576 dot := strings.Index(name, ".") 577 base := name[:dot] 578 name = name[dot+1:] 579 for _, subse := range submembers { 580 if subse.Name() == base { 581 switch subse.(type) { 582 case *rdict.StreamerObject, *rdict.StreamerObjectAny, *rdict.StreamerObjectPointer, *rdict.StreamerObjectAnyPointer: 583 // FIXME(sbinet): always load latest version? 584 subinfo, err := ctx.StreamerInfo(strings.TrimRight(subse.TypeName(), "*"), -1) 585 if err != nil { 586 panic(err) 587 } 588 submembers = subinfo.Elements() 589 } 590 } 591 } 592 } 593 594 if strings.Contains(name, "[") { 595 idx := strings.Index(name, "[") 596 name = name[:idx] 597 } 598 var subse rbytes.StreamerElement 599 for _, elmt := range members { 600 if elmt.Name() == name { 601 subse = elmt 602 break 603 } 604 } 605 tree.attachStreamerElement(sub, subse, ctx) 606 } 607 } 608 609 type tntuple struct { 610 ttree 611 nvars int 612 } 613 614 func (*tntuple) RVersion() int16 { 615 return rvers.Ntuple 616 } 617 618 func (*tntuple) Class() string { 619 return "TNtuple" 620 } 621 622 func (nt *tntuple) UnmarshalROOT(r *rbytes.RBuffer) error { 623 if r.Err() != nil { 624 return r.Err() 625 } 626 627 hdr := r.ReadHeader(nt.Class(), nt.RVersion()) 628 629 r.ReadObject(&nt.ttree) 630 nt.nvars = int(r.ReadI32()) 631 632 r.CheckHeader(hdr) 633 return r.Err() 634 } 635 636 type tntupleD struct { 637 ttree 638 nvars int 639 } 640 641 func (*tntupleD) RVersion() int16 { 642 return rvers.NtupleD 643 } 644 645 func (*tntupleD) Class() string { 646 return "TNtupleD" 647 } 648 649 func (nt *tntupleD) UnmarshalROOT(r *rbytes.RBuffer) error { 650 if r.Err() != nil { 651 return r.Err() 652 } 653 654 hdr := r.ReadHeader(nt.Class(), nt.RVersion()) 655 656 r.ReadObject(&nt.ttree) 657 nt.nvars = int(r.ReadI32()) 658 659 r.CheckHeader(hdr) 660 return r.Err() 661 } 662 663 type tioFeatures uint8 664 665 func (*tioFeatures) RVersion() int16 { 666 return rvers.ROOT_IOFeatures 667 } 668 669 func (*tioFeatures) Class() string { return "TIOFeatures" } 670 671 func (tio *tioFeatures) MarshalROOT(w *rbytes.WBuffer) (int, error) { 672 if w.Err() != nil { 673 return 0, w.Err() 674 } 675 hdr := w.WriteHeader(tio.Class(), tio.RVersion()) 676 677 if *tio != 0 { 678 var buf = [4]byte{0x1a, 0xa1, 0x2f, 0x10} // FIXME(sbinet) where do these 4 bytes come from ? 679 n, err := w.Write(buf[:]) 680 if err != nil { 681 return n, fmt.Errorf("could not write tio marshaled buffer: %w", err) 682 } 683 } 684 685 w.WriteU8(uint8(*tio)) 686 687 return w.SetHeader(hdr) 688 } 689 690 func (tio *tioFeatures) UnmarshalROOT(r *rbytes.RBuffer) error { 691 if r.Err() != nil { 692 return r.Err() 693 } 694 695 hdr := r.ReadHeader(tio.Class(), tio.RVersion()) 696 697 var buf [4]byte // FIXME(sbinet) where do these 4 bytes come from ? 698 _, err := r.Read(buf[:1]) 699 if err != nil { 700 return err 701 } 702 703 var u8 uint8 704 switch buf[0] { 705 case 0: 706 // nothing to do. 707 default: 708 _, err := r.Read(buf[1:]) 709 if err != nil { 710 return err 711 } 712 u8 = r.ReadU8() 713 } 714 715 *tio = tioFeatures(u8) 716 717 r.CheckHeader(hdr) 718 return r.Err() 719 } 720 721 func init() { 722 { 723 f := func() reflect.Value { 724 o := &ttree{} 725 return reflect.ValueOf(o) 726 } 727 rtypes.Factory.Add("TTree", f) 728 } 729 { 730 f := func() reflect.Value { 731 o := &tntuple{} 732 return reflect.ValueOf(o) 733 } 734 rtypes.Factory.Add("TNtuple", f) 735 } 736 { 737 f := func() reflect.Value { 738 o := &tntupleD{} 739 return reflect.ValueOf(o) 740 } 741 rtypes.Factory.Add("TNtupleD", f) 742 } 743 } 744 745 var ( 746 _ root.Object = (*ttree)(nil) 747 _ root.Named = (*ttree)(nil) 748 _ Tree = (*ttree)(nil) 749 _ rbytes.Marshaler = (*ttree)(nil) 750 _ rbytes.Unmarshaler = (*ttree)(nil) 751 752 _ root.Object = (*tntuple)(nil) 753 _ root.Named = (*tntuple)(nil) 754 _ Tree = (*tntuple)(nil) 755 _ rbytes.Unmarshaler = (*tntuple)(nil) 756 757 _ root.Object = (*tntupleD)(nil) 758 _ root.Named = (*tntupleD)(nil) 759 _ Tree = (*tntupleD)(nil) 760 _ rbytes.Unmarshaler = (*tntupleD)(nil) 761 762 _ root.Object = (*tioFeatures)(nil) 763 _ rbytes.RVersioner = (*tioFeatures)(nil) 764 _ rbytes.Marshaler = (*tioFeatures)(nil) 765 _ rbytes.Unmarshaler = (*tioFeatures)(nil) 766 )