AliAODEvent: corrected copy constructor and assignment operator. This do not work...
[u/mrichter/AliRoot.git] / STEER / AliAODEvent.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 //     AOD base class
20 //     Author: Markus Oldenburg, CERN
21 //-------------------------------------------------------------------------
22
23 #include <TROOT.h>
24 #include <TTree.h>
25 #include <TFolder.h>
26 #include <TFriendElement.h>
27 #include <TProcessID.h>
28 #include <TCollection.h>
29 #include "Riostream.h"
30 #include "AliAODEvent.h"
31 #include "AliAODHeader.h"
32 #include "AliAODTrack.h"
33
34 ClassImp(AliAODEvent)
35
36 // definition of std AOD member names
37   const char* AliAODEvent::fAODListName[kAODListN] = {"header",
38                                                       "tracks",
39                                                       "vertices",
40                                                       "v0s",
41                                                       "cascades",
42                                                       "tracklets",
43                                                       "jets",
44                                                       "emcalCells",
45                                                       "phosCells",
46                                                       "caloClusters",
47                                                       "fmdClusters",
48                                                       "pmdClusters"
49                                                       
50 };
51 //______________________________________________________________________________
52 AliAODEvent::AliAODEvent() :
53   AliVEvent(),
54   fAODObjects(new TList()),
55   fAODFolder(0),
56   fConnected(kFALSE),
57   fHeader(0),
58   fTracks(0),
59   fVertices(0),
60   fV0s(0),
61   fCascades(0),
62   fTracklets(0),
63   fJets(0),
64   fEmcalCells(0),
65   fPhosCells(0),
66   fCaloClusters(0),
67   fFmdClusters(0),
68   fPmdClusters(0)
69 {
70   // default constructor
71 }
72
73 //______________________________________________________________________________
74 AliAODEvent::AliAODEvent(const AliAODEvent& aod):
75   AliVEvent(aod),
76   fAODObjects(new TList()),
77   fAODFolder(new TFolder()),
78   fConnected(kFALSE),
79   fHeader(new AliAODHeader(*aod.fHeader)),
80   fTracks(new TClonesArray(*aod.fTracks)),
81   fVertices(new TClonesArray(*aod.fVertices)),
82   fV0s(new TClonesArray(*aod.fV0s)),
83   fCascades(new TClonesArray(*aod.fCascades)),
84   fTracklets(new AliAODTracklets(*aod.fTracklets)),
85   fJets(new TClonesArray(*aod.fJets)),
86   fEmcalCells(new AliAODCaloCells(*aod.fEmcalCells)),
87   fPhosCells(new AliAODCaloCells(*aod.fPhosCells)),
88   fCaloClusters(new TClonesArray(*aod.fCaloClusters)),
89   fFmdClusters(new TClonesArray(*aod.fFmdClusters)),
90   fPmdClusters(new TClonesArray(*aod.fPmdClusters))
91 {
92   // Copy constructor
93   AddObject(fHeader);
94   AddObject(fTracks);
95   AddObject(fVertices);
96   AddObject(fV0s);
97   AddObject(fCascades);
98   AddObject(fTracklets);
99   AddObject(fJets);
100   AddObject(fEmcalCells);
101   AddObject(fPhosCells);
102   AddObject(fCaloClusters);
103   AddObject(fFmdClusters);
104   AddObject(fPmdClusters);
105   fConnected = aod.fConnected;
106   GetStdContent();
107   CreateStdFolders();
108 }
109
110 //______________________________________________________________________________
111 AliAODEvent & AliAODEvent::operator=(const AliAODEvent& aod) {
112
113     // Assignment operator
114
115   if(&aod == this) return *this;
116   AliVEvent::operator=(aod);
117
118   // This assumes that the list is already created
119   // and that the virtual void Copy(Tobject&) function
120   // is correctly implemented in the derived class
121   // otherwise only TObject::Copy() will be used
122
123   if((fAODObjects->GetSize()==0)&&(aod.fAODObjects->GetSize()>=kAODListN)){
124     // We cover the case that we do not yet have the 
125     // standard content but the source has it
126     CreateStdContent();
127   }
128   
129   // Here we have the standard content without user additions, but the content is 
130   // not matching the aod source.
131   
132   // Iterate the list of source objects
133   TIter next(aod.GetList());
134   TObject *its = 0;
135   TString name;
136   while ((its = next())) {
137     name = its->GetName();
138     // Check if we have this object type in out list
139     TObject *mine = fAODObjects->FindObject(name);    
140     if(!mine) {
141       // We have to create the same type of object.
142       TClass* pClass=TClass::GetClass(its->ClassName());     
143       if (!pClass) {
144         AliWarning(Form("Can not find class description for entry %s (%s)\n",
145                    its->ClassName(), name.Data()));
146         continue;
147       }
148       mine=(TObject*)pClass->New();
149       if(!mine){
150         // not in this: can be added to list
151         AliWarning(Form("%s:%d Could not find %s for copying \n",
152                    (char*)__FILE__,__LINE__,name.Data()));
153         continue;
154       }  
155       if(mine->InheritsFrom("TNamed"))  {
156         ((TNamed*)mine)->SetName(name);
157       } else if(mine->InheritsFrom("TCollection")){
158         if(mine->InheritsFrom("TClonesArray")) {
159           TClonesArray *itscl = dynamic_cast<TClonesArray*>(its);
160           if (!itscl) {
161             AliWarning(Form("Class description for entry %s (%s) not TClonesArray\n",
162                    its->ClassName(), name.Data()));
163             continue;
164           
165           }
166                dynamic_cast<TClonesArray*>(mine)->SetClass(itscl->GetClass(), itscl->GetSize());
167         }
168         dynamic_cast<TCollection*>(mine)->SetName(name);
169       }
170       AliDebug(1, Form("adding object %s of type %s", mine->GetName(), mine->ClassName()));
171       AddObject(mine);
172     }
173     // Now we have an object of the same type and name, but different content.        
174     if(!its->InheritsFrom("TCollection")){
175       // simple objects (do they have a Copy method that calls operator= ?)
176       its->Copy(*mine);
177     } else if (its->InheritsFrom("TClonesArray")) {
178       // Create or expand the tclonesarray pointers
179       // so we can directly copy to the object
180       TClonesArray *its_tca = (TClonesArray*)its;
181       TClonesArray *mine_tca = (TClonesArray*)mine;
182       // this leaves the capacity of the TClonesArray the same
183       // except for a factor of 2 increase when size > capacity
184       // does not release any memory occupied by the tca
185       Int_t its_entries = its_tca->GetEntriesFast();
186       mine_tca->ExpandCreate(its_entries);
187       for(int i=0; i<its_entries; i++){
188         // copy 
189         TObject *mine_tca_obj = mine_tca->At(i);
190         TObject *its_tca_obj = its_tca->At(i);
191         // no need to delete first
192         // pointers within the class should be handled by Copy()...
193         // Can there be Empty slots?
194         its_tca_obj->Copy(*mine_tca_obj);
195       }
196     } else {
197       AliWarning(Form("%s:%d cannot copy TCollection \n",
198                       (char*)__FILE__,__LINE__));
199     }
200   }  
201   fConnected = aod.fConnected;
202   return *this;
203 }
204
205
206 //______________________________________________________________________________
207 AliAODEvent::~AliAODEvent() 
208 {
209 // destructor
210     if(fAODObjects&&!fConnected)
211     {
212         delete fAODObjects;
213         fAODObjects = 0;
214     }
215
216     delete fAODFolder;
217 }
218
219 //______________________________________________________________________________
220 void AliAODEvent::AddObject(TObject* obj) 
221 {
222   // Add an object to the list of objects.
223   // Please be aware that in order to increase performance you should
224   // refrain from using TObjArrays (if possible). Use TClonesArrays, instead.
225   
226   fAODObjects->AddLast(obj);
227 }
228
229 //______________________________________________________________________________
230 void AliAODEvent::RemoveObject(TObject* obj) 
231 {
232   // Removes an object from the list of objects.
233   
234   fAODObjects->Remove(obj);
235 }
236
237 //______________________________________________________________________________
238 TObject *AliAODEvent::FindListObject(const char *objName)
239 {
240   // Return the pointer to the object with the given name.
241
242   return fAODObjects->FindObject(objName);
243 }
244
245 //______________________________________________________________________________
246 void AliAODEvent::CreateStdContent() 
247 {
248   // create the standard AOD content and set pointers
249
250   // create standard objects and add them to the TList of objects
251   AddObject(new AliAODHeader());
252   AddObject(new TClonesArray("AliAODTrack", 0));
253   AddObject(new TClonesArray("AliAODVertex", 0));
254   AddObject(new TClonesArray("AliAODv0", 0));
255   AddObject(new TClonesArray("AliAODcascade", 0));
256   AddObject(new AliAODTracklets());
257   AddObject(new TClonesArray("AliAODJet", 0));
258   AddObject(new AliAODCaloCells());
259   AddObject(new AliAODCaloCells());
260   AddObject(new TClonesArray("AliAODCaloCluster", 0));
261   AddObject(new TClonesArray("AliAODFmdCluster", 0));
262   AddObject(new TClonesArray("AliAODPmdCluster", 0));
263   // set names
264   SetStdNames();
265
266   // read back pointers
267   GetStdContent();
268   CreateStdFolders();
269   return;
270 }
271
272 void  AliAODEvent::MakeEntriesReferencable()
273 {
274     // Make all entries referencable in a subsequent process
275     //
276     TIter next(fAODObjects);
277     TObject* obj;
278     while ((obj = next()))
279     {
280         if(obj->InheritsFrom("TCollection"))
281             {
282                 AssignIDtoCollection((TCollection*)obj);
283             }
284     }
285 }
286
287 //______________________________________________________________________________
288 void AliAODEvent::SetStdNames()
289 {
290   // introduce the standard naming
291
292   if(fAODObjects->GetEntries()==kAODListN){
293     for(int i = 0;i < fAODObjects->GetEntries();i++){
294       TObject *fObj = fAODObjects->At(i);
295       if(fObj->InheritsFrom("TNamed")){
296         ((TNamed*)fObj)->SetName(fAODListName[i]);
297       }
298       else if(fObj->InheritsFrom("TClonesArray")){
299         ((TClonesArray*)fObj)->SetName(fAODListName[i]);
300       }
301     }
302   }
303   else{
304     printf("%s:%d SetStdNames() Wrong number of Std Entries \n",(char*)__FILE__,__LINE__);
305   }
306
307
308 void AliAODEvent::CreateStdFolders()
309 {
310     // Create the standard folder structure
311     fAODFolder = gROOT->GetRootFolder()->AddFolder("AOD", "AOD");
312     if(fAODObjects->GetEntries()==kAODListN){
313         for(int i = 0;i < fAODObjects->GetEntries();i++){
314             TObject *fObj = fAODObjects->At(i);
315             if(fObj->InheritsFrom("TClonesArray")){
316                 fAODFolder->AddFolder(fAODListName[i], fAODListName[i], (TCollection*) fObj);
317             } else {
318                 fAODFolder->AddFolder(fAODListName[i], fAODListName[i], 0);
319             }
320         }
321     }
322     else{
323         printf("%s:%d CreateStdFolders() Wrong number of Std Entries \n",(char*)__FILE__,__LINE__);
324     }
325
326
327 //______________________________________________________________________________
328 void AliAODEvent::GetStdContent()
329 {
330   // set pointers for standard content
331
332   fHeader        = (AliAODHeader*)fAODObjects->FindObject("header");
333   fTracks        = (TClonesArray*)fAODObjects->FindObject("tracks");
334   fVertices      = (TClonesArray*)fAODObjects->FindObject("vertices");
335   fV0s           = (TClonesArray*)fAODObjects->FindObject("v0s");
336   fCascades      = (TClonesArray*)fAODObjects->FindObject("cascades");
337   fTracklets     = (AliAODTracklets*)fAODObjects->FindObject("tracklets");
338   fJets          = (TClonesArray*)fAODObjects->FindObject("jets");
339   fEmcalCells    = (AliAODCaloCells*)fAODObjects->FindObject("emcalCells");
340   fPhosCells     = (AliAODCaloCells*)fAODObjects->FindObject("phosCells");
341   fCaloClusters  = (TClonesArray*)fAODObjects->FindObject("caloClusters");
342   fFmdClusters   = (TClonesArray*)fAODObjects->FindObject("fmdClusters");
343   fPmdClusters   = (TClonesArray*)fAODObjects->FindObject("pmdClusters");
344 }
345
346 //______________________________________________________________________________
347 void AliAODEvent::ResetStd(Int_t trkArrSize, 
348                            Int_t vtxArrSize, 
349                            Int_t v0ArrSize,
350                            Int_t cascadeArrSize,
351                            Int_t jetSize, 
352                            Int_t caloClusSize, 
353                            Int_t fmdClusSize, 
354                            Int_t pmdClusSize
355                            )
356 {
357   // deletes content of standard arrays and resets size 
358   
359   fTracks->Delete();
360   if (trkArrSize > fTracks->GetSize()) 
361     fTracks->Expand(trkArrSize);
362
363   fVertices->Delete();
364   if (vtxArrSize > fVertices->GetSize()) 
365     fVertices->Expand(vtxArrSize);
366          
367   fV0s->Delete();
368   if (v0ArrSize > fV0s->GetSize()) 
369     fV0s->Expand(v0ArrSize);
370   
371   fCascades->Delete();
372   if (cascadeArrSize > fCascades->GetSize()) 
373     fCascades->Expand(cascadeArrSize);
374   
375   fJets->Delete();
376   if (jetSize > fJets->GetSize())
377     fJets->Expand(jetSize);
378
379   fCaloClusters->Delete();
380   if (caloClusSize > fCaloClusters->GetSize()) 
381     fCaloClusters->Expand(caloClusSize);
382
383   fFmdClusters->Delete();
384   if (fmdClusSize > fFmdClusters->GetSize()) 
385     fFmdClusters->Expand(fmdClusSize);
386
387   fPmdClusters->Delete();
388   if (pmdClusSize > fPmdClusters->GetSize()) 
389     fPmdClusters->Expand(pmdClusSize);
390
391   // Reset the tracklets
392   fTracklets->DeleteContainer();
393   fPhosCells->DeleteContainer();  
394   fEmcalCells->DeleteContainer();
395
396 }
397
398 void AliAODEvent::ClearStd()
399 {
400   // clears the standard arrays
401   fHeader        ->RemoveQTheta();
402   fTracks        ->Delete();
403   fVertices      ->Delete();
404   fV0s           ->Delete();
405   fCascades      ->Delete();
406   fTracklets     ->DeleteContainer();
407   fJets          ->Delete();
408   fEmcalCells    ->DeleteContainer();
409   fPhosCells     ->DeleteContainer();
410   fCaloClusters  ->Delete();
411   fFmdClusters   ->Clear();
412   fPmdClusters   ->Clear();
413 }
414
415 //_________________________________________________________________
416 Int_t AliAODEvent::GetPHOSClusters(TRefArray *clusters) const
417 {
418   // fills the provided TRefArray with all found phos clusters
419   
420   clusters->Clear();
421   
422   AliAODCaloCluster *cl = 0;
423   Bool_t first = kTRUE;
424   for (Int_t i = 0; i < GetNCaloClusters() ; i++) {
425     if ( (cl = GetCaloCluster(i)) ) {
426       if (cl->IsPHOSCluster()){
427         if(first) {
428           new (clusters) TRefArray(TProcessID::GetProcessWithUID(cl)); 
429           first=kFALSE;
430         }
431         clusters->Add(cl);
432         //printf("IsPHOS cluster %d, E %2.3f Size: %d \n",i,cl->E(),clusters->GetEntriesFast());
433       }
434     }
435   }
436   return clusters->GetEntriesFast();
437 }
438
439 //_________________________________________________________________
440 Int_t AliAODEvent::GetEMCALClusters(TRefArray *clusters) const
441 {
442   // fills the provided TRefArray with all found emcal clusters
443
444   clusters->Clear();
445   AliAODCaloCluster *cl = 0;
446   Bool_t first = kTRUE;
447   for (Int_t i = 0; i < GetNCaloClusters(); i++) {
448     if ( (cl = GetCaloCluster(i)) ) {
449       if (cl->IsEMCALCluster()){
450         if(first) {
451           new (clusters) TRefArray(TProcessID::GetProcessWithUID(cl)); 
452           first=kFALSE;
453         }
454         clusters->Add(cl);
455         //printf("IsEMCal cluster %d, E %2.3f Size: %d \n",i,cl->E(),clusters->GetEntriesFast());
456       }
457     }
458   }
459   return clusters->GetEntriesFast();
460 }
461
462
463 //______________________________________________________________________________
464 Int_t AliAODEvent::GetMuonTracks(TRefArray *muonTracks) const
465 {
466   // fills the provided TRefArray with all found muon tracks
467
468   muonTracks->Clear();
469
470   AliAODTrack *track = 0;
471   for (Int_t iTrack = 0; iTrack < GetNTracks(); iTrack++) {
472     if ((track = GetTrack(iTrack))->IsMuonTrack()) {
473       muonTracks->Add(track);
474     }
475   }
476   
477   return muonTracks->GetEntriesFast();
478 }
479
480
481 void AliAODEvent::ReadFromTree(TTree *tree, Option_t* opt /*= ""*/)
482 {
483   // Connects aod event to tree
484   
485   if(!tree){
486     Printf("%s %d AliAODEvent::ReadFromTree() Zero Pointer to Tree \n",(char*)__FILE__,__LINE__);
487     return;
488   }
489   // load the TTree
490   if(!tree->GetTree())tree->LoadTree(0);
491
492   // Try to find AliAODEvent
493   AliAODEvent *aodEvent = 0;
494   aodEvent = (AliAODEvent*)tree->GetTree()->GetUserInfo()->FindObject("AliAODEvent");
495   if(aodEvent){
496     // Check if already connected to tree
497     TList* connectedList = (TList*) (tree->GetUserInfo()->FindObject("AODObjectsConnectedToTree"));
498     if (connectedList && (strcmp(opt, "reconnect"))) {
499         // If connected use the connected list of objects
500         fAODObjects->Delete();
501         fAODObjects = connectedList;
502         GetStdContent(); 
503         fConnected = kTRUE;
504         return;
505     } 
506     // Connect to tree
507     // prevent a memory leak when reading back the TList
508     // if (!(strcmp(opt, "reconnect"))) fAODObjects->Delete();
509
510     // create a new TList from the UserInfo TList... 
511     // copy constructor does not work...
512     fAODObjects = (TList*)(aodEvent->GetList()->Clone());
513     fAODObjects->SetOwner(kTRUE);
514     if(fAODObjects->GetEntries()<kAODListN){
515       printf("%s %d AliAODEvent::ReadFromTree() TList contains less than the standard contents %d < %d \n",
516              (char*)__FILE__,__LINE__,fAODObjects->GetEntries(),kAODListN);
517     }
518     //
519     // Let's find out whether we have friends
520     TList* friendL = tree->GetTree()->GetListOfFriends();
521     if (friendL) 
522     {
523         TIter next(friendL);
524         TFriendElement* fe;
525         while ((fe = (TFriendElement*)next())){
526             aodEvent = (AliAODEvent*)(fe->GetTree()->GetUserInfo()->FindObject("AliAODEvent"));
527             if (!aodEvent) {
528                 printf("No UserInfo on tree \n");
529             } else {
530
531                 TList* objL = (TList*)(aodEvent->GetList()->Clone());
532                 printf("Get list of object from tree %d !!\n", objL->GetEntries());
533                 TIter nextobject(objL);
534                 TObject* obj =  0;
535                 while((obj = nextobject()))
536                 {
537                     printf("Adding object from friend %s !\n", obj->GetName());
538                     fAODObjects->Add(obj);
539                 } // object "branch" loop
540             } // has userinfo  
541         } // friend loop
542     } // has friends    
543             
544
545 // set the branch addresses
546     TIter next(fAODObjects);
547     TNamed *el;
548     while((el=(TNamed*)next())){
549       TString bname(el->GetName());
550       // check if branch exists under this Name
551       TBranch *br = tree->GetTree()->GetBranch(bname.Data());
552       if(br){
553         tree->SetBranchAddress(bname.Data(),fAODObjects->GetObjectRef(el));
554       } else {
555           br = tree->GetBranch(Form("%s.",bname.Data()));
556           if(br){
557               tree->SetBranchAddress(Form("%s.",bname.Data()),fAODObjects->GetObjectRef(el));
558           }
559           else{
560               printf("%s %d AliAODEvent::ReadFromTree() No Branch found with Name %s. \n",
561                      (char*)__FILE__,__LINE__,bname.Data());
562           }     
563       }
564     }
565     GetStdContent();
566     // when reading back we are not owner of the list 
567     // must not delete it
568     fAODObjects->SetOwner(kTRUE);
569     fAODObjects->SetName("AODObjectsConnectedToTree");
570     // we are not owner of the list objects 
571     // must not delete it
572     tree->GetUserInfo()->Add(fAODObjects);
573     fConnected = kTRUE;
574   }// no aodEvent
575   else {
576     // we can't get the list from the user data, create standard content
577     // and set it by hand
578     CreateStdContent();
579     TIter next(fAODObjects);
580     TNamed *el;
581     while((el=(TNamed*)next())){
582       TString bname(el->GetName());    
583       tree->SetBranchAddress(bname.Data(),fAODObjects->GetObjectRef(el));
584     }
585     GetStdContent();
586     // when reading back we are not owner of the list 
587     // must not delete it
588     fAODObjects->SetOwner(kTRUE);
589   }
590 }
591
592 //______________________________________________________________________________
593 void AliAODEvent::Print(Option_t *) const
594 {
595   // Print the names of the all branches
596   TIter next(fAODObjects);
597   TNamed *el;
598   Printf(">>>>>  AOD  Content <<<<<");    
599   while((el=(TNamed*)next())){
600     Printf(">> %s ",el->GetName());      
601   }
602   Printf(">>>>>                <<<<<");    
603   
604   return;
605 }
606
607 void AliAODEvent::AssignIDtoCollection(TCollection* col)
608 {
609     // Static method which assigns a ID to each object in a collection
610     // In this way the objects are marked as referenced and written with 
611     // an ID. This has the advantage that TRefs to this objects can be 
612     // written by a subsequent process.
613     TIter next(col);
614     TObject* obj;
615     while ((obj = next()))
616         TProcessID::AssignID(obj);
617 }