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