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