ndmspc  v1.2.0-0.1.rc3
NTreeBranch.cxx
1 #include <TTree.h>
2 #include <TList.h>
3 #include <string>
4 #include <vector>
5 #include <TH1.h>
6 #include <THnSparse.h>
7 #include <TBranch.h>
8 #include <TObject.h>
9 #include <TROOT.h>
10 #include <TSystem.h>
11 #include "NLogger.h"
12 #include "NUtils.h"
13 
14 #include "NTreeBranch.h"
15 
17 ClassImp(Ndmspc::NTreeBranch);
19 
20 namespace Ndmspc {
21 NTreeBranch::NTreeBranch(TTree * tree, const std::string & name, void * address, const std::string & objClassName)
22  : TObject(), fName(name), fObjectClassName(objClassName)
23 {
27  // SetAddress(address);
28  if (tree) {
29  Branch(tree, address);
30  }
31 }
33 {
37  // delete fObject;
38  // delete fBranch;
39 }
40 TBranch * NTreeBranch::Branch(TTree * tree, void * address)
41 {
45  if (!tree) {
46  NLogError("Tree is nullptr !!!");
47  return nullptr;
48  }
49 
50  if (tree->GetBranch(fName.c_str())) {
51  fBranch = tree->GetBranch(fName.c_str());
52  return fBranch;
53  }
54  // fBranch = tree->Branch(fName.c_str(), fObjectClassName.c_str(), &address);
55  tree->Branch(fName.c_str(), fObjectClassName.c_str(), &address);
56  fBranch = tree->GetBranch(fName.c_str());
57  return fBranch;
58 }
59 void NTreeBranch::SetAddress(void * address, bool deleteExisting)
60 {
64  NLogTrace("NTreeBranch::SetAddress: Setting address %p for branch '%s' ...", address, fName.c_str());
65 
66  // if (fObject && deleteExisting) {
67  if (fObject && deleteExisting) {
68  NLogDebug("NTreeBranch::SetAddress: Deleting existing object %p for branch '%s' ...", fObject, fName.c_str());
69  fObject->Delete(); // Delete existing object to avoid memory leaks when setting new address
70  // NOTE: fObject->Delete() calls 'delete this' internally (TObject::Delete()),
71  // so do NOT also call 'delete fObject' here — that would be a double-free.
72  fObject = nullptr;
73  }
74  fObject = (TObject *)address;
75  fBranch->SetAddress(&fObject);
76 }
78 {
82 
83  if (!tree) {
84  NLogError("Tree is nullptr !!!");
85  return;
86  }
87 
88  NLogTrace("NTreeBranch::SetBranchAddress: Setting branch address '%s' ...", fName.c_str());
89 
90  if (fObject) {
91  NLogDebug("NTreeBranch::SetBranchAddress: Deleting existing object %p for branch '%s' ...", fObject, fName.c_str());
92  fObject->Delete(); // Delete existing object to avoid memory leaks when setting new address
93  // NOTE: fObject->Delete() calls 'delete this' internally (TObject::Delete()),
94  // so do NOT also call 'delete fObject' here — that would be a double-free.
95  fObject = nullptr;
96  }
97  tree->SetBranchStatus(fName.c_str(), fBranchStatus);
98  tree->SetBranchAddress(fName.c_str(), &fObject);
99  fBranch = tree->GetBranch(fName.c_str());
100 }
101 
102 Long64_t NTreeBranch::GetEntry(TTree * tree, Long64_t entry)
103 {
107 
108  if (tree == nullptr) {
109  NLogError("Tree is not initialized !!!");
110  return -1;
111  }
112 
113  NLogTrace("Getting entry for branch '%s' %lld status=%d ...", fBranch->GetName(), entry,
114  tree->GetBranchStatus(fBranch->GetName()));
115 
116  Long64_t bytes = 0;
117  if (fBranch && tree->GetBranchStatus(fBranch->GetName()) == 1) {
118  // Temporarily disable ROOT's recursive cleanup to prevent crashes when
119  // TCanvas objects (stored in TList branches) are destroyed during
120  // deserialization of a new entry (TCanvas::Streamer -> TObjArray::~TObjArray
121  // -> RecursiveRemove).
122  // Bool_t prevMustClean = gROOT->MustClean();
123  // gROOT->SetMustClean(kFALSE);
124 
125  if (fObject && fObject->InheritsFrom(TList::Class())) {
126  NLogTrace("NTreeBranch::GetEntry: Deleting existing object %p for branch '%s' ...", fObject, fName.c_str());
127  // NUtils::SafeDeleteObject(fObject);
128  TList * lst = static_cast<TList *>(fObject);
130  fObject = nullptr;
131  }
132  bytes = fBranch->GetEntry(entry);
133  // ProcInfo_t info;
134  // gSystem->GetProcInfo(&info);
135  // NLogDebug("NTreeBranch::GetEntry:[RSS]: %ld kB", info.fMemResident);
136 
137  // gROOT->SetMustClean(prevMustClean);
138  NLogTrace("NTreeBranch::GetEntry: Getting content from %s with size %.3f MB", fBranch->GetName(),
139  (double)bytes / (1024 * 1024));
140  }
141 
142  return bytes;
143 }
144 void NTreeBranch::SaveEntry(NTreeBranch * hnstBranchIn, bool useProjection, const std::string projOpt)
145 {
149  NLogTrace("Saving entry for branch=%s ...", fName.c_str());
150 
151  TString classNameStr = hnstBranchIn->GetObjectClassName().c_str();
152  // NLogDebug("NTreeBranch::SaveEntry: Obj class name %s ...", classNameStr.Data());
153  if (classNameStr.BeginsWith("THnSparse")) {
154 
155  THnSparse * in = (THnSparse *)hnstBranchIn->GetObject();
156  if (in) {
157  if (in->GetNdimensions() > 0) {
158  if (useProjection) {
159  // in->Print();
160  auto dims = std::make_unique<Int_t[]>(in->GetNdimensions());
161  // Int_t dims[in->GetNdimensions()];
162  for (Int_t iDim = 0; iDim < in->GetNdimensions(); iDim++) {
163  dims[iDim] = iDim;
164  }
165  THnSparse * out = (THnSparse *)in->ProjectionND(in->GetNdimensions(), dims.get(), projOpt.c_str());
166  // Loop over all bins
167  double sum = 0;
168  NLogTrace("Projection of %s with filled bins %lld ...", in->GetName(), out->GetNbins());
169  for (Int_t i = 0; i < out->GetNbins(); i++) {
170  NLogTrace("Bin %d content=%f", i, out->GetBinContent(i));
171  sum += out->GetBinContent(i);
172  }
173  // out->Projection(0)->Print();
174  out->SetEntries(sum);
175  out->SetNameTitle(in->GetName(), in->GetTitle());
176  // out->Print();
177  SetAddress(out);
178  }
179  else {
180  SetAddress(in);
181  }
182  }
183  }
184  else {
185  SetAddress(nullptr);
186  }
187  }
188  else {
189  NLogTrace("Class '%s' is stored default method !!!", classNameStr.Data());
190  // return;
191  }
192 }
193 
194 void NTreeBranch::Print(Option_t * /*option*/) const
195 {
199  NLogInfo("Branch name='%s' objClassName='%s' address=%p branch=%p status=%d", fName.c_str(), fObjectClassName.c_str(),
201 }
202 
203 } // namespace Ndmspc
NDMSPC tree branch object for managing ROOT TBranch and associated data.
Definition: NTreeBranch.h:18
std::string GetObjectClassName() const
Get object class name.
Definition: NTreeBranch.h:87
Long64_t GetEntry(TTree *tree, Long64_t entry)
Get entry from TTree.
NTreeBranch(TTree *tree=nullptr, const std::string &name="", void *address=nullptr, const std::string &objClassName="TObject")
Constructor.
Definition: NTreeBranch.cxx:21
TObject * fObject
! Object pointer
Definition: NTreeBranch.h:136
int fBranchStatus
Branch status.
Definition: NTreeBranch.h:134
virtual void Print(Option_t *option="") const
Print branch information.
virtual ~NTreeBranch()
Destructor.
Definition: NTreeBranch.cxx:32
std::string fObjectClassName
Object class name.
Definition: NTreeBranch.h:137
TBranch * Branch(TTree *tree, void *address)
Create branch in TTree with given address.
Definition: NTreeBranch.cxx:40
void SaveEntry(NTreeBranch *hnstIn, bool useProjection=false, const std::string projOpt="OE")
Save entry to another NTreeBranch.
void SetAddress(void *address, bool deleteExisting=false)
Set address for branch data.
Definition: NTreeBranch.cxx:59
TObject * GetObject() const
Get object pointer.
Definition: NTreeBranch.h:81
TBranch * fBranch
! Branch pointer
Definition: NTreeBranch.h:135
void SetBranchAddress(TTree *tree)
Set branch address in TTree.
Definition: NTreeBranch.cxx:77
std::string fName
Branch name.
Definition: NTreeBranch.h:133
static void SafeDeleteTList(TList *&lst)
Safely delete a TList and all its contents, bypassing ROOT's GarbageCollect.
Definition: NUtils.cxx:2018