GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4CompositeEvent.cxx
Go to the documentation of this file.
1 // $Id$
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 #include "TGo4CompositeEvent.h"
15 
16 #include "TTree.h"
17 #include "TROOT.h"
18 #include "TObjArray.h"
19 #include "TDirectory.h"
20 #include "TBranch.h"
21 
22 #include "TGo4Log.h"
23 
26  fNElements(0),
27  fEventElements(nullptr),
28  fMaxIndex(0)
29 {
30 }
31 
32 TGo4CompositeEvent::TGo4CompositeEvent(const char *aName, const char *aTitle, Short_t aBaseCat) :
33  TGo4EventElement(aName,aTitle, aBaseCat),
34  fNElements(0),
35  fEventElements(nullptr),
36  fMaxIndex(0)
37 {
38 }
39 
41 {
42  if(fEventElements) {
43 
44  fEventElements->Delete();
45 
46  delete fEventElements;
47 
48  fEventElements = nullptr;
49  }
50 }
51 
53 {
55 
56  if (!res && fEventElements)
57  res = dynamic_cast<TGo4EventElement *> (fEventElements->FindObject(name));
58 
59  return res;
60 }
61 
62 
63 void TGo4CompositeEvent::makeBranch(TBranch *parent)
64 {
65  if (fEventElements)
66  for (Int_t i = 0; i <= fEventElements->GetLast(); i++) {
68  if (par && *par) {
69  TBranch *b = parent->GetTree()->TTree::Branch(TString::Format("%s.", (*par)->GetName()).Data(),
70  (*par)->ClassName(), par, 4000, 99);
71  (*par)->makeBranch(b);
72  }
73  }
74 
76 }
77 
78 Int_t TGo4CompositeEvent::activateBranch(TBranch *branch, Int_t init, TGo4EventElement **var_ptr)
79 {
80  // first read event itself
81  TGo4EventElement::activateBranch(branch, init, var_ptr);
82 
83  if (!branch) return fNElements;
84 
85  // we need to call GetEntry here to get value of fNElements and fMaxIndex
86  branch->GetEntry(0);
87 
88  if (fDebug)
89  TGo4Log::Debug("##### TGo4CompositeEvent::activateBranch called from obj:%s",this->GetName());
90 
91  TTree *tree = branch->GetTree();
92  TObjArray *br = tree->GetListOfBranches();
93 
94  Int_t i = init;
95  Int_t all_branches = fNElements;
96 
97  // expand object array to final size before setting branch addresses:
98  ProvideArray();
99 
100 
101  if (fDebug)
102  TGo4Log::Debug("-I-TGo4CompositeEvent::activateBranch from obj:%s bname:%s Elements:%d index:%d",
103  GetName(), branch->GetName(), fNElements, init);
104 
105  while (i < init + all_branches) {
106  i++;
107  TBranch *b = (TBranch *) br->At(i);
108  Bool_t readentry = kFALSE;
109  if (!b) continue;
110 
111  TString sub = b->GetName();
112  sub.Remove(sub.Length()-1);
113  TGo4EventElement *par = getEventElement(sub.Data());
114 
115  if (fDebug)
116  TGo4Log::Debug("-I TGo4CompositeEvent::activateBranch use subbranch %s", b->GetName());
117 
118  if (!par) {
119 
120  TClass *cl = gROOT->GetClass(b->GetClassName());
121  if (!cl) {
122  TGo4Log::Debug("-I class %s cannot be reconstructed", b->GetClassName());
123  continue;
124  }
125 
126  par = (TGo4EventElement *) cl->New();
127  // need to set correct object name:
128  par->SetName(sub.Data());
129  if(fDebug)
130  TGo4Log::Debug("-I Created new instance of class %s, name:%s", cl->GetName(), par->GetName());
131 
132  if (!par) {
133  TGo4Log::Error("-I class %s instance cannot be created", b->GetClassName());
134  continue;
135  }
136 
137  readentry = !par->isComposed();
138  }
139 
140  // TODO: could we put element in the elements array BEFORE we activate branch
141  // in this case activate branch will set correct address from the beginning
142  Int_t offset = par->activateBranch(b, i, &par);
143 
144  if (fDebug)
145  TGo4Log::Debug("-I activate from obj:%s elems:%d index:%d adding:%s",
146  this->GetName(), init+fNElements, i, par->GetName());
147 
148  // we need to getentry only when new object was created to get its id
149  if (readentry) b->GetEntry(0);
150 
151  if (fDebug)
152  TGo4Log::Debug("Add branch %s event %s offset %d", b->GetName(), par->GetName(), offset);
153 
154  if (addEventElement(par, kTRUE)) {
155  TGo4EventElement ** par_ptr = (TGo4EventElement **) &((*fEventElements)[par->getId()]);
156  tree->SetBranchAddress(b->GetName(), par_ptr);
157  }
158 
159  i+=offset;
160  all_branches+=offset;
161  if (fDebug)
162  TGo4Log::Debug("-I from obj:%s activate indexing after offset:%d index:%d max:%d",
163  this->GetName(), offset, i, init+all_branches);
164  }
165 
166  // FIXME: do we need clear method here ????
167  // Clear();
168 
169  if (fDebug)
170  TGo4Log::Debug("-I activate return value from obj:%s offset:%i", GetName(), all_branches);
171 
172  return all_branches;
173 }
174 
175 void TGo4CompositeEvent::Clear(Option_t *opt)
176 {
177  //Clears the data in the event (i.e. clears the internal buffers...)
178 
180 
181  TIter next(fEventElements);
182  while (auto ev = (TGo4EventElement *)next())
183  ev->Clear(opt);
184 }
185 
186 Bool_t TGo4CompositeEvent::addEventElement(TGo4EventElement *aElement, Bool_t reading)
187 {
188  // if Identifiers are needed for fast retrieval of elements
189  // one should use:
190  // >>> fEventElements->AddAtAndExpand(aElement,aElement->getId());
191  // Note: When reading from file, adding elements should not be
192  // incremented
193 
194  // when trying to add same element second time do nothing
195  if (reading && fEventElements && fEventElements->FindObject(aElement)) return kTRUE;
196 
197  if (getEventElement(aElement->GetName(),1)) {
198  TGo4Log::Error("<TGo4CompositeEvent::addEventElement> object:%s already in structure => not added !",
199  aElement->GetName());
200  return kFALSE;
201  }
202 
203  if ( aElement->getId() < 0 ) {
204  TGo4Log::Error("<TGo4CompositeEvent::addEventElement> object:%s with invalid Id:%d => not added !",
205  aElement->GetName(), aElement->getId());
206  return kFALSE;
207  }
208 
209  if (getEventElement(aElement->getId()) != nullptr) {
210  TGo4Log::Error("<TGo4CompositeEvent::addEventElement> object:%s with Id:%d already used => not added !",
211  aElement->GetName(), aElement->getId());
212  return kFALSE;
213  }
214 
215  ProvideArray();
216 
217  if (fDebug)
218  TGo4Log::Debug("-I adding element in :%s :%p of id:%i",GetName(),aElement, aElement->getId());
219 
220  fEventElements->AddAtAndExpand(aElement,aElement->getId());
221  if(!reading) fNElements++;
222  if(aElement->getId()>fMaxIndex) fMaxIndex=aElement->getId();
223  if (fDebug)
224  TGo4Log::Debug("-I fNElements:%d fMaxIndex:%d",fNElements, fMaxIndex);
225 
226  return kTRUE;
227 }
228 
229 
231 {
232  // Returns a pointer to the partial event with array location idx.
233 
234  if (!fEventElements || (idx < 0) || (idx > fEventElements->GetLast()))
235  return nullptr;
236  return (TGo4EventElement *)fEventElements->At(idx);
237 }
238 
239 TGo4EventElement *TGo4CompositeEvent::getEventElement(const char *name, Int_t final_element)
240 {
241  TIter next(fEventElements);
242  while (auto ev = (TGo4EventElement *)next()) {
243  if(strcmp(name,ev->GetName()) == 0) return ev;
244  if (ev->isComposed()) {
245  TGo4EventElement *inter= ((TGo4CompositeEvent *) ev)->getEventElement(name,1);
246  if (inter) return inter;
247  }
248  }
249  if(final_element == 0)
250  TGo4Log::Debug("TGo4CompositeEvent => Element:%s not found in Composite:%s", name, GetName());
251  return nullptr;
252 }
253 
255 {
257 
258  TIter next(fEventElements);
259 
260  while (auto ev = (TGo4EventElement *)next())
261  ev->deactivate();
262 }
263 
264 
266 {
268 
269  TIter next(fEventElements);
270  while (auto ev = (TGo4EventElement *)next())
271  ev->activate();
272 }
273 
274 
275 TObjArray *TGo4CompositeEvent::getListOfComposites(Bool_t toplevel)
276 {
277  TObjArray *comp = new TObjArray(12);
278  if (toplevel) comp->Add(this);
279 
280  TIter next(fEventElements);
281  //-- Add top level composite
282  while (auto ev = (TGo4EventElement *)next()) {
283  if (ev->isComposed()) {
284  comp->Add( ev );
285  TObjArray *dump = ((TGo4CompositeEvent *) ev)->getListOfComposites(kFALSE);
286 
287  comp->AddAll(dump);
288 
289  // SL: memory leak, list should be removed
290  delete dump;
291  }
292  }
293  return comp;
294 }
295 
296 
298 {
299  if (!fEventElements || (i < 0) || (i > fEventElements->GetLast())) {
300  TGo4Log::Error("Wrong index %d in TGo4CompositeEvent::operator[]", i);
301  return *this;
302  }
303 
304  return * ((TGo4EventElement *) (fEventElements->At(i)));
305 }
306 
307 
309 {
310  if (!fEventElements) {
311  Int_t size = fMaxIndex+1;
312  fEventElements = new TObjArray(size);
313  if (fDebug)
314  TGo4Log::Debug("-I creating TObjArray of size %i",size);
315  }
316  if(fMaxIndex+1 >fEventElements->GetSize()) {
317  fEventElements->Expand(fMaxIndex+1);
318  if (fDebug)
319  TGo4Log::Debug("-I Expanded component array to size %i",fEventElements->GetSize());
320  }
321 }
322 
323 
325 {
326  TDirectory *filsav = gDirectory;
327  gROOT->cd();
328  if (sample) delete *sample;
329  TGo4CompositeEvent *clone = (TGo4CompositeEvent *) Clone();
330  TTree *thetree = new TTree(clone->GetName(), "Single Event Tree");
331  thetree->SetDirectory(nullptr);
332  if (sample) *sample = clone;
333  TBranch *topbranch =
334  thetree->Branch("Go4EventSample", clone->ClassName(), sample ? (TGo4CompositeEvent **) sample : &clone, 64000, 99);
335  clone->makeBranch(topbranch);
336  thetree->Fill();
337  filsav->cd();
338  if (!sample) delete clone;
339  return thetree;
340 }
TGo4EventElement & operator[](Int_t i) override
virtual void makeBranch(TBranch *parent)
virtual TGo4EventElement * GetChild(const char *name)
virtual Bool_t isComposed()
Bool_t addEventElement(TGo4EventElement *aElement, Bool_t reading=kFALSE)
void activate() override
void deactivate() override
TObjArray * getListOfComposites(Bool_t toplevel=kTRUE)
virtual void deactivate()
virtual Short_t getId()
TObjArray * fEventElements
static void Debug(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:281
TGo4EventElement * GetChild(const char *name) override
TTree * CreateSampleTree(TGo4EventElement **sample=nullptr) override
void makeBranch(TBranch *parent) override
void Clear(Option_t *opt="") override
TGo4EventElement * getEventElement(Int_t idx)
void Clear(Option_t *opt="") override
static void Error(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:320
virtual void activate()
Int_t activateBranch(TBranch *branch, Int_t init=0, TGo4EventElement **var_ptr=nullptr) override
virtual Int_t activateBranch(TBranch *branch, Int_t index=0, TGo4EventElement **var_ptr=nullptr)