ndmspc v1.2.0-0.1.rc7
Loading...
Searching...
No Matches
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
17ClassImp(Ndmspc::NTreeBranch);
19
20namespace Ndmspc {
21NTreeBranch::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}
40TBranch * 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}
59void 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
102Long64_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}
144void 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
194void 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.
TObject * fObject
! Object pointer
int fBranchStatus
Branch status.
virtual void Print(Option_t *option="") const
Print branch information.
virtual ~NTreeBranch()
Destructor.
std::string fObjectClassName
Object class name.
TBranch * Branch(TTree *tree, void *address)
Create branch in TTree with given address.
TObject * GetObject() const
Get object pointer.
Definition NTreeBranch.h:81
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.
TBranch * fBranch
! Branch pointer
void SetBranchAddress(TTree *tree)
Set branch address in TTree.
std::string fName
Branch name.
static void SafeDeleteTList(TList *&lst)
Safely delete a TList and all its contents, bypassing ROOT's GarbageCollect.
Definition NUtils.cxx:2022
Global callback function for libwebsockets client events.