]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AOD/AliAODHandler.cxx
AliAODEvent::GetHeader() returns AliVHeader
[u/mrichter/AliRoot.git] / STEER / AOD / AliAODHandler.cxx
1
2 /**************************************************************************
3  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4  *                                                                        *
5  * Author: The ALICE Off-line Project.                                    *
6  * Contributors are mentioned in the code where appropriate.              *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /* $Id$ */
18
19 //-------------------------------------------------------------------------
20 //     Implementation of the Virtual Event Handler Interface for AOD
21 //     Author: Andreas Morsch, CERN
22 //-------------------------------------------------------------------------
23
24
25 #include <TTree.h>
26 #include <TFile.h>
27 #include <TString.h>
28 #include <TList.h>
29 #include <TROOT.h>
30
31 #include "AliLog.h"
32 #include "AliAODHandler.h"
33 #include "AliAODEvent.h"
34 #include "AliAODExtension.h"
35 #include "AliAODTracklets.h"
36 #include "AliStack.h"
37 #include "AliAODMCParticle.h"
38 #include "AliAODMCHeader.h"
39 #include "AliMCEventHandler.h"
40 #include "AliMCEvent.h"
41 #include "AliGenEventHeader.h"
42 #include "AliGenHijingEventHeader.h"
43 #include "AliGenDPMjetEventHeader.h"
44 #include "AliGenPythiaEventHeader.h"
45 #include "AliGenCocktailEventHeader.h"
46 #include "AliCodeTimer.h"
47 #include "AliAODBranchReplicator.h"
48 #include "Riostream.h"
49
50 using std::endl;
51 using std::cout;
52 ClassImp(AliAODHandler)
53
54 //______________________________________________________________________________
55 AliAODHandler::AliAODHandler() :
56     AliVEventHandler(),
57     fIsStandard(kTRUE),
58     fFillAOD(kTRUE),
59     fFillAODRun(kTRUE),
60     fFillExtension(kTRUE),
61     fNeedsHeaderReplication(kFALSE),
62     fNeedsTOFHeaderReplication(kFALSE),
63     fNeedsVZEROReplication(kFALSE),
64     fNeedsTracksBranchReplication(kFALSE),
65     fNeedsVerticesBranchReplication(kFALSE),
66     fNeedsV0sBranchReplication(kFALSE),
67     fNeedsCascadesBranchReplication(kFALSE),
68     fNeedsTrackletsBranchReplication(kFALSE),
69     fNeedsPMDClustersBranchReplication(kFALSE),
70     fNeedsJetsBranchReplication(kFALSE),
71     fNeedsFMDClustersBranchReplication(kFALSE),
72     fNeedsCaloClustersBranchReplication(kFALSE),
73         fNeedsCaloTriggerBranchReplication(kFALSE),
74     fNeedsMCParticlesBranchReplication(kFALSE),
75     fNeedsDimuonsBranchReplication(kFALSE),
76     fNeedsHMPIDBranchReplication(kFALSE),
77     fAODIsReplicated(kFALSE),
78     fTreeBuffSize(30000000),
79     fMemCountAOD(0),
80     fAODEvent(NULL),
81     fMCEventH(NULL),
82     fTreeA(NULL),
83     fFileA(NULL),
84     fFileName(""),
85     fExtensions(NULL),
86     fFilters(NULL)
87 {
88   // default constructor
89 }
90
91 //______________________________________________________________________________
92 AliAODHandler::AliAODHandler(const char* name, const char* title):
93     AliVEventHandler(name, title),
94     fIsStandard(kTRUE),
95     fFillAOD(kTRUE),
96     fFillAODRun(kTRUE),
97     fFillExtension(kTRUE),
98     fNeedsHeaderReplication(kFALSE),
99     fNeedsTOFHeaderReplication(kFALSE),
100     fNeedsVZEROReplication(kFALSE),
101     fNeedsTracksBranchReplication(kFALSE),
102     fNeedsVerticesBranchReplication(kFALSE),
103     fNeedsV0sBranchReplication(kFALSE),
104     fNeedsCascadesBranchReplication(kFALSE),
105     fNeedsTrackletsBranchReplication(kFALSE),
106     fNeedsPMDClustersBranchReplication(kFALSE),
107     fNeedsJetsBranchReplication(kFALSE),
108     fNeedsFMDClustersBranchReplication(kFALSE),
109     fNeedsCaloClustersBranchReplication(kFALSE),
110     fNeedsCaloTriggerBranchReplication(kFALSE),
111     fNeedsMCParticlesBranchReplication(kFALSE),
112     fNeedsDimuonsBranchReplication(kFALSE),
113     fNeedsHMPIDBranchReplication(kFALSE),
114     fAODIsReplicated(kFALSE),
115     fTreeBuffSize(30000000),
116     fMemCountAOD(0),
117     fAODEvent(NULL),
118     fMCEventH(NULL),
119     fTreeA(NULL),
120     fFileA(NULL),
121     fFileName(""),
122     fExtensions(NULL),
123     fFilters(NULL)
124 {
125 // Normal constructor.
126 }
127
128 //______________________________________________________________________________
129 AliAODHandler::~AliAODHandler() 
130 {
131  // Destructor.
132   
133   delete fAODEvent;
134
135   if (fFileA) fFileA->Close();
136
137   delete fFileA;
138   delete fTreeA;
139   delete fExtensions;
140   delete fFilters;
141 }
142
143 //______________________________________________________________________________
144 Bool_t AliAODHandler::Init(Option_t* opt)
145 {
146   // Initialize IO
147   //
148   // Create the AODevent object
149     
150   Bool_t createStdAOD = fIsStandard || fFillAOD;
151   if(!fAODEvent && createStdAOD){
152     fAODEvent = new AliAODEvent();
153     if (fIsStandard) 
154       fAODEvent->CreateStdContent();
155   }
156   //
157   // File opening according to execution mode
158   TString option(opt);
159   option.ToLower();
160   if (createStdAOD) {
161     TDirectory *owd = gDirectory;
162     if (option.Contains("proof")) {
163       // proof
164       // Merging via files. Need to access analysis manager via interpreter.
165       gROOT->ProcessLine(Form("AliAnalysisDataContainer *c_common_out = AliAnalysisManager::GetAnalysisManager()->GetCommonOutputContainer();"));
166       gROOT->ProcessLine(Form("AliAnalysisManager::GetAnalysisManager()->OpenProofFile(c_common_out, \"RECREATE\");"));
167       fFileA = gFile;
168     } else {
169       // local and grid
170       fFileA = new TFile(fFileName.Data(), "RECREATE");
171     }
172     CreateTree(1);
173     owd->cd();
174   }  
175   if (fExtensions) {
176      TIter next(fExtensions);
177      AliAODExtension *ext;
178      while ((ext=(AliAODExtension*)next())) ext->Init(option);
179   }   
180   if (fFilters) {
181      TIter nextf(fFilters);
182      AliAODExtension *filteredAOD;
183      while ((filteredAOD=(AliAODExtension*)nextf())) {
184         filteredAOD->SetEvent(fAODEvent);
185         filteredAOD->Init(option);
186      }
187   }   
188   
189   return kTRUE;
190 }
191
192 //______________________________________________________________________________
193 void AliAODHandler::Print(Option_t* opt) const
194 {
195   // Print info about this object
196
197   cout << opt << Form("IsStandard %d filename=%s",fIsStandard,fFileName.Data()) << endl;
198   
199   if ( fExtensions ) 
200   {
201     cout << opt << fExtensions->GetEntries() << " extensions :" << endl;
202     PrintExtensions(*fExtensions);    
203   }
204   if ( fFilters ) 
205   {
206     cout << opt << fFilters->GetEntries() << " filters :" << endl;
207     PrintExtensions(*fFilters);      
208   }
209 }
210
211 //______________________________________________________________________________
212 void AliAODHandler::PrintExtensions(const TObjArray& array) const
213 {
214   // Show the list of aod extensions
215   TIter next(&array);
216   AliAODExtension* ext(0x0);
217   while ( ( ext = static_cast<AliAODExtension*>(next()) ) )
218   {
219     ext->Print("   ");
220   }
221 }
222
223 //______________________________________________________________________________
224 void AliAODHandler::StoreMCParticles(){
225
226   // 
227   // Remap the labels from ESD stack and store
228   // the AODMCParticles, makes only sense if we have
229   // the mcparticles branch
230   // has to be done here since we cannot know in advance 
231   // which particles are needed (e.g. by the tracks etc.)
232   //
233   // Particles have been selected by AliMCEventhanlder->SelectParticle()
234   // To use the MCEventhandler here we need to set it from the outside
235   // can vanish when Handler go to the ANALYSISalice library
236   //
237   // The Branch booking for mcParticles and mcHeader has to happen 
238   // in an external task for now since the AODHandler does not have access
239   // the AnalysisManager. For the same reason the pointer t o the MCEventH
240   // has to passed to the AOD Handler by this task 
241   // (doing this in the steering macro would not work on PROOF)
242
243   if (!fAODEvent) return;
244   TClonesArray *mcarray = (TClonesArray*)fAODEvent->FindListObject(AliAODMCParticle::StdBranchName()); 
245   if(!mcarray)return;
246
247   AliAODMCHeader *mcHeader = (AliAODMCHeader*)fAODEvent->FindListObject(AliAODMCHeader::StdBranchName()); 
248   if(!mcHeader)return;
249
250   // Get the MC Infos.. Handler needs to be set before 
251   // while adding the branch
252   // This needs to be done, not to depend on the AnalysisManager
253
254   if(!fMCEventH)return;
255   if(!fMCEventH->MCEvent())return;
256   AliStack *pStack = fMCEventH->MCEvent()->Stack();
257   if(!pStack)return;
258
259   fMCEventH->CreateLabelMap();
260
261   //
262   // Get the Event Header 
263   // 
264
265   AliHeader* header = fMCEventH->MCEvent()->Header();
266    // get the MC vertex
267   AliGenEventHeader* genHeader = 0;
268   if (header) genHeader = header->GenEventHeader();
269   if (genHeader) {
270       TArrayF vtxMC(3);
271       genHeader->PrimaryVertex(vtxMC);
272       mcHeader->SetVertex(vtxMC[0],vtxMC[1],vtxMC[2]);
273       // we search the MCEventHeaders first 
274       // Two cases, cocktail or not...
275       AliGenCocktailEventHeader* genCocktailHeader = dynamic_cast<AliGenCocktailEventHeader*>(genHeader);
276       if(genCocktailHeader){
277           // we have a coktail header add the name once
278           mcHeader->AddGeneratorName(genHeader->GetName());
279           TList* headerList = genCocktailHeader->GetHeaders();
280           // the first entry defines some extra general settings
281           AliGenEventHeader *headerEntry = dynamic_cast<AliGenEventHeader*>(headerList->At(0));
282           if (!headerEntry) {
283             AliFatal("AliGenEventHeader entry not found in the header list");
284           } else {   
285             SetMCHeaderInfo(mcHeader,headerEntry);
286           }  
287       }
288       else{
289         // No Cocktail just take the first one
290         SetMCHeaderInfo(mcHeader,genHeader);
291       }
292       // Add all the headers and names, if no cocktail header 
293       // there will be only one entry
294       mcHeader->AddCocktailHeaders(genHeader);
295   }
296   
297
298
299
300
301   // Store the AliAODParticlesMC
302   AliMCEvent* mcEvent = fMCEventH->MCEvent();
303   
304   Int_t np    = mcEvent->GetNumberOfTracks();
305   Int_t nprim = mcEvent->GetNumberOfPrimaries();
306
307
308   Int_t j = 0;
309   TClonesArray& l = *mcarray;
310
311   for(int i = 0; i < np; ++i){
312       if(fMCEventH->IsParticleSelected(i)){
313           Int_t flag = 0;
314           AliMCParticle* mcpart =  (AliMCParticle*) mcEvent->GetTrack(i);
315           if(i<nprim)flag |= AliAODMCParticle::kPrimary;
316           
317           if(mcEvent->IsPhysicalPrimary(i))flag |= AliAODMCParticle::kPhysicalPrim;
318           if(mcEvent->IsSecondaryFromWeakDecay(i))flag |= AliAODMCParticle::kSecondaryFromWeakDecay;
319           if(mcEvent->IsSecondaryFromMaterial(i))flag |= AliAODMCParticle::kSecondaryFromMaterial;
320
321           if(fMCEventH->GetNewLabel(i)!=j){
322               AliError(Form("MISMATCH New label %d j: %d",fMCEventH->GetNewLabel(i),j));
323           }
324
325           AliAODMCParticle mcpartTmp(mcpart,i,flag);
326           
327           mcpartTmp.SetStatus(mcpart->Particle()->GetStatusCode());
328           mcpartTmp.SetMCProcessCode(mcpart->Particle()->GetUniqueID());
329           // 
330           Int_t d0 =  mcpartTmp.GetDaughter(0);
331           Int_t d1 =  mcpartTmp.GetDaughter(1);
332           Int_t m =   mcpartTmp.GetMother();
333           
334           // other than for the track labels, negative values mean
335           // no daughter/mother so preserve it
336           
337           if(d0<0 && d1<0){
338               // no first daughter -> no second daughter
339               // nothing to be done
340               // second condition not needed just for sanity check at the end
341               mcpartTmp.SetDaughter(0,d0);
342               mcpartTmp.SetDaughter(1,d1);
343           } else if(d1 < 0 && d0 >= 0) {
344               // Only one daughter
345               // second condition not needed just for sanity check at the end
346               if(fMCEventH->IsParticleSelected(d0)){
347                   mcpartTmp.SetDaughter(0,fMCEventH->GetNewLabel(d0));
348               } else {
349                   mcpartTmp.SetDaughter(0,-1);
350               }
351               mcpartTmp.SetDaughter(1,d1);
352           }
353           else if (d0 > 0 && d1 > 0 ){
354               // we have two or more daughters loop on the stack to see if they are
355               // selected
356               Int_t d0Tmp = -1;
357               Int_t d1Tmp = -1;
358               for(int id = d0; id<=d1;++id){
359                   if(fMCEventH->IsParticleSelected(id)){
360                       if(d0Tmp==-1){
361                           // first time
362                           d0Tmp = fMCEventH->GetNewLabel(id);
363                           d1Tmp = d0Tmp; // this is to have the same schema as on the stack i.e. with one daugther d0 and d1 are the same 
364                       }
365                       else d1Tmp = fMCEventH->GetNewLabel(id);
366                   }
367               }
368               mcpartTmp.SetDaughter(0,d0Tmp);
369               mcpartTmp.SetDaughter(1,d1Tmp);
370           } else {
371               AliError(Form("Unxpected indices %d %d",d0,d1));
372           }
373           
374           if(m<0){
375               mcpartTmp.SetMother(m);
376           } else {
377               if(fMCEventH->IsParticleSelected(m))mcpartTmp.SetMother(fMCEventH->GetNewLabel(m));
378               else AliError(Form("PROBLEM Mother not selected %d \n", m));
379           }
380
381           new (l[j++]) AliAODMCParticle(mcpartTmp);
382           
383       }
384   }
385   AliInfo(Form("AliAODHandler::StoreMCParticles: Selected %d (Primaries %d / total %d) after validation \n",
386                j,nprim,np));
387   
388   // Set the labels in the AOD output...
389   // Remapping
390
391   // AODTracks
392   TClonesArray* tracks = fAODEvent->GetTracks();
393   Int_t tofLabel[3];
394   if(tracks){
395     for(int it = 0; it < fAODEvent->GetNumberOfTracks();++it){
396       AliAODTrack *track = fAODEvent->GetTrack(it);
397       
398       Int_t sign = 1;
399       Int_t label = track->GetLabel();
400       if(label<0){ // preserve the sign for later usage
401         label *= -1;
402         sign  = -1;
403       }
404       
405       if (label >= AliMCEvent::BgLabelOffset()) label =  mcEvent->BgLabelToIndex(label);
406       if(label > np || track->GetLabel() == 0){
407         AliWarning(Form("Wrong ESD track label %5d (%5d)",track->GetLabel(), label));
408       }
409       if(fMCEventH->GetNewLabel(label) == 0) {
410         AliWarning(Form("New label not found for %5d (%5d)",track->GetLabel(), label));
411       }
412       track->SetLabel(sign*fMCEventH->GetNewLabel(label));
413       
414       track->GetTOFLabel(tofLabel);
415       
416       for (Int_t i = 0; i < 3; i++) {
417         label  = tofLabel[i]; // esd label
418         Int_t nlabel = label; // new label
419         if (label < 0) continue;
420         if (label >= AliMCEvent::BgLabelOffset()) nlabel =  mcEvent->BgLabelToIndex(label);
421         if(nlabel > np || label == 0) {
422           AliWarning(Form("Wrong TOF label %5d (%5d)", label, nlabel));
423         }
424         if(fMCEventH->GetNewLabel(label) == 0){
425           AliWarning(Form("New TOF label not found for %5d %5d",i, label ));
426           tofLabel[i] = -label;  
427         } else {
428           tofLabel[i] = fMCEventH->GetNewLabel(label);
429         }
430       } 
431       track->SetTOFLabel(tofLabel);
432     }
433   }
434   
435   // AOD calo cluster
436   TClonesArray *clusters = fAODEvent->GetCaloClusters();
437   if(clusters){
438     for (Int_t iClust = 0;iClust < fAODEvent->GetNumberOfCaloClusters(); ++iClust) {
439       AliAODCaloCluster * cluster = fAODEvent->GetCaloCluster(iClust);
440       UInt_t nLabel    = cluster->GetNLabels();
441       // Ugly but do not want to fragment memory by creating 
442       // new Int_t (nLabel)
443       Int_t* labels    = const_cast<Int_t*>(cluster->GetLabels());
444       if (labels){
445         for(UInt_t i = 0;i < nLabel;++i){
446           labels[i] = fMCEventH->GetNewLabel(cluster->GetLabelAt(i));
447         }
448       }
449       //      cluster->SetLabels(labels,nLabel);
450     }// iClust
451   }// clusters
452   
453   // AOD calo cells MC label re-index
454   Int_t iCell, nCell, cellMCLabel, cellMCLabelNew;;
455   Short_t cellAbsId;
456   Double_t cellE, cellT, cellEFrac;
457   AliAODCaloCells *cells;
458   
459   // EMCal
460   cells = fAODEvent->GetEMCALCells();
461   if( cells ){
462     nCell = cells->GetNumberOfCells() ;
463     for( iCell = 0; iCell < nCell; iCell++ ){ 
464       cells->GetCell( iCell, cellAbsId, cellE, cellT, cellMCLabel, cellEFrac );
465       // GetNewLabel returns 1 in case when -1 is supplied
466       if( cellMCLabel < 0 )
467         cellMCLabelNew = cellMCLabel;
468       else
469         cellMCLabelNew = fMCEventH->GetNewLabel( cellMCLabel );
470         
471       cells->SetCell( iCell, cellAbsId, cellE, cellT, cellMCLabelNew, cellEFrac );
472     }
473   }
474   // PHOS
475   cells = fAODEvent->GetPHOSCells();
476   if( cells ){
477     nCell = cells->GetNumberOfCells() ;
478     for( iCell = 0; iCell < nCell; iCell++ ){ 
479       cells->GetCell( iCell, cellAbsId, cellE, cellT, cellMCLabel, cellEFrac );
480       // GetNewLabel returns 1 in case when -1 is supplied
481       if( cellMCLabel < 0 )
482         cellMCLabelNew = cellMCLabel;
483       else
484         cellMCLabelNew = fMCEventH->GetNewLabel( cellMCLabel );
485         
486       cells->SetCell( iCell, cellAbsId, cellE, cellT, cellMCLabelNew, cellEFrac );
487     }
488   }
489
490   // AOD tracklets
491   AliAODTracklets *tracklets = fAODEvent->GetTracklets();
492   if(tracklets){
493     for(int it = 0;it < tracklets->GetNumberOfTracklets();++it){
494       int label0 = tracklets->GetLabel(it,0);
495       int label1 = tracklets->GetLabel(it,1);
496       if(label0>=0)label0 = fMCEventH->GetNewLabel(label0);      
497       if(label1>=0)label1 = fMCEventH->GetNewLabel(label1);
498       tracklets->SetLabel(it,0,label0);
499       tracklets->SetLabel(it,1,label1);
500     }
501   }
502
503 }
504
505 //______________________________________________________________________________
506 Bool_t AliAODHandler::FinishEvent()
507 {
508   // Fill data structures
509   if(fFillAOD && fFillAODRun && fAODEvent){
510       fAODEvent->MakeEntriesReferencable();
511       fTreeA->BranchRef();
512       FillTree();
513   }
514
515   if ((fFillAOD && fFillAODRun) || fFillExtension) {
516     if (fExtensions && fFillExtension) {
517       // fFillExtension can be set by the ESD filter or by a delta filter in case of AOD inputs
518       TIter next(fExtensions);
519       AliAODExtension *ext;
520       while ((ext=(AliAODExtension*)next())) ext->FinishEvent();
521     }
522     if (fFilters && fFillAOD && fFillAODRun) {
523       TIter nextf(fFilters);
524       AliAODExtension *ext;
525       while ((ext=(AliAODExtension*)nextf())) {
526               ext->FinishEvent();
527       }  
528     }       
529   }  
530   
531   if (fIsStandard && fAODEvent) 
532   {
533     fAODEvent->ResetStd();    
534   }
535   
536   if (fAODEvent) 
537   {
538     TClonesArray *mcarray = static_cast<TClonesArray*>(fAODEvent->FindListObject(AliAODMCParticle::StdBranchName()));
539     if(mcarray) mcarray->Delete();
540     
541     AliAODMCHeader *mcHeader = static_cast<AliAODMCHeader*>(fAODEvent->FindListObject(AliAODMCHeader::StdBranchName()));
542     if(mcHeader) mcHeader->Reset();
543   }
544   
545   // Reset AOD replication flag
546   fAODIsReplicated = kFALSE;
547   return kTRUE;
548 }
549
550 //______________________________________________________________________________
551 Bool_t AliAODHandler::Terminate()
552 {
553   // Terminate 
554   AddAODtoTreeUserInfo();
555   
556   TIter nextF(fFilters);
557   AliAODExtension *ext;
558   while ((ext=static_cast<AliAODExtension*>(nextF())))
559   {
560     ext->AddAODtoTreeUserInfo();
561   }
562
563   TIter nextE(fExtensions);
564   while ((ext=static_cast<AliAODExtension*>(nextE())))
565   {
566     ext->AddAODtoTreeUserInfo();
567   }
568   
569   return kTRUE;
570 }
571
572 //______________________________________________________________________________
573 Bool_t AliAODHandler::TerminateIO()
574 {
575   // Terminate IO
576   if (fFileA) {
577     fFileA->Write();
578     fFileA->Close();
579     delete fFileA;
580     fFileA = 0;
581     // When closing the file, the tree is also deleted.
582     fTreeA = 0;
583   }
584   
585   TIter nextF(fFilters);
586   AliAODExtension *ext;
587   while ((ext=static_cast<AliAODExtension*>(nextF())))
588   {
589     ext->TerminateIO();
590   }  
591
592   TIter nextE(fExtensions);
593   while ((ext=static_cast<AliAODExtension*>(nextE())))
594   {
595     ext->TerminateIO();
596   }  
597   
598   return kTRUE;
599 }
600
601 //______________________________________________________________________________
602 void AliAODHandler::CreateTree(Int_t flag)
603 {
604     // Creates the AOD Tree
605     fTreeA = new TTree("aodTree", "AliAOD tree");
606     fTreeA->Branch(fAODEvent->GetList());
607     if (flag == 0) fTreeA->SetDirectory(0);
608     fMemCountAOD = 0;
609 }
610
611 //______________________________________________________________________________
612 void AliAODHandler::FillTree()
613 {
614  
615     // Fill the AOD Tree
616    Long64_t nbf = fTreeA->Fill();
617    if (fTreeBuffSize>0 && fTreeA->GetAutoFlush()<0 && (fMemCountAOD += nbf)>fTreeBuffSize ) { // default limit is still not reached
618     nbf = fTreeA->GetZipBytes();
619     if (nbf>0) nbf = -nbf;
620     else       nbf = fTreeA->GetEntries();
621     fTreeA->SetAutoFlush(nbf);
622     AliInfo(Form("Calling fTreeA->SetAutoFlush(%lld) | W:%lld T:%lld Z:%lld",
623                  nbf,fMemCountAOD,fTreeA->GetTotBytes(),fTreeA->GetZipBytes()));        
624   }
625  
626 }
627
628 //______________________________________________________________________________
629 void AliAODHandler::AddAODtoTreeUserInfo()
630 {
631   // Add aod event to tree user info
632   if (fTreeA) fTreeA->GetUserInfo()->Add(fAODEvent);
633   // Now the tree owns our fAODEvent...
634   fAODEvent = 0;
635 }
636
637 //______________________________________________________________________________
638 void AliAODHandler::AddBranch(const char* cname, void* addobj, const char* filename)
639 {
640   // Add a new branch to the aod. Added optional filename parameter if the
641   // branch should be written to a separate file.
642   
643   if (strlen(filename)) 
644   {
645     AliAODExtension *ext = AddExtension(filename);
646     ext->AddBranch(cname, addobj);
647     return;
648   } 
649   
650   // Add branch to all filters
651   // Add branch to all filters
652   if (fFilters) {
653     TIter next(fFilters);
654     AliAODExtension *ext;
655     while ((ext=(AliAODExtension*)next())) ext->AddBranch(cname, addobj);
656   }
657   
658   TDirectory *owd = gDirectory;
659   if (fFileA) 
660   {
661     fFileA->cd();
662   }
663
664   char** apointer = (char**) addobj;
665   TObject* obj = (TObject*) *apointer;
666   
667   fAODEvent->AddObject(obj);
668   
669   const Int_t kSplitlevel = 99; // default value in TTree::Branch()
670   const Int_t kBufsize = 32000; // default value in TTree::Branch()
671   
672   if (!fTreeA->FindBranch(obj->GetName())) 
673   {
674     // Do the same as if we book via 
675     // TTree::Branch(TCollection*)
676     
677     fTreeA->Bronch(obj->GetName(), cname, fAODEvent->GetList()->GetObjectRef(obj),
678                    kBufsize, kSplitlevel - 1);
679   }
680   owd->cd();
681 }
682
683 //______________________________________________________________________________
684 AliAODExtension *AliAODHandler::AddExtension(const char *filename, const char *title, Bool_t tomerge)
685 {
686   // Add an AOD extension with some branches in a different file.
687   
688   TString fname(filename);
689   if (!fname.EndsWith(".root")) fname += ".root";
690   if (!fExtensions) {
691     fExtensions = new TObjArray();
692     fExtensions->SetOwner();
693   }   
694   AliAODExtension *ext = (AliAODExtension*)fExtensions->FindObject(fname);
695   if (!ext) {
696     ext = new AliAODExtension(fname, title);
697     fExtensions->Add(ext);
698   }   
699   ext->SetToMerge(tomerge);
700   return ext;
701 }
702
703 //______________________________________________________________________________
704 AliAODExtension *AliAODHandler::GetExtension(const char *filename) const
705 {
706   // Getter for AOD extensions via file name.
707   if (!fExtensions) return NULL;
708   return (AliAODExtension*)fExtensions->FindObject(filename);
709 }   
710
711 //______________________________________________________________________________
712 AliAODExtension *AliAODHandler::AddFilteredAOD(const char *filename, const char *filtername, Bool_t tomerge)
713 {
714   // Add an AOD extension that can write only AOD events that pass a user filter.
715   if (!fFilters) {
716     fFilters = new TObjArray();
717     fFilters->SetOwner();
718   } 
719   AliAODExtension *filter = (AliAODExtension*)fFilters->FindObject(filename);
720   if (!filter) {
721     filter = new AliAODExtension(filename, filtername, kTRUE);
722     fFilters->Add(filter);
723   }
724   filter->SetToMerge(tomerge);
725   return filter;
726 }      
727
728 //______________________________________________________________________________
729 AliAODExtension *AliAODHandler::GetFilteredAOD(const char *filename) const
730 {
731   // Getter for AOD filters via file name.
732   if (!fFilters) return NULL;
733   return (AliAODExtension*)fFilters->FindObject(filename);
734 }   
735
736 //______________________________________________________________________________
737 void AliAODHandler::SetOutputFileName(const char* fname)
738 {
739 // Set file name.
740    fFileName = fname;
741 }
742
743 //______________________________________________________________________________
744 const char *AliAODHandler::GetOutputFileName() const
745 {
746 // Get file name.
747    return fFileName.Data();
748 }
749
750 //______________________________________________________________________________
751 const char *AliAODHandler::GetExtraOutputs(Bool_t merge) const
752 {
753   // Get extra outputs as a string separated by commas.
754   static TString eoutputs;
755   eoutputs = "";
756   AliAODExtension *obj;
757   if (fExtensions) {
758     TIter next1(fExtensions);
759     while ((obj=(AliAODExtension*)next1())) {
760       if (merge && !obj->IsToMerge()) continue;
761       if (!eoutputs.IsNull()) eoutputs += ",";
762       eoutputs += obj->GetName();
763     }
764   }
765   if (fFilters) {
766     TIter next2(fFilters);
767     while ((obj=(AliAODExtension*)next2())) {
768       if (merge && !obj->IsToMerge()) continue;
769       if (!eoutputs.IsNull()) eoutputs += ",";
770       eoutputs += obj->GetName();
771     }
772   }
773   return eoutputs.Data();
774 }
775
776 //______________________________________________________________________________
777 Bool_t AliAODHandler::HasExtensions() const
778 {
779   // Whether or not we manage extensions
780   
781   if ( fExtensions && fExtensions->GetEntries()>0 ) return kTRUE;
782   
783   return kFALSE;
784 }
785
786 //______________________________________________________________________________
787 void  AliAODHandler::SetMCHeaderInfo(AliAODMCHeader *mcHeader,AliGenEventHeader *genHeader){
788
789
790   // Utility function to cover different cases for the AliGenEventHeader
791   // Needed since different ProcessType and ImpactParamter are not 
792   // in the base class...
793
794   if(!genHeader)return;
795   AliGenPythiaEventHeader *pythiaGenHeader = dynamic_cast<AliGenPythiaEventHeader*>(genHeader);
796   if (pythiaGenHeader) {
797     mcHeader->SetEventType(pythiaGenHeader->ProcessType());
798     mcHeader->SetPtHard(pythiaGenHeader->GetPtHard());
799     return;
800   }
801   
802   AliGenDPMjetEventHeader* dpmJetGenHeader = dynamic_cast<AliGenDPMjetEventHeader*>(genHeader);
803   
804   if (dpmJetGenHeader){
805     mcHeader->SetEventType(dpmJetGenHeader->ProcessType());
806     return;
807   } 
808
809   AliGenHijingEventHeader* hijingGenHeader = dynamic_cast<AliGenHijingEventHeader*>(genHeader);
810   if(hijingGenHeader){
811     mcHeader->SetImpactParameter(hijingGenHeader->ImpactParameter());
812     return;
813   }
814   
815   //  AliWarning(Form("MC Eventheader not known: %s",genHeader->GetName()));
816   
817 }
818