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