GSI Object Oriented Online Offline (Go4) GO4-6.4.0
Loading...
Searching...
No Matches
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"
30#include "TGo4EventElement.h"
31#include "TGo4Status.h"
32#include "TGo4AnalysisImp.h"
33
34void 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
45void 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
56void 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
68void 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
109TDataMember *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
244bool 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
270 tentry->ProcessTreeNew(tree, TGo4Analysis::Instance()->GetDynListInterval());
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}
TDataMember * FindDataMember(TClass *eventclass, const char *memname, Long_t *totaloffset)
#define __MAXHISDIM__
#define __MAXCONDIM__
The mother of all go4 analysis.
static TGo4Analysis * Instance()
return analysis instance
TGo4EventElement * GetEventStructure(const char *name) const
Search reference to event structure in folder.
TH1 * GetHistogram(const char *name)
Search histogram in histogram list (directory).
Bool_t AddHistogram(TH1 *his, const char *subfolder=nullptr, Bool_t replace=kTRUE)
Add external histogram to go4 histogram directory.
TGo4Condition * GetAnalysisCondition(const char *name, const char *cond_cl=nullptr)
Retrieves an analysis condition from list by name.
TTree * GetTree(const char *name)
Search tree in tree folder.
ABC for all entries that can be kept in a dynamic list.
virtual void Reset()
Resets this entry to an initial status.
Bool_t IsEnabledProcessing() const
Int_t Handle() override
This is a default handler function for the respective exception type.
static bool ProcessHEntry(TGo4HistogramEntry *hentry)
static void ProcessEntries(TFolder *folder, Bool_t processtrees, Int_t interval)
Iterates all entries of the list and processes the objects, depending on coordinate values and analys...
static void PrintEntries(TFolder *folder)
static bool ProcessTEntry(TGo4TreeHistogramEntry *tentry, Bool_t processtrees, Int_t interval)
static void ResetEntries(TFolder *folder)
static void CleanupPointerInEntries(TFolder *folder, TObject *obj)
The abstract base class for the data elements of which the unpacked events (or detector structure dat...
Entry for the dynamic list, specialized for histogram like objects.
TObject * fxHisEvents[__MAXHISDIM__]
Pointer for event objects, class does not known to entry itself.
const char * GetConVarName(Int_t ix) const
TH1 * fxHistogram
The (histogram) object kept by this entry.
const char * GetHistogramName() const
Get name of the external histogram to be filled.
void InitHistPointer(Int_t ix, TObject *event, TDataMember *member, Long_t offset)
static const char * Get_fgcNOEVENT()
const char * GetHistEventName(Int_t ix) const
Bool_t NeedInitialisation() const
const char * GetConEventName(Int_t ix) const
void InitCondPointer(Int_t ix, TObject *event, TDataMember *member, Long_t offset)
const char * GetConditionName() const
void ProcessNew(Bool_t *evvalid)
void SetNeedInitialisation(Bool_t on=kTRUE)
const char * GetHistVarName(Int_t ix) const
static const char * Get_fgcNODATA()
TGo4Condition * fxCondition
Condition to be checked on processing this entry.
Dynamic list entry which links a histogram to a certain tree.
Bool_t fbNewHistogram
True before Process is called the first time.
const char * GetTreeName() const
const char * GetHistogramName() const
Get name of the external histogram to be filled.
void SetDynListInterval(Int_t value)
void ProcessTreeNew(TTree *tree, Int_t times)