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  )