Update master to aliroot
[u/mrichter/AliRoot.git] / STEER / AOD / AliAODExtension.cxx
CommitLineData
14d6fad5 1#include "AliAODExtension.h"
2
3//-------------------------------------------------------------------------
4// Support class for AOD extensions. This is created by the user analysis
5// that requires a separate file for some AOD branches. The name of the
6// AliAODExtension object is the file name where the AOD branches will be
7// stored.
8//-------------------------------------------------------------------------
9
10#include "AliAODBranchReplicator.h"
11#include "AliAODEvent.h"
12#include "AliCodeTimer.h"
13#include "AliLog.h"
14#include "Riostream.h"
15#include "TDirectory.h"
16#include "TFile.h"
17#include "TList.h"
18#include "TMap.h"
19#include "TMap.h"
20#include "TObjString.h"
21#include "TROOT.h"
22#include "TString.h"
23#include "TTree.h"
24
66b0310c 25using std::endl;
26using std::cout;
14d6fad5 27ClassImp(AliAODExtension)
28
29//______________________________________________________________________________
30AliAODExtension::AliAODExtension() : TNamed(),
31fAODEvent(0), fTreeE(0), fFileE(0), fNtotal(0), fNpassed(0),
92f945a7 32fSelected(kFALSE), fTreeBuffSize(30000000), fMemCountAOD(0),
7e68d49f 33fRepFiMap(0x0), fRepFiList(0x0), fEnableReferences(kTRUE), fObjectList(0)
14d6fad5 34{
35 // default ctor
36}
37
38//______________________________________________________________________________
39AliAODExtension::AliAODExtension(const char* name, const char* title, Bool_t isfilter)
40:TNamed(name,title),
41fAODEvent(0),
42fTreeE(0),
43fFileE(0),
44fNtotal(0),
45fNpassed(0),
46fSelected(kFALSE),
92f945a7 47fTreeBuffSize(30000000),
48fMemCountAOD(0),
14d6fad5 49fRepFiMap(0x0),
50fRepFiList(0x0),
51fEnableReferences(kTRUE),
52fObjectList(0x0)
53{
54 // Constructor.
55 if (isfilter) {
56 TObject::SetBit(kFilteredAOD);
57 printf("####### Added AOD filter %s\n", name);
58 } else printf("####### Added AOD extension %s\n", name);
59 KeepUnspecifiedBranches();
60}
61
62//______________________________________________________________________________
63AliAODExtension::~AliAODExtension()
64{
65 // Destructor.
66 if(fFileE){
67 // is already handled in TerminateIO
68 fFileE->Close();
69 delete fFileE;
70 fTreeE = 0;
71 fAODEvent = 0;
72 }
73 if (fTreeE) delete fTreeE;
74 if (fRepFiMap) fRepFiMap->DeleteAll();
75 delete fRepFiMap; // the map is owner
76 delete fRepFiList; // the list is not
77 delete fObjectList; // not owner
78}
79
80//______________________________________________________________________________
81void AliAODExtension::AddBranch(const char* cname, void* addobj)
82{
83 // Add a new branch to the aod
84
85 if (!fAODEvent) {
86 char type[20];
87 gROOT->ProcessLine(Form("TString s_tmp; AliAnalysisManager::GetAnalysisManager()->GetAnalysisTypeString(s_tmp); sprintf((char*)%p, \"%%s\", s_tmp.Data());", type));
88 Init(type);
89 }
90 TDirectory *owd = gDirectory;
91 if (fFileE) {
92 fFileE->cd();
93 }
94 char** apointer = (char**) addobj;
95 TObject* obj = (TObject*) *apointer;
96
97 fAODEvent->AddObject(obj);
98
99 TString bname(obj->GetName());
100
101 if (!fTreeE->FindBranch(bname.Data()))
102 {
103 Bool_t acceptAdd(kTRUE);
104
105 if ( TestBit(kDropUnspecifiedBranches) )
106 {
107 // check that this branch is in our list of specified ones...
108 // otherwise do not add it !
109 TIter next(fRepFiMap);
110 TObjString* p;
111
112 acceptAdd=kFALSE;
113
114 while ( ( p = static_cast<TObjString*>(next()) ) && !acceptAdd )
115 {
116 if ( p->String() == bname ) acceptAdd=kTRUE;
117 }
118 }
119
120 if ( acceptAdd )
121 {
122 // Do the same as if we book via
123 // TTree::Branch(TCollection*)
124
125 fObjectList->Add(obj);
126
127 const Int_t kSplitlevel = 99; // default value in TTree::Branch()
128 const Int_t kBufsize = 32000; // default value in TTree::Branch()
129
130 fTreeE->Bronch(bname.Data(), cname,
131 fAODEvent->GetList()->GetObjectRef(obj),
132 kBufsize, kSplitlevel - 1);
133 }
134 }
135 owd->cd();
136}
137
138//______________________________________________________________________________
139Bool_t AliAODExtension::FinishEvent()
140{
141 // Fill current event.
142 fNtotal++;
143 if (!IsFilteredAOD()) {
144 fAODEvent->MakeEntriesReferencable();
92f945a7 145 FillTree();
14d6fad5 146 return kTRUE;
147 }
148 // Filtered AOD. Fill only if event is selected.
149 if (!fSelected) return kTRUE;
150
151 TIter next(fRepFiList);
152
153 AliAODBranchReplicator* repfi;
154
155 while ( ( repfi = static_cast<AliAODBranchReplicator*>(next()) ) )
156 {
157 repfi->ReplicateAndFilter(*fAODEvent);
158 }
159 fNpassed++;
92f945a7 160 FillTree();
14d6fad5 161 fSelected = kFALSE; // so that next event will not be selected unless demanded
162 return kTRUE;
163}
164
165//______________________________________________________________________________
92f945a7 166void AliAODExtension::FillTree()
167{
168 //
169 // Fill AOD extension tree and check AutoFlush settings
170 //
171
172 Long64_t nbf = fTreeE->Fill();
173
174 // Check buffer size and set autoflush if fTreeBuffSize is reached
175 if (fTreeBuffSize>0 && fTreeE->GetAutoFlush()<0 &&
176 (fMemCountAOD += nbf)>fTreeBuffSize ) { // default limit is still not reached
177 nbf = fTreeE->GetZipBytes();
178 if (nbf>0) nbf = -nbf;
179 else nbf = fTreeE->GetEntries();
180 fTreeE->SetAutoFlush(nbf);
181 AliInfo(Form("Calling fTreeE->SetAutoFlush(%lld) | W:%lld T:%lld Z:%lld",
182 nbf,fMemCountAOD,fTreeE->GetTotBytes(),fTreeE->GetZipBytes()));
183
184 }
185}
186
187//______________________________________________________________________________
14d6fad5 188Bool_t AliAODExtension::Init(Option_t *option)
189{
190 // Initialize IO.
191
192 AliCodeTimerAuto(GetName(),0);
193
194 if(!fAODEvent)
195 {
196 fAODEvent = new AliAODEvent();
197 }
198
199 TDirectory *owd = gDirectory;
200 TString opt(option);
201 opt.ToLower();
202
203 if (opt.Contains("proof"))
204 {
205 // proof
206 // Merging via files. Need to access analysis manager via interpreter.
207 gROOT->ProcessLine(Form("AliAnalysisDataContainer *c_common_out = AliAnalysisManager::GetAnalysisManager()->GetCommonOutputContainer();"));
208 gROOT->ProcessLine(Form("AliAnalysisManager::GetAnalysisManager()->OpenProofFile(c_common_out, \"RECREATE\", \"%s\");", fName.Data()));
209 fFileE = gFile;
210 }
211 else
212 {
213 fFileE = new TFile(GetName(), "RECREATE");
214 }
215 fTreeE = new TTree("aodTree", "AliAOD tree");
216
217 delete fObjectList;
218 fObjectList = new TList;
219 fObjectList->SetOwner(kFALSE); // be explicit we're not the owner...
220 TList* inputList = fAODEvent->GetList();
221 TIter next(inputList);
222 TObject* o;
223
224 while ( ( o = next() ) )
225 {
226 // Loop on the objects that are within the main AOD, and see what to do with them :
227 // - transmit them to our AOD as they are
228 // - filter them (by means of an AliAODBranchReplicator)
229 // - drop them completely
230
231 Bool_t mustKeep(kFALSE);
232
233 TString test(o->ClassName());
234 test.ToUpper();
97aa6e17 235 // check if there is a replicator for the header
236 Bool_t headerHasReplicator = fRepFiMap && (fRepFiMap->FindObject(o->GetName())!=0x0);
237 if (test.BeginsWith("ALIAODHEADER") && !headerHasReplicator)
14d6fad5 238 {
239 // do not allow to drop header branch
240 mustKeep=kTRUE;
241 }
242
243 if ( fRepFiMap && !mustKeep )
244 {
245 // we have some replicators, so let's see what the relevant one decides about this object
246 TObject* specified = fRepFiMap->FindObject(o->GetName()); // FindObject finds key=o->GetName() in the map
247 if (specified)
248 {
249 AliAODBranchReplicator* repfi = dynamic_cast<AliAODBranchReplicator*>(fRepFiMap->GetValue(o->GetName())); // GetValue gets the replicator corresponding to key=o->GetName()
250 if ( repfi )
251 {
252 TList* replicatedList = repfi->GetList();
253 if (replicatedList)
254 {
255 AliAODEvent::AssignIDtoCollection(replicatedList);
256 TIter nextRep(replicatedList);
257 TObject* objRep;
258 while ( ( objRep = nextRep() ) )
259 {
260 if ( !fObjectList->FindObject(objRep) ) // insure we're not adding several times the same object
261 {
262 fObjectList->Add(objRep);
263 }
264 }
265 }
266 else
267 {
268 AliError(Form("replicatedList from %s is null !",repfi->GetName()));
269 }
270 }
271 }
272 else
273 {
274 if ( !TestBit(kDropUnspecifiedBranches) )
275 {
276 // object o will be transmitted to the output AOD, unchanged
277 fObjectList->Add(o);
278 }
279 }
280 }
281 else
282 {
283 // no replicator, so decide based on the policy about dropping unspecified branches
284 if ( mustKeep || !TestBit(kDropUnspecifiedBranches) )
285 {
286 // object o will be transmitted to the output AOD, unchanged
287 fObjectList->Add(o);
288 }
289 }
290 }
291
292 if (fEnableReferences)
293 {
294 fTreeE->BranchRef();
295 }
296
297 fTreeE->Branch(fObjectList);
298
299 owd->cd();
300
301 return kTRUE;
302}
303
304//______________________________________________________________________________
305void AliAODExtension::Print(Option_t* opt) const
306{
307 // Print info about this extension
308
309 cout << opt << Form("%s - %s - %s - aod %p",IsFilteredAOD() ? "FilteredAOD" : "Extension",
310 GetName(),GetTitle(),GetAOD()) << endl;
311 if ( !fEnableReferences )
312 {
313 cout << opt << opt << "References are disabled ! Hope you know what you are doing !" << endl;
314 }
315 if ( TestBit(kDropUnspecifiedBranches) )
316 {
317 cout << opt << opt << "All branches not explicitely specified will be dropped" << endl;
318 }
319
320 TIter next(fRepFiMap);
321 TObjString* s;
322
323 while ( ( s = static_cast<TObjString*>(next()) ) )
324 {
325 AliAODBranchReplicator* br = static_cast<AliAODBranchReplicator*>(fRepFiMap->GetValue(s->String().Data()));
326
327 cout << opt << opt << "Branch " << s->String();
328 if (br)
329 {
330 cout << " will be filtered by class " << br->ClassName();
331 }
332 else
333 {
334 cout << " will be transmitted as is";
335 }
336 cout << endl;
337 }
338}
339
340//______________________________________________________________________________
341void AliAODExtension::SetEvent(AliAODEvent* event)
342{
343 // Connects to an external event
344 if (!IsFilteredAOD()) {
345 Error("SetEvent", "Not allowed to set external event for non filtered AOD's");
346 return;
347 }
348 fAODEvent = event;
349}
350
351//______________________________________________________________________________
352void AliAODExtension::AddAODtoTreeUserInfo()
353{
354 // Add aod event to tree user info
355
356 if (!fTreeE) return;
357
358 AliAODEvent* aodEvent(fAODEvent);
359
360 if ( IsFilteredAOD() )
361 {
362 // cannot attach fAODEvent (which is shared with our AliAODHandler mother)
363 // so we create a custom (empty) AliAODEvent
364 // Has also the advantage we can specify only the list of objects
365 // that are actually there in this filtered aod
366 //
367 aodEvent = new AliAODEvent;
368 TIter nextObj(fObjectList);
369 TObject* o;
370 while ( ( o = nextObj() ) )
371 {
372 aodEvent->AddObject(o);
373 }
374 }
1045cbad
AM
375
376 TList *l = aodEvent->GetList();
377 if (l) {
378 for(int i = 0;i < l->GetEntries(); ++i){
379 TObject *pObject = l->At(i);
380 if(pObject->InheritsFrom(TClonesArray::Class())){
381 ((TClonesArray*)pObject)->Delete();
382 } else if(!pObject->InheritsFrom(TCollection::Class())){
383 TClass *pClass = TClass::GetClass(pObject->ClassName());
384 if (pClass && pClass->GetListOfMethods()->FindObject("Clear")) {
385 AliDebug(1, Form("Clear for object %s class %s", pObject->GetName(), pObject->ClassName()));
386 pObject->Clear();
387 }
388 } else {
389 AliWarning(Form("No method to clear for object %s class %s", pObject->GetName(), pObject->ClassName()));
390 }
391 }
392 }
14d6fad5 393 fTreeE->GetUserInfo()->Add(aodEvent);
394}
395
396//______________________________________________________________________________
397Bool_t AliAODExtension::TerminateIO()
398{
399 // Terminate IO
400 if (TObject::TestBit(kFilteredAOD))
401 printf("AOD Filter %s: events processed: %d passed: %d\n", GetName(), fNtotal, fNpassed);
402 else
403 printf("AOD extension %s: events processed: %d\n", GetName(), fNtotal);
404 if (fFileE)
405 {
406 fFileE->Write();
407 fFileE->Close();
408 delete fFileE;
409 fFileE = 0;
410 fTreeE = 0;
411 fAODEvent = 0;
412 }
413 return kTRUE;
414}
415
416//______________________________________________________________________________
417void AliAODExtension::FilterBranch(const char* branchName, AliAODBranchReplicator* repfi)
418{
419 // Specify a filter/replicator for a given branch
420 //
421 // If repfi=0x0, this will disable the branch (in the output) completely.
422 //
423 // repfi is adopted by this class, i.e. user should not delete it.
424 //
425 // WARNING : branch name must be exact.
426 //
427 // See also the documentation for AliAODBranchReplicator class.
428 //
429
430 if (!fRepFiMap)
431 {
432 fRepFiMap = new TMap;
433 fRepFiMap->SetOwnerKeyValue(kTRUE,kTRUE);
434 fRepFiList = new TList;
435 fRepFiList->SetOwner(kFALSE);
436 }
437
438 fRepFiMap->Add(new TObjString(branchName),repfi);
439
440 if (repfi && !fRepFiList->FindObject(repfi))
441 {
442 // insure we get unique and non-null replicators in this list
443 fRepFiList->Add(repfi);
444 }
445}
446