]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliAODHandler.cxx
Added support for creating both standard AOD and several deltaAOD's in the same
[u/mrichter/AliRoot.git] / STEER / AliAODHandler.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 //-------------------------------------------------------------------------
19 //     Implementation of the Virtual Event Handler Interface for AOD
20 //     Author: Andreas Morsch, CERN
21 //-------------------------------------------------------------------------
22
23
24 #include <TTree.h>
25 #include <TFile.h>
26 #include <TRef.h>
27 #include <TString.h>
28 #include <TList.h>
29
30 #include "AliLog.h"
31 #include "AliAODHandler.h"
32 #include "AliAODEvent.h"
33 #include "AliAODTracklets.h"
34 #include "AliStack.h"
35 #include "AliAODMCParticle.h"
36 #include "AliAODMCHeader.h"
37 #include "AliMCEventHandler.h"
38 #include "AliMCEvent.h"
39 #include "AliGenEventHeader.h"
40 #include "AliGenHijingEventHeader.h"
41 #include "AliGenDPMjetEventHeader.h"
42 #include "AliGenPythiaEventHeader.h"
43 #include "AliGenCocktailEventHeader.h"
44
45
46
47 ClassImp(AliAODHandler)
48
49 //______________________________________________________________________________
50 AliAODHandler::AliAODHandler() :
51     AliVEventHandler(),
52     fIsStandard(kTRUE),
53     fFillAOD(kTRUE),
54     fNeedsHeaderReplication(kFALSE),
55     fNeedsTracksBranchReplication(kFALSE),
56     fNeedsVerticesBranchReplication(kFALSE),
57     fNeedsV0sBranchReplication(kFALSE),
58     fNeedsTrackletsBranchReplication(kFALSE),
59     fNeedsPMDClustersBranchReplication(kFALSE),
60     fNeedsJetsBranchReplication(kFALSE),
61     fNeedsFMDClustersBranchReplication(kFALSE),
62     fNeedsCaloClustersBranchReplication(kFALSE),
63     fAODIsReplicated(kFALSE),
64     fAODEvent(NULL),
65     fMCEventH(NULL),
66     fTreeA(NULL),
67     fFileA(NULL),
68     fFileName(""),
69     fExtensions(NULL)
70 {
71   // default constructor
72 }
73
74 //______________________________________________________________________________
75 AliAODHandler::AliAODHandler(const char* name, const char* title):
76     AliVEventHandler(name, title),
77     fIsStandard(kTRUE),
78     fFillAOD(kTRUE),
79     fNeedsHeaderReplication(kFALSE),
80     fNeedsTracksBranchReplication(kFALSE),
81     fNeedsVerticesBranchReplication(kFALSE),
82     fNeedsV0sBranchReplication(kFALSE),
83     fNeedsTrackletsBranchReplication(kFALSE),
84     fNeedsPMDClustersBranchReplication(kFALSE),
85     fNeedsJetsBranchReplication(kFALSE),
86     fNeedsFMDClustersBranchReplication(kFALSE),
87     fNeedsCaloClustersBranchReplication(kFALSE),
88     fAODIsReplicated(kFALSE),
89     fAODEvent(NULL),
90     fMCEventH(NULL),
91     fTreeA(NULL),
92     fFileA(NULL),
93     fFileName(""),
94     fExtensions(NULL)
95 {
96 }
97
98 //______________________________________________________________________________
99 AliAODHandler::~AliAODHandler() 
100 {
101  // Destructor.
102   delete fAODEvent;
103   if(fFileA){
104     // is already handled in TerminateIO
105     fFileA->Close();
106     delete fFileA;
107   }
108   delete fTreeA;
109   if (fExtensions) delete fExtensions;
110 }
111
112 //______________________________________________________________________________
113 Bool_t AliAODHandler::Init(Option_t* opt)
114 {
115   // Initialize IO
116   //
117   // Create the AODevent object
118   if(!fAODEvent){
119     fAODEvent = new AliAODEvent();
120     if (fIsStandard) fAODEvent->CreateStdContent();
121   }
122   //
123   // File opening according to execution mode
124   TString option(opt);
125   option.ToLower();
126   if (option.Contains("proof")) {
127     // proof
128     if (option.Contains("special")) {
129        // File for tree already opened on slave -> merging via files
130        fFileA = gFile;
131        CreateTree(1);
132     } else {   
133        // Merging in memory (not needed anymore)
134        CreateTree(1);
135     }   
136   } else {
137     // local and grid
138     TDirectory *owd = gDirectory;
139     fFileA = new TFile(fFileName.Data(), "RECREATE");
140     CreateTree(1);
141     owd->cd();
142   }
143   if (fExtensions) {
144      TIter next(fExtensions);
145      AliAODExtension *ext;
146      while ((ext=(AliAODExtension*)next())) ext->Init(option);
147   }   
148   return kTRUE;
149 }
150
151 //______________________________________________________________________________
152 void AliAODHandler::StoreMCParticles(){
153
154   // 
155   // Remap the labels from ESD stack and store
156   // the AODMCParticles, makes only sense if we have
157   // the mcparticles branch
158   // has to be done here since we cannot know in advance 
159   // which particles are needed (e.g. by the tracks etc.)
160   //
161   // Particles have been selected by AliMCEventhanlder->SelectParticle()
162   // To use the MCEventhandler here we need to set it from the outside
163   // can vanish when Handler go to the ANALYSISalice library
164   //
165   // The Branch booking for mcParticles and mcHeader has to happen 
166   // in an external task for now since the AODHandler does not have access
167   // the AnalysisManager. For the same reason the pointer t o the MCEventH
168   // has to passed to the AOD Handler by this task 
169   // (doing this in the steering macro would not work on PROOF)
170
171   TClonesArray *mcarray = (TClonesArray*)fAODEvent->FindListObject(AliAODMCParticle::StdBranchName()); 
172   if(!mcarray)return;
173   mcarray->Delete();
174
175   AliAODMCHeader *mcHeader = (AliAODMCHeader*)fAODEvent->FindListObject(AliAODMCHeader::StdBranchName()); 
176   if(!mcHeader)return;
177
178   mcHeader->Reset();
179
180   // Get the MC Infos.. Handler needs to be set before 
181   // while adding the branch
182   // This needs to be done, not to depend on the AnalysisManager
183
184   if(!fMCEventH)return;
185   if(!fMCEventH->MCEvent())return;
186   AliStack *pStack = fMCEventH->MCEvent()->Stack();
187   if(!pStack)return;
188
189   fMCEventH->CreateLabelMap();
190
191   //
192   // Get the Event Header 
193   // 
194
195   AliHeader* header = fMCEventH->MCEvent()->Header();
196   if (!header)return;
197
198   // get the MC vertex
199   AliGenEventHeader* genHeader = header->GenEventHeader();
200   TArrayF vtxMC(3);
201   genHeader->PrimaryVertex(vtxMC);
202   mcHeader->SetVertex(vtxMC[0],vtxMC[1],vtxMC[2]);
203
204   // we search the MCEventHeaders first 
205   // Two cases, cocktail or not...
206   AliGenCocktailEventHeader* genCocktailHeader = dynamic_cast<AliGenCocktailEventHeader*>(genHeader);
207   if(genCocktailHeader){
208     // we have a coktail header
209     mcHeader->AddGeneratorName(genHeader->GetName());
210     // Loop from the back so that the first one sets the process type
211     TList* headerList = genCocktailHeader->GetHeaders();
212     for(int i = headerList->GetEntries()-1;i>=0;--i){
213       AliGenEventHeader *headerEntry = dynamic_cast<AliGenEventHeader*>(headerList->At(i));
214       SetMCHeaderInfo(mcHeader,headerEntry);
215     }
216   }
217   else{
218     // No Cocktail just take the first one
219     SetMCHeaderInfo(mcHeader,genHeader);
220   }
221
222
223
224
225   // Store the AliAODParticlesMC
226
227   Int_t np    = pStack->GetNtrack();
228   Int_t nprim = pStack->GetNprimary();
229
230
231   Int_t j = 0;
232   TClonesArray& l = *mcarray;
233
234   for(int i = 0;i < np;++i){
235     if(fMCEventH->IsParticleSelected(i)){
236
237       Int_t flag = 0;
238       TParticle *part = pStack->Particle(i);
239       if(i<nprim)flag |= AliAODMCParticle::kPrimary;
240       if(pStack->IsPhysicalPrimary(i))flag |= AliAODMCParticle::kPhysicalPrim;
241
242       if(fMCEventH->GetNewLabel(i)!=j){
243         AliError(Form("MISMATCH New label %d j: %d",fMCEventH->GetNewLabel(i),j));
244       }
245       AliAODMCParticle mcpart_tmp(part,i,flag);
246
247       // 
248       Int_t d0 =  mcpart_tmp.GetDaughter(0);
249       Int_t d1 =  mcpart_tmp.GetDaughter(1);
250       Int_t m =  mcpart_tmp.GetMother();
251
252       // other than for the track labels, negative values mean
253       // no daughter/mother so preserve it
254  
255       if(d0<0 && d1<0){
256         // no first daughter -> no second daughter
257         // nothing to be done
258         // second condition not needed just for sanity check at the end
259         mcpart_tmp.SetDaughter(0,d0);
260         mcpart_tmp.SetDaughter(1,d1);
261       }
262       else if(d1 < 0 && d0 >= 0){
263         // Only one daughter
264         // second condition not needed just for sanity check at the end
265         if(fMCEventH->IsParticleSelected(d0)){
266           mcpart_tmp.SetDaughter(0,fMCEventH->GetNewLabel(d0));
267         }
268         else{
269           mcpart_tmp.SetDaughter(0,-1);
270         }
271         mcpart_tmp.SetDaughter(1,d1);
272       }
273       else if (d0 > 0 && d1 > 0 ){
274         // we have two or more daughters loop on the stack to see if they are
275         // selected
276         Int_t d0_tmp = -1;
277         Int_t d1_tmp = -1;
278         for(int id = d0; id<=d1;++id){
279           if(fMCEventH->IsParticleSelected(id)){
280             if(d0_tmp==-1){
281               // first time
282               d0_tmp = fMCEventH->GetNewLabel(id);
283               d1_tmp = d0_tmp; // this is to have the same schema as on the stack i.e. with one daugther d0 and d1 are the same 
284             }
285             else d1_tmp = fMCEventH->GetNewLabel(id);
286           }
287         }
288         mcpart_tmp.SetDaughter(0,d0_tmp);
289         mcpart_tmp.SetDaughter(1,d1_tmp);
290       }
291       else{
292         AliError(Form("Unxpected indices %d %d",d0,d1));
293       }
294
295       if(m<0){
296         mcpart_tmp.SetMother(m);
297       }
298       else{
299         if(fMCEventH->IsParticleSelected(m))mcpart_tmp.SetMother(fMCEventH->GetNewLabel(m));
300         else AliError("PROBLEM Mother not selected");
301       }
302
303       new (l[j++]) AliAODMCParticle(mcpart_tmp);
304       
305     }
306   }
307   AliInfo(Form("AliAODHandler::StoreMCParticles: Selected %d (Primaries %d / total %d) after validation",
308                j,nprim,np));
309   
310   // Set the labels in the AOD output...
311   // Remapping
312
313   // AODTracks
314   TClonesArray* tracks = fAODEvent->GetTracks();
315   if(tracks){
316     for(int it = 0; it < fAODEvent->GetNTracks();++it){
317       AliAODTrack *track = fAODEvent->GetTrack(it);
318       
319       if(TMath::Abs(track->GetLabel())>np||track->GetLabel()==0){
320         AliWarning(Form("Wrong ESD track label %d",track->GetLabel()));
321       }
322       if(fMCEventH->GetNewLabel(track->GetLabel())==0){
323         AliWarning(Form("New label not found for %d",track->GetLabel()));
324       }
325       track->SetLabel(fMCEventH->GetNewLabel(track->GetLabel()));
326     }
327   }
328   
329   // AOD calo cluster
330   TClonesArray *clusters = fAODEvent->GetCaloClusters();
331   if(clusters){
332     for (Int_t iClust = 0;iClust < fAODEvent->GetNCaloClusters(); ++iClust) {
333       AliAODCaloCluster * cluster = fAODEvent->GetCaloCluster(iClust);
334       UInt_t nLabel    = cluster->GetNLabel();
335       // Ugly but do not want to fragment memory by creating 
336       // new Int_t (nLabel)
337       Int_t* labels    = const_cast<Int_t*>(cluster->GetLabels());
338       if (labels){
339         for(UInt_t i = 0;i < nLabel;++i){
340           labels[i] = fMCEventH->GetNewLabel(cluster->GetLabel(i));
341         }
342       }
343       //      cluster->SetLabels(labels,nLabel);
344     }// iClust
345   }// clusters
346
347   // AOD tracklets
348   AliAODTracklets *tracklets = fAODEvent->GetTracklets();
349   if(tracklets){
350     for(int it = 0;it < tracklets->GetNumberOfTracklets();++it){
351       int label0 = tracklets->GetLabel(it,0);
352       int label1 = tracklets->GetLabel(it,1);
353       if(label0>=0)label0 = fMCEventH->GetNewLabel(label0);      
354       if(label1>=0)label1 = fMCEventH->GetNewLabel(label1);
355       tracklets->SetLabel(it,0,label0);
356       tracklets->SetLabel(it,1,label1);
357     }
358   }
359
360 }
361
362 //______________________________________________________________________________
363 Bool_t AliAODHandler::FinishEvent()
364 {
365   // Fill data structures
366   if(fFillAOD){
367     fAODEvent->MakeEntriesReferencable();
368     StoreMCParticles();
369     FillTree();
370     if (fExtensions) {
371       TIter next(fExtensions);
372       AliAODExtension *ext;
373       while ((ext=(AliAODExtension*)next())) {
374         ext->GetAOD()->MakeEntriesReferencable();
375         ext->GetTree()->Fill();
376       }  
377     }       
378   }
379
380   if (fIsStandard) fAODEvent->ResetStd();
381   // Reset AOD replication flag
382   fAODIsReplicated = kFALSE;
383   return kTRUE;
384 }
385
386 //______________________________________________________________________________
387 Bool_t AliAODHandler::Terminate()
388 {
389   // Terminate 
390   AddAODtoTreeUserInfo();
391   if (fExtensions) {
392     TIter next(fExtensions);
393     AliAODExtension *ext;
394     while ((ext=(AliAODExtension*)next())) ext->GetTree()->GetUserInfo()->Add(ext->GetAOD());
395   }  
396   return kTRUE;
397 }
398
399 //______________________________________________________________________________
400 Bool_t AliAODHandler::TerminateIO()
401 {
402   // Terminate IO
403   if (fFileA) {
404     fFileA->Close();
405     delete fFileA;
406     fFileA = 0;
407   }
408   if (fExtensions) {
409     TIter next(fExtensions);
410     AliAODExtension *ext;
411     while ((ext=(AliAODExtension*)next())) ext->TerminateIO();
412   }  
413   return kTRUE;
414 }
415
416 //______________________________________________________________________________
417 void AliAODHandler::CreateTree(Int_t flag)
418 {
419     // Creates the AOD Tree
420     fTreeA = new TTree("aodTree", "AliAOD tree");
421     fTreeA->Branch(fAODEvent->GetList());
422     TRef junk = (TObject*)fTreeA->BranchRef();
423     if (flag == 0) fTreeA->SetDirectory(0);
424 }
425
426 //______________________________________________________________________________
427 void AliAODHandler::FillTree()
428 {
429     // Fill the AOD Tree
430   fTreeA->Fill();
431 }
432
433 //______________________________________________________________________________
434 void AliAODHandler::AddAODtoTreeUserInfo()
435 {
436   // Add aod event to tree user info
437   fTreeA->GetUserInfo()->Add(fAODEvent);
438 }
439
440 //______________________________________________________________________________
441 void AliAODHandler::AddBranch(const char* cname, void* addobj, const char* filename)
442 {
443     // Add a new branch to the aod. Added optional filename parameter if the
444     // branch should be written to a separate file.
445     if (strlen(filename)) {
446        AliAODExtension *ext = AddExtension(filename);
447        ext->AddBranch(cname, addobj);
448        return;
449     }
450     TDirectory *owd = gDirectory;
451     if (fFileA) {
452       fFileA->cd();
453     }
454     char** apointer = (char**) addobj;
455     TObject* obj = (TObject*) *apointer;
456
457     fAODEvent->AddObject(obj);
458  
459     const Int_t kSplitlevel = 99; // default value in TTree::Branch()
460     const Int_t kBufsize = 32000; // default value in TTree::Branch()
461
462     if (!fTreeA->FindBranch(obj->GetName())) {
463       // Do the same as if we book via 
464       // TTree::Branch(TCollection*)
465       
466       fTreeA->Bronch(obj->GetName(), cname, fAODEvent->GetList()->GetObjectRef(obj),
467                      kBufsize, kSplitlevel - 1);
468       //    fTreeA->Branch(obj->GetName(), cname, addobj);
469     }
470     owd->cd();
471 }
472
473 //______________________________________________________________________________
474 AliAODExtension *AliAODHandler::AddExtension(const char *filename, const char *title)
475 {
476 // Add an AOD extension with some branches in a different file.
477    TString fname(filename);
478    if (!fname.EndsWith(".root")) fname += ".root";
479    if (!fExtensions) {
480       fExtensions = new TObjArray();
481       fExtensions->SetOwner();
482    }   
483    AliAODExtension *ext = (AliAODExtension*)fExtensions->FindObject(fname);
484    if (!ext) {
485       ext = new AliAODExtension(fname, title);
486       fExtensions->Add(ext);
487    }   
488    return ext;
489 }
490    
491 //______________________________________________________________________________
492 void AliAODHandler::SetOutputFileName(const char* fname)
493 {
494 // Set file name.
495    fFileName = fname;
496 }
497
498 //______________________________________________________________________________
499 const char *AliAODHandler::GetOutputFileName()
500 {
501 // Get file name.
502    return fFileName.Data();
503 }
504
505 //______________________________________________________________________________
506 void  AliAODHandler::SetMCHeaderInfo(AliAODMCHeader *mcHeader,AliGenEventHeader *genHeader){
507
508
509   // Utility function to cover different cases for the AliGenEventHeader
510   // Needed since different ProcessType and ImpactParamter are not 
511   // in the base class...
512   // We don't encode process types for event cocktails yet
513   // could be done e.g. by adding offsets depnding on the generator
514
515   mcHeader->AddGeneratorName(genHeader->GetName());
516   if(!genHeader)return;
517   AliGenPythiaEventHeader *pythiaGenHeader = dynamic_cast<AliGenPythiaEventHeader*>(genHeader);
518     if (pythiaGenHeader) {
519       mcHeader->SetEventType(pythiaGenHeader->ProcessType());
520       return;
521     }
522     
523     AliGenDPMjetEventHeader* dpmJetGenHeader = dynamic_cast<AliGenDPMjetEventHeader*>(genHeader);
524
525   if (dpmJetGenHeader){
526     mcHeader->SetEventType(dpmJetGenHeader->ProcessType());
527     return;
528   } 
529
530   AliGenHijingEventHeader* hijingGenHeader = dynamic_cast<AliGenHijingEventHeader*>(genHeader);
531   if(hijingGenHeader){
532     mcHeader->SetImpactParameter(hijingGenHeader->ImpactParameter());
533     return;
534   }
535   
536   AliWarning(Form("MC Eventheader not known: %s",genHeader->GetName()));
537
538 }
539
540 ClassImp(AliAODExtension)
541
542 //-------------------------------------------------------------------------
543 //     Support class for AOD extensions. This is created by the user analysis
544 //     that requires a separate file for some AOD branches. The name of the 
545 //     AliAODExtension object is the file name where the AOD branches will be
546 //     stored.
547 //-------------------------------------------------------------------------
548
549 //______________________________________________________________________________
550 AliAODExtension::~AliAODExtension()
551 {
552 // Destructor.
553   delete fAODEvent;
554   if(fFileE){
555     // is already handled in TerminateIO
556     fFileE->Close();
557     delete fFileE;
558   }
559   delete fTreeE;
560 }
561
562 //______________________________________________________________________________
563 void AliAODExtension::AddBranch(const char* cname, void* addobj)
564 {
565     // Add a new branch to the aod 
566     if (!fAODEvent) Init("");
567     TDirectory *owd = gDirectory;
568     if (fFileE) {
569       fFileE->cd();
570     }
571     char** apointer = (char**) addobj;
572     TObject* obj = (TObject*) *apointer;
573
574     fAODEvent->AddObject(obj);
575  
576     const Int_t kSplitlevel = 99; // default value in TTree::Branch()
577     const Int_t kBufsize = 32000; // default value in TTree::Branch()
578
579     if (!fTreeE->FindBranch(obj->GetName())) {
580       // Do the same as if we book via 
581       // TTree::Branch(TCollection*)
582       
583       fTreeE->Bronch(obj->GetName(), cname, fAODEvent->GetList()->GetObjectRef(obj),
584                      kBufsize, kSplitlevel - 1);
585       //    fTreeA->Branch(obj->GetName(), cname, addobj);
586     }
587     owd->cd();
588 }
589
590 //______________________________________________________________________________
591 Bool_t AliAODExtension::Init(Option_t */*option*/)
592 {
593 // Initialize IO.
594   if(!fAODEvent) fAODEvent = new AliAODEvent();
595   TDirectory *owd = gDirectory;
596   fFileE = new TFile(GetName(), "RECREATE");
597   fTreeE = new TTree("aodTree", "AliAOD tree");
598   fTreeE->Branch(fAODEvent->GetList());
599   TRef junk = (TObject*)fTreeE->BranchRef();
600   owd->cd();
601   return kTRUE;
602 }
603
604 //______________________________________________________________________________
605 Bool_t AliAODExtension::TerminateIO()
606 {
607   // Terminate IO
608   if (fFileE) {
609     fFileE->Write();
610     fFileE->Close();
611     delete fFileE;
612     fFileE = 0;
613   }
614   return kTRUE;
615 }