// @(#)root/tree:$Id$ // Author: Rene Brun 12/01/96 /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #ifndef ROOT_TTree #define ROOT_TTree ////////////////////////////////////////////////////////////////////////// // // // TTree // // // // A TTree object is a list of TBranch. // // To Create a TTree object one must: // // - Create the TTree header via the TTree constructor // // - Call the TBranch constructor for every branch. // // // // To Fill this object, use member function Fill with no parameters. // // The Fill function loops on all defined TBranch. // // // ////////////////////////////////////////////////////////////////////////// #include "Compression.h" #include "ROOT/TIOFeatures.hxx" #include "TArrayD.h" #include "TArrayI.h" #include "TAttFill.h" #include "TAttLine.h" #include "TAttMarker.h" #include "TClass.h" #include "TDataType.h" #include "TDirectory.h" #include "TObjArray.h" #include "TVirtualTreePlayer.h" #ifdef R__LESS_INCLUDES class TBranch; class TList; #else #include "TBranch.h" // #include "TBuffer.h" #include "TList.h" #endif #include #include #include #include class TBuffer; class TBrowser; class TFile; class TLeaf; class TH1; class TTreeFormula; class TPolyMarker; class TEventList; class TEntryList; class TSQLResult; class TSelector; class TPrincipal; class TFriendElement; class TCut; class TVirtualIndex; class TBranchRef; class TBasket; class TStreamerInfo; class TTreeCache; class TTreeCloner; class TFileMergeInfo; class TVirtualPerfStats; class TTree : public TNamed, public TAttLine, public TAttFill, public TAttMarker { using TIOFeatures = ROOT::TIOFeatures; protected: Long64_t fEntries; ///< Number of entries // NOTE: cannot use std::atomic for these counters as it cannot be serialized. Long64_t fTotBytes; ///< Total number of bytes in all branches before compression Long64_t fZipBytes; ///< Total number of bytes in all branches after compression Long64_t fSavedBytes; ///< Number of autosaved bytes Long64_t fFlushedBytes; ///< Number of auto-flushed bytes Double_t fWeight; ///< Tree weight (see TTree::SetWeight) Int_t fTimerInterval; ///< Timer interval in milliseconds Int_t fScanField; ///< Number of runs before prompting in Scan Int_t fUpdate; ///< Update frequency for EntryLoop Int_t fDefaultEntryOffsetLen; ///< Initial Length of fEntryOffset table in the basket buffers Int_t fNClusterRange; ///< Number of Cluster range in addition to the one defined by 'AutoFlush' Int_t fMaxClusterRange; /// fTotalBuffers; ///Notify(). /// Usually points to a TNotifyLink if this is a TChain. TObject *fNotify; //! TDirectory *fDirectory; ///> fSortedBranches; /// fSeqBranches; /// fAllocationTime{0}; /// fAllocationCount{0}; /// fIMTTotBytes; /// fIMTZipBytes; /// 0, the members of the object are serialised as separate branches. /// \return Pointer to the TBranch that was created. The branch is owned by the tree. template TBranch *Branch(const char* name, T* obj, Int_t bufsize = 32000, Int_t splitlevel = 99) { return BranchImpRef(name, TClass::GetClass(), TDataType::GetType(typeid(T)), obj, bufsize, splitlevel); } /// Add a new branch, and infer the data type from the array `addobj` being passed. /// /// \note This and the previous overload should cover most cases for creating a branch. Try to use these two whenever /// possible, unless e.g. type conversions are needed. /// /// \param[in] name Name of the branch to be created. /// \param[in] addobj Array of the objects to be added. When calling Fill(), the current value of the type/object will be saved. /// \param[in] bufsize he buffer size in bytes for this branch. When the buffer is full, it is compressed and written to disc. /// The default value of 32000 bytes and should be ok for most simple types. Larger buffers (e.g. 256000) if your Tree is not split and each entry is large (Megabytes). /// A small value for bufsize is beneficial if entries in the Tree are accessed randomly and the Tree is in split mode. /// \param[in] splitlevel If T is a class or struct and splitlevel > 0, the members of the object are serialised as separate branches. /// \return Pointer to the TBranch that was created. The branch is owned by the tree. template TBranch *Branch(const char* name, T** addobj, Int_t bufsize = 32000, Int_t splitlevel = 99) { return BranchImp(name, TClass::GetClass(), addobj, bufsize, splitlevel); } virtual Int_t Branch(TCollection* list, Int_t bufsize = 32000, Int_t splitlevel = 99, const char* name = ""); virtual Int_t Branch(TList* list, Int_t bufsize = 32000, Int_t splitlevel = 99); virtual Int_t Branch(const char* folder, Int_t bufsize = 32000, Int_t splitlevel = 99); virtual TBranch *Branch(const char* name, void* address, const char* leaflist, Int_t bufsize = 32000); TBranch *Branch(const char* name, char* address, const char* leaflist, Int_t bufsize = 32000) { // Overload to avoid confusion between this signature and the template instance. return Branch(name,(void*)address,leaflist,bufsize); } TBranch *Branch(const char* name, Longptr_t address, const char* leaflist, Int_t bufsize = 32000) { // Overload to avoid confusion between this signature and the template instance. return Branch(name,(void*)address,leaflist,bufsize); } TBranch *Branch(const char* name, int address, const char* leaflist, Int_t bufsize = 32000) { // Overload to avoid confusion between this signature and the template instance. return Branch(name,(void*)(Longptr_t)address,leaflist,bufsize); } virtual TBranch *Branch(const char* name, const char* classname, void* addobj, Int_t bufsize = 32000, Int_t splitlevel = 99); template TBranch *Branch(const char* name, const char* classname, T* obj, Int_t bufsize = 32000, Int_t splitlevel = 99) { // See BranchImpRed for details. Here we __ignore return BranchImpRef(name, classname, TClass::GetClass(), obj, bufsize, splitlevel); } template TBranch *Branch(const char* name, const char* classname, T** addobj, Int_t bufsize = 32000, Int_t splitlevel = 99) { // See BranchImp for details return BranchImp(name, classname, TClass::GetClass(), addobj, bufsize, splitlevel); } template TBranch *Branch(const char* name, std::array *obj, Int_t bufsize = 32000, Int_t splitlevel = 99) { TClass *cl = TClass::GetClass(); if (cl) { TClass *arrCl = TClass::GetClass>(); Error("Branch","std::array of objects not yet supported as top level branch object (the class is %s)", arrCl ? arrCl->GetName() : cl->GetName()); return nullptr; } return BranchImpArr(name, TDataType::GetType(typeid(T)), N, obj, bufsize, splitlevel); } virtual TBranch *Bronch(const char* name, const char* classname, void* addobj, Int_t bufsize = 32000, Int_t splitlevel = 99); virtual TBranch *BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize = 32000, Int_t splitlevel = 1); virtual TBranch *BranchRef(); void Browse(TBrowser*) override; virtual Int_t BuildIndex(const char *majorname, const char *minorname = "0"); TStreamerInfo *BuildStreamerInfo(TClass* cl, void *pointer = nullptr, Bool_t canOptimize = kTRUE); virtual TFile *ChangeFile(TFile* file); virtual TTree *CloneTree(Long64_t nentries = -1, Option_t* option = ""); virtual void CopyAddresses(TTree*,Bool_t undo = kFALSE); virtual Long64_t CopyEntries(TTree* tree, Long64_t nentries = -1, Option_t *option = "", Bool_t needCopyAddresses = false); virtual TTree *CopyTree(const char* selection, Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); virtual TBasket *CreateBasket(TBranch*); virtual void DirectoryAutoAdd(TDirectory *); Int_t Debug() const { return fDebug; } void Delete(Option_t* option = "") override; // *MENU* void Draw(Option_t* opt) override { Draw(opt, "", "", kMaxEntries, 0); } virtual Long64_t Draw(const char* varexp, const TCut& selection, Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); virtual Long64_t Draw(const char* varexp, const char* selection, Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); // *MENU* virtual void DropBaskets(); virtual void DropBuffers(Int_t nbytes); Bool_t EnableCache(); virtual Int_t Fill(); virtual TBranch *FindBranch(const char* name); virtual TLeaf *FindLeaf(const char* name); virtual Int_t Fit(const char* funcname, const char* varexp, const char* selection = "", Option_t* option = "", Option_t* goption = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); // *MENU* virtual Int_t FlushBaskets(Bool_t create_cluster = true) const; virtual const char *GetAlias(const char* aliasName) const; UInt_t GetAllocationCount() const { return fAllocationCount; } #ifdef R__TRACK_BASKET_ALLOC_TIME ULong64_t GetAllocationTime() const { return fAllocationTime; } #endif virtual Long64_t GetAutoFlush() const {return fAutoFlush;} virtual Long64_t GetAutoSave() const {return fAutoSave;} virtual TBranch *GetBranch(const char* name); virtual TBranchRef *GetBranchRef() const { return fBranchRef; }; virtual Bool_t GetBranchStatus(const char* branchname) const; static Int_t GetBranchStyle(); virtual Long64_t GetCacheSize() const { return fCacheSize; } virtual TClusterIterator GetClusterIterator(Long64_t firstentry); virtual Long64_t GetChainEntryNumber(Long64_t entry) const { return entry; } virtual Long64_t GetChainOffset() const { return fChainOffset; } virtual Bool_t GetClusterPrefetch() const { return fCacheDoClusterPrefetch; } TFile *GetCurrentFile() const; Int_t GetDefaultEntryOffsetLen() const {return fDefaultEntryOffsetLen;} Long64_t GetDebugMax() const { return fDebugMax; } Long64_t GetDebugMin() const { return fDebugMin; } TDirectory *GetDirectory() const { return fDirectory; } virtual Long64_t GetEntries() const { return fEntries; } virtual Long64_t GetEntries(const char *selection); virtual Long64_t GetEntriesFast() const { return fEntries; } virtual Long64_t GetEntriesFriend() const; virtual Long64_t GetEstimate() const { return fEstimate; } virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0); Int_t GetEvent(Long64_t entry, Int_t getall = 0) { return GetEntry(entry, getall); } virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor = 0); virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor = 0) const; virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor = 0) const; TEventList *GetEventList() const { return fEventList; } virtual TEntryList *GetEntryList(); virtual Long64_t GetEntryNumber(Long64_t entry) const; virtual Int_t GetFileNumber() const { return fFileNumber; } virtual TTree *GetFriend(const char*) const; virtual const char *GetFriendAlias(TTree*) const; TH1 *GetHistogram() { return GetPlayer()->GetHistogram(); } virtual Bool_t GetImplicitMT() { return fIMTEnabled; } virtual Int_t *GetIndex() { return &fIndex.fArray[0]; } virtual Double_t *GetIndexValues() { return &fIndexValues.fArray[0]; } ROOT::TIOFeatures GetIOFeatures() const; virtual TIterator *GetIteratorOnAllLeaves(Bool_t dir = kIterForward); virtual TLeaf *GetLeaf(const char* branchname, const char* leafname); virtual TLeaf *GetLeaf(const char* name); virtual TList *GetListOfClones() { return fClones; } virtual TObjArray *GetListOfBranches() { return &fBranches; } virtual TObjArray *GetListOfLeaves() { return &fLeaves; } virtual TList *GetListOfFriends() const { return fFriends; } virtual TList *GetListOfAliases() const { return fAliases; } // GetMakeClass is left non-virtual for efficiency reason. // Making it virtual affects the performance of the I/O Int_t GetMakeClass() const { return fMakeClass; } virtual Long64_t GetMaxEntryLoop() const { return fMaxEntryLoop; } virtual Double_t GetMaximum(const char* columname); static Long64_t GetMaxTreeSize(); virtual Long64_t GetMaxVirtualSize() const { return fMaxVirtualSize; } virtual Double_t GetMinimum(const char* columname); virtual Int_t GetNbranches() { return fBranches.GetEntriesFast(); } TObject *GetNotify() const { return fNotify; } TVirtualTreePlayer *GetPlayer(); virtual Int_t GetPacketSize() const { return fPacketSize; } virtual TVirtualPerfStats *GetPerfStats() const { return fPerfStats; } TTreeCache *GetReadCache(TFile *file) const; TTreeCache *GetReadCache(TFile *file, Bool_t create); virtual Long64_t GetReadEntry() const { return fReadEntry; } virtual Long64_t GetReadEvent() const { return fReadEntry; } virtual Int_t GetScanField() const { return fScanField; } TTreeFormula *GetSelect() { return GetPlayer()->GetSelect(); } virtual Long64_t GetSelectedRows() { return GetPlayer()->GetSelectedRows(); } virtual Int_t GetTimerInterval() const { return fTimerInterval; } TBuffer* GetTransientBuffer(Int_t size); virtual Long64_t GetTotBytes() const { return fTotBytes; } virtual TTree *GetTree() const { return const_cast(this); } virtual TVirtualIndex *GetTreeIndex() const { return fTreeIndex; } virtual Int_t GetTreeNumber() const { return 0; } Float_t GetTargetMemoryRatio() const { return fTargetMemoryRatio; } virtual Int_t GetUpdate() const { return fUpdate; } virtual TList *GetUserInfo(); // See TSelectorDraw::GetVar TTreeFormula *GetVar(Int_t i) { return GetPlayer()->GetVar(i); } // See TSelectorDraw::GetVar TTreeFormula *GetVar1() { return GetPlayer()->GetVar1(); } // See TSelectorDraw::GetVar TTreeFormula *GetVar2() { return GetPlayer()->GetVar2(); } // See TSelectorDraw::GetVar TTreeFormula *GetVar3() { return GetPlayer()->GetVar3(); } // See TSelectorDraw::GetVar TTreeFormula *GetVar4() { return GetPlayer()->GetVar4(); } // See TSelectorDraw::GetVal virtual Double_t *GetVal(Int_t i) { return GetPlayer()->GetVal(i); } // See TSelectorDraw::GetVal virtual Double_t *GetV1() { return GetPlayer()->GetV1(); } // See TSelectorDraw::GetVal virtual Double_t *GetV2() { return GetPlayer()->GetV2(); } // See TSelectorDraw::GetVal virtual Double_t *GetV3() { return GetPlayer()->GetV3(); } // See TSelectorDraw::GetVal virtual Double_t *GetV4() { return GetPlayer()->GetV4(); } virtual Double_t *GetW() { return GetPlayer()->GetW(); } virtual Double_t GetWeight() const { return fWeight; } virtual Long64_t GetZipBytes() const { return fZipBytes; } virtual void IncrementTotalBuffers(Int_t nbytes) { fTotalBuffers += nbytes; } Bool_t IsFolder() const override { return kTRUE; } virtual Bool_t InPlaceClone(TDirectory *newdirectory, const char *options = ""); virtual Int_t LoadBaskets(Long64_t maxmemory = 2000000000); virtual Long64_t LoadTree(Long64_t entry); virtual Long64_t LoadTreeFriend(Long64_t entry, TTree* T); virtual Int_t MakeClass(const char *classname = nullptr, Option_t* option = ""); virtual Int_t MakeCode(const char *filename = nullptr); virtual Int_t MakeProxy(const char* classname, const char* macrofilename = nullptr, const char* cutfilename = nullptr, const char* option = nullptr, Int_t maxUnrolling = 3); virtual Int_t MakeSelector(const char *selector = nullptr, Option_t *option = ""); Bool_t MemoryFull(Int_t nbytes); virtual Long64_t Merge(TCollection* list, Option_t* option = ""); virtual Long64_t Merge(TCollection* list, TFileMergeInfo *info); static TTree *MergeTrees(TList* list, Option_t* option = ""); Bool_t Notify() override; virtual void OptimizeBaskets(ULong64_t maxMemory=10000000, Float_t minComp=1.1, Option_t *option=""); TPrincipal *Principal(const char* varexp = "", const char* selection = "", Option_t* option = "np", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); void Print(Option_t* option = "") const override; // *MENU* virtual void PrintCacheStats(Option_t* option = "") const; virtual Long64_t Process(const char* filename, Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); // *MENU* virtual Long64_t Process(TSelector* selector, Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); virtual Long64_t Project(const char* hname, const char* varexp, const char* selection = "", Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); virtual TSQLResult *Query(const char* varexp = "", const char* selection = "", Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); virtual Long64_t ReadFile(const char* filename, const char* branchDescriptor = "", char delimiter = ' '); virtual Long64_t ReadStream(std::istream& inputStream, const char* branchDescriptor = "", char delimiter = ' '); virtual void Refresh(); virtual void RegisterExternalFriend(TFriendElement *); virtual void RemoveExternalFriend(TFriendElement *); virtual void RemoveFriend(TTree*); void RecursiveRemove(TObject *obj) override; virtual void Reset(Option_t* option = ""); virtual void ResetAfterMerge(TFileMergeInfo *); virtual void ResetBranchAddress(TBranch *); virtual void ResetBranchAddresses(); virtual Long64_t Scan(const char* varexp = "", const char* selection = "", Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); // *MENU* virtual Bool_t SetAlias(const char* aliasName, const char* aliasFormula); virtual void SetAutoSave(Long64_t autos = -300000000); virtual void SetAutoFlush(Long64_t autof = -30000000); virtual void SetBasketSize(const char* bname, Int_t buffsize = 16000); virtual Int_t SetBranchAddress(const char *bname,void *add, TBranch **ptr = nullptr); virtual Int_t SetBranchAddress(const char *bname,void *add, TClass *realClass, EDataType datatype, Bool_t isptr); virtual Int_t SetBranchAddress(const char *bname,void *add, TBranch **ptr, TClass *realClass, EDataType datatype, Bool_t isptr); template Int_t SetBranchAddress(const char *bname, T **add, TBranch **ptr = nullptr) { TClass *cl = TClass::GetClass(); EDataType type = kOther_t; if (!cl) type = TDataType::GetType(typeid(T)); return SetBranchAddress(bname,add,ptr,cl,type,true); } #ifndef R__NO_CLASS_TEMPLATE_SPECIALIZATION // This can only be used when the template overload resolution can distinguish between // T* and T** template Int_t SetBranchAddress(const char *bname, T *add, TBranch **ptr = nullptr) { TClass *cl = TClass::GetClass(); EDataType type = kOther_t; if (!cl) type = TDataType::GetType(typeid(T)); return SetBranchAddress(bname,add,ptr,cl,type,false); } #endif virtual void SetBranchStatus(const char* bname, Bool_t status = 1, UInt_t* found = nullptr); static void SetBranchStyle(Int_t style = 1); //style=0 for old branch, =1 for new branch style virtual Int_t SetCacheSize(Long64_t cachesize = -1); virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last); virtual void SetCacheLearnEntries(Int_t n=10); virtual void SetChainOffset(Long64_t offset = 0) { fChainOffset=offset; } virtual void SetCircular(Long64_t maxEntries); virtual void SetClusterPrefetch(Bool_t enabled) { fCacheDoClusterPrefetch = enabled; } virtual void SetDebug(Int_t level = 1, Long64_t min = 0, Long64_t max = 9999999); // *MENU* virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting = kFALSE); virtual void SetDirectory(TDirectory* dir); virtual Long64_t SetEntries(Long64_t n = -1); virtual void SetEstimate(Long64_t nentries = 1000000); ROOT::TIOFeatures SetIOFeatures(const ROOT::TIOFeatures &); virtual void SetFileNumber(Int_t number = 0); virtual void SetEventList(TEventList* list); virtual void SetEntryList(TEntryList* list, Option_t *opt=""); virtual void SetImplicitMT(Bool_t enabled) { fIMTEnabled = enabled; } virtual void SetMakeClass(Int_t make); virtual void SetMaxEntryLoop(Long64_t maxev = kMaxEntries) { fMaxEntryLoop = maxev; } // *MENU* static void SetMaxTreeSize(Long64_t maxsize = 100000000000LL); virtual void SetMaxVirtualSize(Long64_t size = 0) { fMaxVirtualSize = size; } // *MENU* void SetName(const char* name) override; // *MENU* /** * @brief Sets the address of the object to be notified when the tree is loaded. * * The method TObject::Notify is called for the given object when the tree * is loaded. Specifically this occurs in the TTree::LoadTree method. To * remove the notification call this method with nullptr: * @code tree->SetNotify(nullptr); @endcode * * If this is a TChain, `obj` is most often going to be a TNotifyLink. * * @param[in] obj Pointer to a TObject to be notified. */ virtual void SetNotify(TObject* obj); virtual void SetObject(const char* name, const char* title); virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1); virtual void SetPerfStats(TVirtualPerfStats* perf); virtual void SetScanField(Int_t n = 50) { fScanField = n; } // *MENU* void SetTargetMemoryRatio(Float_t ratio) { fTargetMemoryRatio = ratio; } virtual void SetTimerInterval(Int_t msec = 333) { fTimerInterval=msec; } virtual void SetTreeIndex(TVirtualIndex* index); virtual void SetWeight(Double_t w = 1, Option_t* option = ""); virtual void SetUpdate(Int_t freq = 0) { fUpdate = freq; } virtual void Show(Long64_t entry = -1, Int_t lenmax = 20); virtual void StartViewer(); // *MENU* virtual Int_t StopCacheLearningPhase(); virtual Int_t UnbinnedFit(const char* funcname, const char* varexp, const char* selection = "", Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); void UseCurrentStyle() override; Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override; Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) const override; ClassDefOverride(TTree, 20) // Tree descriptor (the main ROOT I/O class) }; ////////////////////////////////////////////////////////////////////////// // // // TTreeFriendLeafIter // // // // Iterator on all the leaves in a TTree and its friend // // // ////////////////////////////////////////////////////////////////////////// class TTreeFriendLeafIter : public TIterator { protected: TTree *fTree; ///< tree being iterated TIterator *fLeafIter; ///< current leaf sub-iterator. TIterator *fTreeIter; ///< current tree sub-iterator. Bool_t fDirection; ///< iteration direction TTreeFriendLeafIter() : fTree(nullptr), fLeafIter(nullptr), fTreeIter(nullptr), fDirection(kFALSE) { } public: TTreeFriendLeafIter(const TTree* t, Bool_t dir = kIterForward); TTreeFriendLeafIter(const TTreeFriendLeafIter &iter); ~TTreeFriendLeafIter() override { SafeDelete(fLeafIter); SafeDelete(fTreeIter); } TIterator &operator=(const TIterator &rhs) override; TTreeFriendLeafIter &operator=(const TTreeFriendLeafIter &rhs); const TCollection *GetCollection() const override { return nullptr; } Option_t *GetOption() const override; TObject *Next() override; void Reset() override { SafeDelete(fLeafIter); SafeDelete(fTreeIter); } Bool_t operator !=(const TIterator&) const override { // TODO: Implement me return false; } Bool_t operator !=(const TTreeFriendLeafIter&) const { // TODO: Implement me return false; } TObject *operator*() const override { // TODO: Implement me return nullptr; } ClassDefOverride(TTreeFriendLeafIter,0) //Linked list iterator }; #endif