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