GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4DynamicList.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 "TGo4DynamicList.h"
15 
16 #include <stdexcept>
17 #include <cstdlib>
18 
19 #include "TFolder.h"
20 #include "TDataMember.h"
21 #include "TDataType.h"
22 #include "TBaseClass.h"
23 #include "TH1.h"
24 #include "TList.h"
25 #include "TROOT.h"
26 
28 #include "TGo4HistogramEntry.h"
29 #include "TGo4TreeHistogramEntry.h"
30 #include "TGo4EventElement.h"
31 #include "TGo4Status.h"
32 #include "TGo4AnalysisImp.h"
33 
34 void TGo4DynamicList::ResetEntries(TFolder *folder)
35 {
36  if (!folder) return;
37 
38  TIter iter(folder->GetListOfFolders());
39  while(auto obj = iter()) {
40  TGo4DynamicEntry *entry = dynamic_cast<TGo4DynamicEntry *> (obj);
41  if (entry) entry->Reset();
42  }
43 }
44 
45 void TGo4DynamicList::PrintEntries(TFolder *folder)
46 {
47  if (!folder) return;
48 
49  TIter iter(folder->GetListOfFolders());
50  while(auto obj = iter()) {
51  TGo4DynamicEntry *entry = dynamic_cast<TGo4DynamicEntry *> (obj);
52  if (entry) entry->Print("*");
53  }
54 }
55 
56 void TGo4DynamicList::CleanupPointerInEntries(TFolder *folder, TObject *objtoremove)
57 {
58  if (!folder) return;
59 
60  TIter iter(folder->GetListOfFolders());
61  while(auto obj = iter()) {
62  TGo4DynamicEntry *entry = dynamic_cast<TGo4DynamicEntry *> (obj);
63  if (entry) entry->RecursiveRemove(objtoremove);
64  }
65 }
66 
67 
68 void TGo4DynamicList::ProcessEntries(TFolder *folder, Bool_t processtrees, Int_t interval)
69 {
70  if (!folder) return;
71 
72  TGo4DynamicEntry *errorentry = nullptr;
73  TIter iter(folder->GetListOfFolders());
74 
75  try {
76  while(auto obj = iter()) {
77  TGo4DynamicEntry *entry = dynamic_cast<TGo4DynamicEntry *> (obj);
78  if (!entry) continue;
79 
80  try {
81  if (!entry->IsEnabledProcessing()) continue;
82 
83  if (!ProcessHEntry(dynamic_cast<TGo4HistogramEntry*> (entry))) {
84  errorentry = entry;
85  break;
86  }
87 
88  if (!ProcessTEntry(dynamic_cast<TGo4TreeHistogramEntry*> (entry), processtrees, interval)) {
89  errorentry = entry;
90  break;
91  }
92  }
93  catch(TGo4DynamicListException& ex) {
94  ex.Handle(); // will disable the error causing entry, continue other entries
95  errorentry = (TGo4DynamicEntry *) entry;
96  }
97  } // while
98  //if(processtrees) TGo4Analysis::Instance()->ResetBackStores(kTRUE); // clear backstore reset bits
99  // note: the above call is redundant in current usage, because in processtrees case the
100  // backstore is immediately reset again for the next time
101  // (buffer reset interval equals treedraw interval)
102  }
103  catch(std::exception& ex) { // treat standard library exceptions
104  throw TGo4DynamicListException(errorentry,
105  TString::Format("!!!STD exception %s was raised processing dynamic entry!!!", ex.what()).Data());
106  }
107 }
108 
109 TDataMember *FindDataMember(TClass *eventclass,
110  const char *memname,
111  Long_t* totaloffset)
112 {
113  if(!eventclass) return nullptr;
114  // here we might parse the memname for dots to figure out aggregated classes
115 
117  // check for array member index:
118  Long_t indexoffset = 0;
119  const char *ixbegin = strchr(memname,'[');
120  if(ixbegin) {
121  // std::cout <<"-------------FindDataMember of Entry " << GetName() << std::endl;
122  // std::cout <<"Found index in member" << memname << std::endl;
123  ixbegin++;
124  const char *ixend = strchr(ixbegin,']');
125  if(ixend) {
126  TString buf(ixbegin, ixend-ixbegin);
127  indexoffset = buf.Atoll();
128  if(indexoffset < 0) indexoffset = 0;
129  }
130  }
132 
133  TDataMember *eventmember = eventclass->GetDataMember(memname);
134  if(eventmember) {
135  *totaloffset+=eventmember->GetOffset();
136  } else {
137  // if not found directly, check for baseclass members:
138  TIter baseiter(eventclass->GetListOfBases());
139  while(auto ob = baseiter()) {
140  TBaseClass* baseclass = dynamic_cast<TBaseClass*>(ob);
141  if(baseclass)
142  {
143  // we have a baseclass
144  TClass *bclass = baseclass->GetClassPointer();
145  // search for member in all superclasses recursively:
146  eventmember = FindDataMember(bclass, memname, totaloffset);
147  if (eventmember) {
148  // we found member in any of the baseclasses
149  *totaloffset+=baseclass->GetDelta();
150  // inc total offset to this by baseclass offset
151  // member offset is relative to TClass (i.e. baseclass here)
152  break;
153  }
154  } // if(baseclass)
155  } // while
156  } // if (eventmember)
157 
158  // finally, we check for eventmember type to add
159  //correct offset in case of array:
160  if(eventmember)
161  {
162  const char *tname = eventmember->GetFullTypeName();
163  // check if given index is inside allocated size:
164  Int_t maxindex = eventmember->GetMaxIndex(0);
165  if(maxindex < 0) maxindex = 1; // for non-array members maxindex is -1
166  if(indexoffset<maxindex)
167  {
168  Int_t datasize = eventmember->GetDataType()->Size();
169  *totaloffset += indexoffset*datasize;
170  }
171  else
172  {
173  throw TGo4DynamicListException(nullptr,
174  TString::Format("Index %ld for array member:%s out of range %s[%d]", indexoffset, memname, tname, maxindex).Data());
175  }
176  }
177 
178  return eventmember;
179 }
180 
182 {
183  if (!hentry) return true;
184 
185  if (hentry->NeedInitialisation()) {
187 
188  hentry->fxCondition = ana->GetAnalysisCondition(hentry->GetConditionName());
189 
190  for(Int_t n = 0; n < __MAXCONDIM__; n++) {
191  TGo4EventElement *event = nullptr;
192  TDataMember *eventmember = nullptr;
193  Long_t offset = 0;
194 
195  const char *evname = hentry->GetConEventName(n);
196  const char *memname = hentry->GetConVarName(n);
197 
198  if (!TString(evname).Contains(TGo4HistogramEntry::Get_fgcNOEVENT()))
199  event = ana->GetEventStructure(evname);
200 
201  if(event)
202  if(!TString(memname).Contains(TGo4HistogramEntry::Get_fgcNODATA()))
203  eventmember = FindDataMember(event->IsA(), memname, &offset);
204 
205  hentry->InitCondPointer(n, event, eventmember, offset);
206  }
207 
208  hentry->fxHistogram = ana->GetHistogram(hentry->GetHistogramName());
209 
210  for (Int_t n = 0; n < __MAXHISDIM__; n++) {
211  TGo4EventElement *event = nullptr;
212  TDataMember *eventmember = nullptr;
213  Long_t offset = 0;
214 
215  const char *evname = hentry->GetHistEventName(n);
216  const char *memname = hentry->GetHistVarName(n);
217 
218  if (!TString(evname).Contains(TGo4HistogramEntry::Get_fgcNOEVENT()))
219  event = ana->GetEventStructure(evname);
220 
221  if(event)
222  if(!TString(memname).Contains(TGo4HistogramEntry::Get_fgcNODATA()))
223  eventmember = FindDataMember(event->IsA(), memname, &offset);
224 
225  hentry->InitHistPointer(n, event, eventmember, offset);
226  }
227 
228  hentry->SetNeedInitialisation(kFALSE);
229  }
230 
231  Bool_t evvalid[__MAXHISDIM__];
232  for (Int_t n = 0; n < __MAXHISDIM__; n++) {
233  evvalid[n] = kFALSE;
234  TGo4EventElement *event = (TGo4EventElement *) hentry->fxHisEvents[n];
235  if (event)
236  evvalid[n] = event->IsValid();
237  }
238 
239  hentry->ProcessNew(evvalid);
240 
241  return true;
242 }
243 
244 bool TGo4DynamicList::ProcessTEntry(TGo4TreeHistogramEntry* tentry, Bool_t processtrees, Int_t interval)
245 {
246  if (!tentry) return true;
247 
248  tentry->SetDynListInterval(interval);
249 
250  if(!processtrees) return true;
251 
252  const char *hname = tentry->GetHistogramName();
253 
254  TTree *tree = TGo4Analysis::Instance()->GetTree(tentry->GetTreeName());
255  if (!tree) {
256  throw TGo4DynamicListException(tentry,
257  TString::Format("Tree Histogram Entry: !!! Could not find Tree %s ",tentry->GetTreeName()).Data());
258  }
259 
260  TH1 *histo = TGo4Analysis::Instance()->GetHistogram(hname);
261  //if(!histo) std::cout <<"ProcessTEntry do did not find histo "<<hname << std::endl;
262  if (!tentry->fbNewHistogram && !histo) {
263  throw TGo4DynamicListException(tentry,
264  TString::Format("Tree Histogram Entry: !!! Could not find Histogram %s ",hname).Data());
265  }
266 
267  if (histo)
268  tentry->fbNewHistogram = kFALSE;
269 
271 
272  if (tentry->fbNewHistogram) {
273  histo = dynamic_cast<TH1 *>(gROOT->FindObject(hname));
274  if(!histo)
275  histo = dynamic_cast<TH1 *>(gROOT->FindObjectAny(hname));
276  // note JA: FindObject fails with histogram created in hsimple.C on Cintserver when gDirectory was different from gRoot
277  // in this case, histogram is only available in TRoot::fList via scan over root folders
278  // note2: second fix is in TGo4Analysis::Process() which explicitely resets gDirectory to gROOT
279  // before entering the MainCycle(); so FindObjectAny should be never necessary now
280  if(histo) {
281  TGo4Analysis::Instance()->AddHistogram(histo); // we put the new histogram into our histo folder!
282  histo->SetBit(TGo4Status::kGo4CanDelete);
283  tentry->fbNewHistogram=kFALSE;
284  }
285  }
286 
287  return true;
288 }
virtual void Reset()
void SetNeedInitialisation(Bool_t on=kTRUE)
static void CleanupPointerInEntries(TFolder *folder, TObject *obj)
const char * GetConEventName(Int_t ix) const
const char * GetTreeName() const
const char * GetHistEventName(Int_t ix) const
const char * GetConVarName(Int_t ix) const
void ProcessTreeNew(TTree *tree, Int_t times)
void SetDynListInterval(Int_t value)
#define __MAXHISDIM__
TGo4Condition * GetAnalysisCondition(const char *name, const char *cond_cl=nullptr)
const char * GetHistogramName() const
void InitCondPointer(Int_t ix, TObject *event, TDataMember *member, Long_t offset)
Bool_t IsEnabledProcessing() const
static void ResetEntries(TFolder *folder)
static bool ProcessHEntry(TGo4HistogramEntry *hentry)
TH1 * GetHistogram(const char *name)
Bool_t NeedInitialisation() const
static bool ProcessTEntry(TGo4TreeHistogramEntry *tentry, Bool_t processtrees, Int_t interval)
TTree * GetTree(const char *name)
Bool_t AddHistogram(TH1 *his, const char *subfolder=nullptr, Bool_t replace=kTRUE)
#define __MAXCONDIM__
static void PrintEntries(TFolder *folder)
static const char * Get_fgcNODATA()
TDataMember * FindDataMember(TClass *eventclass, const char *memname, Long_t *totaloffset)
TObject * fxHisEvents[__MAXHISDIM__]
void InitHistPointer(Int_t ix, TObject *event, TDataMember *member, Long_t offset)
TGo4EventElement * GetEventStructure(const char *name) const
const char * GetConditionName() const
Int_t GetDynListInterval() const
void ProcessNew(Bool_t *evvalid)
static TGo4Analysis * Instance()
static const char * Get_fgcNOEVENT()
TGo4Condition * fxCondition
const char * GetHistVarName(Int_t ix) const
const char * GetHistogramName() const
static void ProcessEntries(TFolder *folder, Bool_t processtrees, Int_t interval)