fixes from Laurent for the MC branch in the AOD filters
authoragheata <agheata@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 18 Feb 2011 10:52:02 +0000 (10:52 +0000)
committeragheata <agheata@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 18 Feb 2011 10:52:02 +0000 (10:52 +0000)
ANALYSIS/macros/AddTaskESDFilter.C
PWG3/muon/AliAODMuonReplicator.cxx
PWG3/muon/AliAODMuonReplicator.h
PWG3/muon/AliAnalysisTaskESDMuonFilter.cxx
PWG3/muon/AliAnalysisTaskESDMuonFilter.h
STEER/AliAODEvent.cxx
STEER/AliAODExtension.cxx [new file with mode: 0644]
STEER/AliAODExtension.h [new file with mode: 0644]
STEER/AliAODHandler.cxx
STEER/AliAODHandler.h
STEER/CMakelibAOD.pkg

index 50e5e9d..c185a7c 100644 (file)
@@ -48,7 +48,10 @@ AliAnalysisTaskESDfilter *AddTaskESDFilter(Bool_t useKineFilter=kTRUE,
    mgr->AddTask(esdfilter);
   
    // Muons
-   AliAnalysisTaskESDMuonFilter *esdmuonfilter = new AliAnalysisTaskESDMuonFilter("ESD Muon Filter");
+   Bool_t onlyMuon=kTRUE;
+   Bool_t keepAllEvents=kTRUE;
+   Int_t mcMode=(useKineFilter ? 2 : 0); // use 1 instead of 2 to get all MC information instead of just ancestors of mu tracks
+   AliAnalysisTaskESDMuonFilter *esdmuonfilter = new AliAnalysisTaskESDMuonFilter("ESD Muon Filter",onlyMuon,keepAllEvents,mcMode);
    mgr->AddTask(esdmuonfilter);
    if(usePhysicsSelection){
      esdfilter->SelectCollisionCandidates(AliVEvent::kAny);
index 3f99d9b..4c96bb0 100644 (file)
 #include "AliAODEvent.h"
 #include "AliAODTrack.h"
 #include "AliAODDimuon.h"
+#include "AliAODMCHeader.h"
+#include "AliAODMCParticle.h"
 #include <cassert>
 
 ClassImp(AliAODMuonReplicator)
 
 //_____________________________________________________________________________
 AliAODMuonReplicator::AliAODMuonReplicator(const char* name, const char* title,
-                                                 AliAnalysisCuts* trackCut,
-                                                 AliAnalysisCuts* vertexCut)
-: AliAODBranchReplicator(name,title), 
+                                           AliAnalysisCuts* trackCut,
+                                           AliAnalysisCuts* vertexCut,
+                                           Int_t mcMode)
+:AliAODBranchReplicator(name,title), 
 fTrackCut(trackCut), fTracks(0x0), 
 fVertexCut(vertexCut), fVertices(0x0), 
 fDimuons(0x0),
-fList(0x0)
+fList(0x0),
+fMCParticles(0x0),
+fMCHeader(0x0),
+fMCMode(mcMode),
+fLabelMap(),
+fParticleSelected()
 {
   // default ctor
 }
@@ -67,6 +75,235 @@ AliAODMuonReplicator::~AliAODMuonReplicator()
 }
 
 //_____________________________________________________________________________
+void AliAODMuonReplicator::SelectParticle(Int_t i)
+{
+  // taking the absolute values here, need to take care 
+  // of negative daughter and mother
+  // IDs when setting!
+  
+  if (!IsParticleSelected(TMath::Abs(i)))
+  {
+    fParticleSelected.Add(TMath::Abs(i),1);    
+  }
+}
+
+//_____________________________________________________________________________
+Bool_t AliAODMuonReplicator::IsParticleSelected(Int_t i)  
+{
+  // taking the absolute values here, need to take 
+  // care with negative daughter and mother
+  // IDs when setting!
+  return (fParticleSelected.GetValue(TMath::Abs(i))==1);
+}
+
+
+//_____________________________________________________________________________
+void AliAODMuonReplicator::CreateLabelMap(const AliAODEvent& source)
+{  
+  //
+  // this should be called once all selections are done 
+  //
+  
+  fLabelMap.Delete();
+  
+  TClonesArray* mcParticles = static_cast<TClonesArray*>(source.FindListObject(AliAODMCParticle::StdBranchName()));
+  
+  Int_t i(0);
+  Int_t j(0);
+  
+  TIter next(mcParticles);
+  
+  while ( next() ) 
+  {
+    if (IsParticleSelected(i))
+    {
+      fLabelMap.Add(i,j++);
+    }
+    ++i;
+  }
+}
+
+//_____________________________________________________________________________
+Int_t AliAODMuonReplicator::GetNewLabel(Int_t i) 
+{
+  // Gets the label from the new created Map
+  // Call CreatLabelMap before
+  // otherwise only 0 returned
+  return fLabelMap.GetValue(TMath::Abs(i));
+}
+
+//_____________________________________________________________________________
+void AliAODMuonReplicator::FilterMC(const AliAODEvent& source)
+{
+  // Filter MC information
+
+  fMCHeader->Reset();
+  fMCParticles->Clear("C");
+
+  AliAODMCHeader* mcHeader(0x0);
+  TClonesArray* mcParticles(0x0);
+  
+  fParticleSelected.Delete();
+  
+  if ( !fTracks->GetEntries() ) return;
+  // only copy MC information for events where there's at least one muon track
+    
+  mcHeader = static_cast<AliAODMCHeader*>(source.FindListObject(AliAODMCHeader::StdBranchName()));
+  
+  if ( mcHeader ) 
+  {
+    *fMCHeader = *mcHeader;
+  }
+  
+  mcParticles = static_cast<TClonesArray*>(source.FindListObject(AliAODMCParticle::StdBranchName()));
+  
+  if ( mcParticles && fMCMode>=2 )
+  {
+    // loop on (kept) muon tracks to find their ancestors
+    TIter nextMT(fTracks);
+    AliAODTrack* mt;
+    int outLabel(0);
+    
+    while ( ( mt = static_cast<AliAODTrack*>(nextMT()) ) )
+    {
+      Int_t label = mt->GetLabel();
+      
+      while ( label >= 0 ) 
+      {
+        SelectParticle(label);
+        AliAODMCParticle* mother = static_cast<AliAODMCParticle*>(mcParticles->UncheckedAt(label));
+        if (!mother)
+        {
+          AliError("Got a null mother ! Check that !");
+          label = -1;
+        }
+        else
+        {
+          label = mother->GetMother();
+        }
+      }
+    }
+    
+    CreateLabelMap(source);
+    
+    // Actual filtering and label remapping (shamelessly taken for the implementation of AliAODHandler::StoreMCParticles)
+    TIter nextMC(mcParticles);
+    AliAODMCParticle* p;
+    Int_t nmc(0);
+    Int_t nmcout(0);
+    
+    while ( ( p = static_cast<AliAODMCParticle*>(nextMC()) ) )
+    {
+      AliAODMCParticle c(*p);
+      
+      if ( IsParticleSelected(nmc) )
+      {
+        // 
+        Int_t d0 =  p->GetDaughter(0);
+        Int_t d1 =  p->GetDaughter(1);
+        Int_t m =   p->GetMother();
+        
+        // other than for the track labels, negative values mean
+        // no daughter/mother so preserve it
+        
+        if(d0<0 && d1<0)
+        {
+          // no first daughter -> no second daughter
+          // nothing to be done
+          // second condition not needed just for sanity check at the end
+          c.SetDaughter(0,d0);
+          c.SetDaughter(1,d1);
+        } else if(d1 < 0 && d0 >= 0) 
+        {
+          // Only one daughter
+          // second condition not needed just for sanity check at the end
+          if(IsParticleSelected(d0))
+          {
+            c.SetDaughter(0,GetNewLabel(d0));
+          } else 
+          {
+            c.SetDaughter(0,-1);
+          }
+          c.SetDaughter(1,d1);
+        }
+        else if (d0 > 0 && d1 > 0 )
+        {
+          // we have two or more daughters loop on the stack to see if they are
+          // selected
+          Int_t d0tmp = -1;
+          Int_t d1tmp = -1;
+          for (int id = d0; id<=d1;++id)
+          {
+            if (IsParticleSelected(id))
+            {
+              if(d0tmp==-1)
+              {
+                // first time
+                d0tmp = GetNewLabel(id);
+                d1tmp = d0tmp; // this is to have the same schema as on the stack i.e. with one daugther d0 and d1 are the same 
+              }
+              else d1tmp = GetNewLabel(id);
+            }
+          }
+          c.SetDaughter(0,d0tmp);
+          c.SetDaughter(1,d1tmp);
+        } else 
+        {
+          AliError(Form("Unxpected indices %d %d",d0,d1));
+        }
+        
+        if ( m < 0 )
+        {
+          c.SetMother(m);
+        } else 
+        {
+          if (IsParticleSelected(m)) 
+          {
+            c.SetMother(GetNewLabel(m));              
+          }
+          else 
+          {
+            AliError(Form("PROBLEM Mother not selected %d", m));              
+          }
+        }
+        
+        new ((*fMCParticles)[nmcout++]) AliAODMCParticle(c);
+      }
+      
+      ++nmc;        
+    }      
+    
+    // now remap the tracks...
+    
+    TIter nextTrack(fTracks);
+    AliAODTrack* t;
+    
+    while ( ( t = static_cast<AliAODTrack*>(nextTrack()) ) )
+    {
+      t->SetLabel(GetNewLabel(t->GetLabel()));
+    }
+    
+  }
+  else if ( mcParticles ) 
+  {
+    // simple copy of input MC particles to ouput MC particles
+    TIter nextMC(mcParticles);
+    AliAODMCParticle* p;
+    Int_t nmcout(0);
+    
+    while ( ( p = static_cast<AliAODMCParticle*>(nextMC()) ) )
+    {
+      new ((*fMCParticles)[nmcout++]) AliAODMCParticle(*p);
+    }
+  }
+  
+  AliDebug(1,Form("input mc %d output mc %d",
+                  mcParticles ? mcParticles->GetEntries() : 0,
+                  fMCParticles ? fMCParticles->GetEntries() : 0));
+  
+}
+
+//_____________________________________________________________________________
 TList* AliAODMuonReplicator::GetList() const
 {
   // return (and build if not already done) our internal list of managed objects
@@ -77,7 +314,7 @@ TList* AliAODMuonReplicator::GetList() const
     
     fVertices = new TClonesArray("AliAODVertex",2);
                fVertices->SetName("vertices");    
-
+    
     fDimuons = new TClonesArray("AliAODDimuon",2);
     fDimuons->SetName("dimuons");
     
@@ -87,6 +324,15 @@ TList* AliAODMuonReplicator::GetList() const
     fList->Add(fTracks);
     fList->Add(fVertices);
     fList->Add(fDimuons);
+
+    if ( fMCMode > 0 )
+    {
+      fMCHeader = new AliAODMCHeader;    
+      fMCParticles = new TClonesArray("AliAODMCParticle",1000);
+      fMCParticles->SetName(AliAODMCParticle::StdBranchName());
+      fList->Add(fMCHeader);
+      fList->Add(fMCParticles);
+    }
   }
   return fList;
 }
@@ -96,19 +342,20 @@ void AliAODMuonReplicator::ReplicateAndFilter(const AliAODEvent& source)
 {
   // Replicate (and filter if filters are there) the relevant parts we're interested in AODEvent
   
-  static int n(0);
-  
-  ++n;
-  
   assert(fTracks!=0x0);
   fTracks->Clear("C");
   TIter next(source.GetTracks());
   AliAODTrack* t;
   Int_t ntracks(0);
-  
+  Int_t input(0);
   
   while ( ( t = static_cast<AliAODTrack*>(next()) ) )
   {
+    if ( t->IsMuonTrack() ) 
+    {
+      ++input;
+    }
+    
     if ( !fTrackCut || fTrackCut->IsSelected(t) ) 
     {
       new((*fTracks)[ntracks++]) AliAODTrack(*t);
@@ -145,7 +392,15 @@ void AliAODMuonReplicator::ReplicateAndFilter(const AliAODEvent& source)
       new((*fDimuons)[ndimuons++]) AliAODDimuon(fTracks->At(i),fTracks->At(j));
     }
   }
-  
-  AliDebug(1,Form("n=%d tracks=%d vertices=%d ndimuons=%d",n,fTracks->GetEntries(),fVertices->GetEntries(),fDimuons->GetEntries()));
+
+  AliDebug(1,Form("input mu tracks=%d tracks=%d vertices=%d ndimuons=%d",
+                  input,fTracks->GetEntries(),fVertices->GetEntries(),fDimuons->GetEntries()));
+
+  // Finally, deal with MC information, if needed
+
+  if ( fMCMode > 0 )
+  {
+    FilterMC(source);      
+  }
 }
 
index 4399fee..9d5d25f 100644 (file)
@@ -10,6 +10,9 @@
 #ifndef ALIDAODBRANCHREPLICATOR_H
 #  include "AliAODBranchReplicator.h"
 #endif
+#ifndef ROOT_TExMap
+#  include "TExMap.h"
+#endif
 
 //
 // Implementation of a branch replicator 
 
 class AliAnalysisCuts;
 class TClonesArray;
+class AliAODMCHeader;
 
 class AliAODMuonReplicator : public AliAODBranchReplicator
 {
 public:
+  
   AliAODMuonReplicator(const char* name="AliAODMuonReplicator", 
                        const char* title="Branch Replicator for muon related branches",
                        AliAnalysisCuts* trackCut=0x0,
-                       AliAnalysisCuts* vertexCut=0x0);
+                       AliAnalysisCuts* vertexCut=0x0,
+                       Int_t mcMode=0);
   virtual ~AliAODMuonReplicator();
   
   virtual TList* GetList() const;
@@ -34,6 +40,13 @@ public:
   virtual void ReplicateAndFilter(const AliAODEvent& source);
   
 private:
+  void FilterMC(const AliAODEvent& source);
+  void SelectParticle(Int_t i);
+  Bool_t IsParticleSelected(Int_t i);
+  void CreateLabelMap(const AliAODEvent& source);
+  Int_t GetNewLabel(Int_t i);
+  
+private:
   AliAnalysisCuts* fTrackCut; // decides which tracks to keep
   mutable TClonesArray* fTracks; //! internal array of muon tracks
   AliAnalysisCuts* fVertexCut; // decides which vertices to keep
@@ -41,11 +54,17 @@ private:
   mutable TClonesArray* fDimuons; //! internal array of dimuons
   mutable TList* fList; //! internal list of managed objects (fVertices and fTracks)
   
+  mutable TClonesArray* fMCParticles; //! internal array of MC particles
+  mutable AliAODMCHeader* fMCHeader; //! internal array of MC header
+  Int_t fMCMode; // MC filtering switch (0=none=no mc information,1=normal=simple copy,>=2=aggressive=filter out)
+  TExMap fLabelMap; //! for MC label remapping (in case of aggressive filtering)
+  TExMap fParticleSelected; //! List of selected MC particles
+
 private:
   AliAODMuonReplicator(const AliAODMuonReplicator&);
   AliAODMuonReplicator& operator=(const AliAODMuonReplicator&);
   
-  ClassDef(AliAODMuonReplicator,2) // Branch replicator for ESD to muon AOD.
+  ClassDef(AliAODMuonReplicator,3) // Branch replicator for ESD to muon AOD.
 };
 
 #endif
index 55dd806..852d107 100644 (file)
@@ -33,6 +33,7 @@
 #include "AliAODDimuon.h"
 #include "AliAODEvent.h"
 #include "AliAODHandler.h"
+#include "AliAODExtension.h"
 #include "AliAODMCParticle.h"
 #include "AliAODMuonReplicator.h"
 #include "AliAODVertex.h"
@@ -99,24 +100,26 @@ Bool_t AliAnalysisNonPrimaryVertices::IsSelected(TObject* obj)
   
 }
 
-AliAnalysisTaskESDMuonFilter::AliAnalysisTaskESDMuonFilter(Bool_t onlyMuon, Bool_t keepAllEvents):
+AliAnalysisTaskESDMuonFilter::AliAnalysisTaskESDMuonFilter(Bool_t onlyMuon, Bool_t keepAllEvents, Int_t mcMode):
   AliAnalysisTaskSE(),
   fTrackFilter(0x0),
   fEnableMuonAOD(kFALSE),
   fEnableDimuonAOD(kFALSE),
   fOnlyMuon(onlyMuon),
-  fKeepAllEvents(keepAllEvents)
+  fKeepAllEvents(keepAllEvents),
+  fMCMode(mcMode)
 {
   // Default constructor
 }
 
-AliAnalysisTaskESDMuonFilter::AliAnalysisTaskESDMuonFilter(const char* name, Bool_t onlyMuon, Bool_t keepAllEvents):
+AliAnalysisTaskESDMuonFilter::AliAnalysisTaskESDMuonFilter(const char* name, Bool_t onlyMuon, Bool_t keepAllEvents, Int_t mcMode):
   AliAnalysisTaskSE(name),
   fTrackFilter(0x0),
   fEnableMuonAOD(kFALSE),
   fEnableDimuonAOD(kFALSE),
   fOnlyMuon(onlyMuon),
-  fKeepAllEvents(keepAllEvents)
+  fKeepAllEvents(keepAllEvents),
+  fMCMode(mcMode)
 {
   // Constructor
 }
@@ -154,6 +157,11 @@ void AliAnalysisTaskESDMuonFilter::PrintTask(Option_t *option, Int_t indent) con
   {
     cout << spaces.Data() << "Keep only events with at least one muon" << endl;
   }
+  
+  if ( fMCMode > 0 ) 
+  {
+    cout << spaces.Data() << "Assuming work on MC data (i.e. will transmit MC branches)" << endl;
+  }
 }
 
 //______________________________________________________________________________
@@ -170,16 +178,29 @@ void AliAnalysisTaskESDMuonFilter::AddFilteredAOD(const char* aodfilename, const
   
   if ( fOnlyMuon ) 
   {    
-    AliAODBranchReplicator* murep = new AliAODMuonReplicator("MuonReplicator",
-                                                             "remove non muon tracks and non primary or pileup vertices",
-                                                             new AliAnalysisNonMuonTrackCuts,
-                                                             new AliAnalysisNonPrimaryVertices);
+    
+    AliAODMuonReplicator* murep = new AliAODMuonReplicator("MuonReplicator",
+                                                           "remove non muon tracks and non primary or pileup vertices",
+                                                           new AliAnalysisNonMuonTrackCuts,
+                                                           new AliAnalysisNonPrimaryVertices,
+                                                           fMCMode);
     
     ext->DropUnspecifiedBranches(); // all branches not part of a FilterBranch call (below) will be dropped
     
     ext->FilterBranch("tracks",murep);    
     ext->FilterBranch("vertices",murep);  
     ext->FilterBranch("dimuons",murep);
+
+    if ( fMCMode > 0 ) 
+    {
+      // MC branches will be copied (if present), as they are, but only
+      // for events with at least one muon. 
+      // For events w/o muon, mcparticles array will be empty and mcheader will be dummy
+      // (e.g. strlen(GetGeneratorName())==0)
+      
+      ext->FilterBranch("mcparticles",murep);
+      ext->FilterBranch("mcHeader",murep);
+    }
   }  
 }
 
index 45c3184..96e1ded 100644 (file)
@@ -23,8 +23,8 @@ class AliStack;
 class AliAnalysisTaskESDMuonFilter : public AliAnalysisTaskSE\r
 {\r
  public:\r
-    AliAnalysisTaskESDMuonFilter(Bool_t onlyMuon=kTRUE, Bool_t keepAllEvents=kTRUE);\r
-    AliAnalysisTaskESDMuonFilter(const char* name, Bool_t onlyMuon=kTRUE, Bool_t keepAllEvents=kTRUE);\r
+    AliAnalysisTaskESDMuonFilter(Bool_t onlyMuon=kTRUE, Bool_t keepAllEvents=kTRUE, Int_t mcMode=0);\r
+    AliAnalysisTaskESDMuonFilter(const char* name, Bool_t onlyMuon=kTRUE, Bool_t keepAllEvents=kTRUE, Int_t mcMode=0);\r
     virtual ~AliAnalysisTaskESDMuonFilter() {;}\r
     // Implementation of interface methods\r
     virtual void UserCreateOutputObjects();\r
@@ -53,8 +53,9 @@ class AliAnalysisTaskESDMuonFilter : public AliAnalysisTaskSE
   Bool_t fEnableDimuonAOD; // flag for enabling Dimuon AOD production\r
   Bool_t fOnlyMuon; // flag for disabling branches irrelevant for (most) muon analyses\r
   Bool_t fKeepAllEvents; // keep even events where there's no muons (to get e.g. unbiased vertex distribution)\r
+  Int_t  fMCMode; // whether and how we're filtering MC data\r
   \r
-  ClassDef(AliAnalysisTaskESDMuonFilter, 3); // Analysis task for standard ESD filtering\r
+  ClassDef(AliAnalysisTaskESDMuonFilter, 5); // Analysis task for standard ESD filtering\r
 };\r
  \r
 class AliAnalysisNonMuonTrackCuts : public AliAnalysisCuts\r
index ad72914..e2d6fff 100644 (file)
@@ -233,7 +233,10 @@ void AliAODEvent::AddObject(TObject* obj)
   // Please be aware that in order to increase performance you should
   // refrain from using TObjArrays (if possible). Use TClonesArrays, instead.
   
-  fAODObjects->AddLast(obj);
+  if ( !fAODObjects->FindObject(obj) ) 
+  {
+    fAODObjects->AddLast(obj);
+  }
 }
 
 //______________________________________________________________________________
@@ -547,9 +550,10 @@ void AliAODEvent::ReadFromTree(TTree *tree, Option_t* opt /*= ""*/)
       // copy constructor does not work...
     fAODObjects = (TList*)(aodEvent->GetList()->Clone());
     fAODObjects->SetOwner(kTRUE);
-    if(fAODObjects->GetEntries()<kAODListN){
-      printf("%s %d AliAODEvent::ReadFromTree() TList contains less than the standard contents %d < %d \n",
-             (char*)__FILE__,__LINE__,fAODObjects->GetEntries(),kAODListN);
+    if(fAODObjects->GetEntries()<kAODListN)
+    {
+      AliWarning(Form("AliAODEvent::ReadFromTree() TList contains less than the standard contents %d < %d"
+                      " That might be fine though (at least for filtered AODs)",fAODObjects->GetEntries(),kAODListN));
     }
       //
       // Let's find out whether we have friends
diff --git a/STEER/AliAODExtension.cxx b/STEER/AliAODExtension.cxx
new file mode 100644 (file)
index 0000000..3f9ab9a
--- /dev/null
@@ -0,0 +1,400 @@
+#include "AliAODExtension.h"
+
+//-------------------------------------------------------------------------
+//     Support class for AOD extensions. This is created by the user analysis
+//     that requires a separate file for some AOD branches. The name of the 
+//     AliAODExtension object is the file name where the AOD branches will be
+//     stored.
+//-------------------------------------------------------------------------
+
+#include "AliAODBranchReplicator.h"
+#include "AliAODEvent.h"
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include "Riostream.h"
+#include "TDirectory.h"
+#include "TFile.h"
+#include "TList.h"
+#include "TMap.h"
+#include "TMap.h"
+#include "TObjString.h"
+#include "TROOT.h"
+#include "TString.h"
+#include "TTree.h"
+
+ClassImp(AliAODExtension)
+
+//______________________________________________________________________________
+AliAODExtension::AliAODExtension() : TNamed(), 
+fAODEvent(0), fTreeE(0), fFileE(0), fNtotal(0), fNpassed(0), 
+fSelected(kFALSE), fRepFiMap(0x0), fRepFiList(0x0), fEnableReferences(kTRUE), fObjectList(0x0)
+{
+  // default ctor
+}
+
+//______________________________________________________________________________
+AliAODExtension::AliAODExtension(const char* name, const char* title, Bool_t isfilter)
+:TNamed(name,title), 
+fAODEvent(0), 
+fTreeE(0), 
+fFileE(0), 
+fNtotal(0), 
+fNpassed(0),
+fSelected(kFALSE),
+fRepFiMap(0x0),
+fRepFiList(0x0),
+fEnableReferences(kTRUE),
+fObjectList(0x0)
+{
+  // Constructor.
+  if (isfilter) {
+    TObject::SetBit(kFilteredAOD);
+    printf("####### Added AOD filter %s\n", name);
+  } else printf("####### Added AOD extension %s\n", name);
+  KeepUnspecifiedBranches();
+}   
+
+//______________________________________________________________________________
+AliAODExtension::~AliAODExtension()
+{
+  // Destructor.
+  if(fFileE){
+    // is already handled in TerminateIO
+    fFileE->Close();
+    delete fFileE;
+    fTreeE = 0;
+    fAODEvent = 0;
+  }
+  if (fTreeE) delete fTreeE;
+  if (fRepFiMap) fRepFiMap->DeleteAll();
+  delete fRepFiMap; // the map is owner
+  delete fRepFiList; // the list is not
+  delete fObjectList; // not owner
+}
+
+//______________________________________________________________________________
+void AliAODExtension::AddBranch(const char* cname, void* addobj)
+{
+  // Add a new branch to the aod 
+  
+  if (!fAODEvent) {
+    char type[20];
+    gROOT->ProcessLine(Form("TString s_tmp; AliAnalysisManager::GetAnalysisManager()->GetAnalysisTypeString(s_tmp); sprintf((char*)%p, \"%%s\", s_tmp.Data());", type));
+    Init(type);
+  }
+  TDirectory *owd = gDirectory;
+  if (fFileE) {
+    fFileE->cd();
+  }
+  char** apointer = (char**) addobj;
+  TObject* obj = (TObject*) *apointer;
+  
+  fAODEvent->AddObject(obj);
+  
+  TString bname(obj->GetName());
+  
+  if (!fTreeE->FindBranch(bname.Data())) 
+  {
+    Bool_t acceptAdd(kTRUE);
+    
+    if ( TestBit(kDropUnspecifiedBranches) )
+    {
+      // check that this branch is in our list of specified ones...
+      // otherwise do not add it !
+      TIter next(fRepFiMap);
+      TObjString* p;
+      
+      acceptAdd=kFALSE;
+      
+      while ( ( p = static_cast<TObjString*>(next()) ) && !acceptAdd )
+      {
+        if ( p->String() == bname ) acceptAdd=kTRUE;
+      }
+    }
+    
+    if ( acceptAdd ) 
+    {
+      // Do the same as if we book via 
+      // TTree::Branch(TCollection*)
+      
+      fObjectList->Add(obj);
+
+      const Int_t kSplitlevel = 99; // default value in TTree::Branch()
+      const Int_t kBufsize = 32000; // default value in TTree::Branch()
+      
+      fTreeE->Bronch(bname.Data(), cname, 
+                     fAODEvent->GetList()->GetObjectRef(obj),
+                     kBufsize, kSplitlevel - 1);
+    }
+  }
+  owd->cd();
+}
+
+//______________________________________________________________________________
+Bool_t AliAODExtension::FinishEvent()
+{
+  // Fill current event.
+  fNtotal++;
+  if (!IsFilteredAOD()) {
+    fAODEvent->MakeEntriesReferencable();
+    fTreeE->Fill();
+    return kTRUE;
+  }  
+  // Filtered AOD. Fill only if event is selected.
+  if (!fSelected) return kTRUE;
+  
+  TIter next(fRepFiList);
+  
+  AliAODBranchReplicator* repfi;
+  
+  while ( ( repfi = static_cast<AliAODBranchReplicator*>(next()) ) )
+  {
+    repfi->ReplicateAndFilter(*fAODEvent);
+  }
+  fNpassed++;
+  fTreeE->Fill();
+  fSelected = kFALSE; // so that next event will not be selected unless demanded
+  return kTRUE;
+}  
+
+//______________________________________________________________________________
+Bool_t AliAODExtension::Init(Option_t *option)
+{
+  // Initialize IO.
+  
+  AliCodeTimerAuto(GetName(),0);
+  
+  if(!fAODEvent) 
+  {
+    fAODEvent = new AliAODEvent();    
+  }
+  
+  TDirectory *owd = gDirectory;
+  TString opt(option);
+  opt.ToLower();
+  
+  if (opt.Contains("proof")) 
+  {
+    // proof
+    // Merging via files. Need to access analysis manager via interpreter.
+    gROOT->ProcessLine(Form("AliAnalysisDataContainer *c_common_out = AliAnalysisManager::GetAnalysisManager()->GetCommonOutputContainer();"));
+    gROOT->ProcessLine(Form("AliAnalysisManager::GetAnalysisManager()->OpenProofFile(c_common_out, \"RECREATE\", \"%s\");", fName.Data()));
+    fFileE = gFile;
+  } 
+  else 
+  {
+    fFileE = new TFile(GetName(), "RECREATE");
+  }  
+  fTreeE = new TTree("aodTree", "AliAOD tree");
+  
+  delete fObjectList;
+  fObjectList = new TList;
+  fObjectList->SetOwner(kFALSE); // be explicit we're not the owner...
+  TList* inputList = fAODEvent->GetList();
+  TIter next(inputList);
+  TObject* o;
+  
+  while ( ( o = next() ) )
+  {
+    // Loop on the objects that are within the main AOD, and see what to do with them :
+    // - transmit them to our AOD as they are
+    // - filter them (by means of an AliAODBranchReplicator)
+    // - drop them completely
+    
+    Bool_t mustKeep(kFALSE);
+    
+    TString test(o->ClassName());
+    test.ToUpper();
+    if (test.Contains("HEADER"))
+    {
+      // do not allow to drop header branch
+      mustKeep=kTRUE;
+    }
+    
+    if ( fRepFiMap && !mustKeep )
+    {
+      // we have some replicators, so let's see what the relevant one decides about this object
+      TObject* specified = fRepFiMap->FindObject(o->GetName()); // FindObject finds key=o->GetName() in the map
+      if (specified)
+      {
+        AliAODBranchReplicator* repfi = dynamic_cast<AliAODBranchReplicator*>(fRepFiMap->GetValue(o->GetName())); // GetValue gets the replicator corresponding to key=o->GetName()
+        if ( repfi ) 
+        {        
+          TList* replicatedList = repfi->GetList();
+          if (replicatedList)
+          {
+            AliAODEvent::AssignIDtoCollection(replicatedList);
+            TIter nextRep(replicatedList);
+            TObject* objRep;
+            while ( ( objRep = nextRep() ) )
+            {
+              if ( !fObjectList->FindObject(objRep) ) // insure we're not adding several times the same object
+              {                
+                fObjectList->Add(objRep);                  
+              }
+            }
+          }
+          else
+          {
+            AliError(Form("replicatedList from %s is null !",repfi->GetName()));
+          }
+        }
+      }
+      else
+      {
+        if ( !TestBit(kDropUnspecifiedBranches) ) 
+        {
+          // object o will be transmitted to the output AOD, unchanged
+          fObjectList->Add(o);
+        }
+      }
+    } 
+    else
+    {
+      // no replicator, so decide based on the policy about dropping unspecified branches
+      if ( mustKeep || !TestBit(kDropUnspecifiedBranches) )
+      {
+        // object o will be transmitted to the output AOD, unchanged
+        fObjectList->Add(o);
+      }
+    }
+  }
+    
+  if (fEnableReferences) 
+  {
+    fTreeE->BranchRef();    
+  }
+    
+  fTreeE->Branch(fObjectList);
+  
+  owd->cd();
+  
+  return kTRUE;
+}
+
+//______________________________________________________________________________
+void AliAODExtension::Print(Option_t* opt) const
+{
+  // Print info about this extension
+  
+  cout << opt << Form("%s - %s - %s - aod %p",IsFilteredAOD() ? "FilteredAOD" : "Extension",
+                      GetName(),GetTitle(),GetAOD()) << endl;
+  if ( !fEnableReferences ) 
+  {
+    cout << opt << opt << "References are disabled ! Hope you know what you are doing !" << endl;
+  }
+  if ( TestBit(kDropUnspecifiedBranches) )
+  {
+    cout << opt << opt << "All branches not explicitely specified will be dropped" << endl;
+  }
+  
+  TIter next(fRepFiMap);
+  TObjString* s;
+  
+  while ( ( s = static_cast<TObjString*>(next()) ) )
+  {
+    AliAODBranchReplicator* br = static_cast<AliAODBranchReplicator*>(fRepFiMap->GetValue(s->String().Data()));
+    
+    cout << opt << opt << "Branch " << s->String();
+    if (br)
+    {
+      cout << " will be filtered by class " << br->ClassName();
+    }
+    else
+    {
+      cout << " will be transmitted as is";
+    }
+    cout << endl;
+  }
+}
+
+//______________________________________________________________________________
+void AliAODExtension::SetEvent(AliAODEvent* event)
+{
+  // Connects to an external event
+  if (!IsFilteredAOD()) {
+    Error("SetEvent", "Not allowed to set external event for non filtered AOD's");   
+    return;
+  }
+  fAODEvent = event;
+}
+
+//______________________________________________________________________________
+void AliAODExtension::AddAODtoTreeUserInfo()
+{
+  // Add aod event to tree user info
+  
+  if (!fTreeE) return;
+  
+  AliAODEvent* aodEvent(fAODEvent);
+  
+  if ( IsFilteredAOD() )
+  {
+    // cannot attach fAODEvent (which is shared with our AliAODHandler mother)
+    // so we create a custom (empty) AliAODEvent 
+    // Has also the advantage we can specify only the list of objects
+    // that are actually there in this filtered aod
+    //
+    aodEvent = new AliAODEvent;
+    TIter nextObj(fObjectList);
+    TObject* o;
+    while ( ( o = nextObj() ) ) 
+    {
+      aodEvent->AddObject(o);
+    }    
+  }
+  
+  fTreeE->GetUserInfo()->Add(aodEvent);
+}
+
+//______________________________________________________________________________
+Bool_t AliAODExtension::TerminateIO()
+{
+  // Terminate IO
+  if (TObject::TestBit(kFilteredAOD))
+    printf("AOD Filter %s: events processed: %d   passed: %d\n", GetName(), fNtotal, fNpassed);
+  else
+    printf("AOD extension %s: events processed: %d\n", GetName(), fNtotal);
+  if (fFileE) 
+  {
+    fFileE->Write();
+    fFileE->Close();
+    delete fFileE;
+    fFileE = 0;
+    fTreeE = 0;
+    fAODEvent = 0;
+  }
+  return kTRUE;
+}
+
+//______________________________________________________________________________
+void AliAODExtension::FilterBranch(const char* branchName, AliAODBranchReplicator* repfi)
+{
+  // Specify a filter/replicator for a given branch
+  //
+  // If repfi=0x0, this will disable the branch (in the output) completely.
+  //
+  // repfi is adopted by this class, i.e. user should not delete it.
+  //
+  // WARNING : branch name must be exact.
+  //
+  // See also the documentation for AliAODBranchReplicator class.
+  //
+  
+  if (!fRepFiMap)
+  {
+    fRepFiMap = new TMap;
+    fRepFiMap->SetOwnerKeyValue(kTRUE,kTRUE);
+    fRepFiList = new TList;
+    fRepFiList->SetOwner(kFALSE);
+  }
+  
+  fRepFiMap->Add(new TObjString(branchName),repfi);
+  
+  if (repfi && !fRepFiList->FindObject(repfi))
+  {
+    // insure we get unique and non-null replicators in this list
+    fRepFiList->Add(repfi);
+  }
+}
+
diff --git a/STEER/AliAODExtension.h b/STEER/AliAODExtension.h
new file mode 100644 (file)
index 0000000..a6bbe54
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef ALIAODEXTENSION_H
+#define ALIAODEXTENSION_H
+
+/* Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id$ */
+
+//-------------------------------------------------------------------------
+//     Support class for AOD extensions. This is created by the user analysis
+//     that requires a separate file for some AOD branches. The name of the 
+//     AliAODExtension object is the file name where the AOD branches will be
+//     stored.
+//     Author: Andrei Gheata, CERN
+//-------------------------------------------------------------------------
+
+#ifndef ROOT_TNamed
+#  include "TNamed.h"
+#endif
+
+class AliAODBranchReplicator;
+class AliAODEvent;
+class TFile;
+class TList;
+class TMap;
+class TTree;
+
+class AliAODExtension : public TNamed {
+  
+public:
+  
+  enum EAliAODExtensionFlags {
+    kFilteredAOD      = BIT(14),
+    kDropUnspecifiedBranches = BIT(15)
+  };
+  
+  AliAODExtension();
+  AliAODExtension(const char* name, const char* title, Bool_t isfilter=kFALSE);
+  virtual ~AliAODExtension();
+  void                 AddBranch(const char* cname, void* addobj);
+  Bool_t               FinishEvent();
+  Int_t                GetNtotal() const         {return fNtotal;}
+  Int_t                GetNpassed() const        {return fNpassed;}
+  const char*          GetOutputFileName() const {return TNamed::GetName();}
+  AliAODEvent*         GetAOD() const            {return fAODEvent;}
+  TTree*               GetTree() const           {return fTreeE;}
+  Bool_t               Init(Option_t *option);
+  Bool_t               IsFilteredAOD() const     {return TObject::TestBit(kFilteredAOD);}
+  Bool_t               IsEventSelected() const   {return fSelected;}
+  void                 SelectEvent(Bool_t flag=kTRUE)  {fSelected = flag;}
+  void                 SetEvent(AliAODEvent* event);
+  void                 SetOutputFileName(const char* fname) {TNamed::SetName(fname);}
+  Bool_t               TerminateIO();
+  
+  void Print(Option_t* opt="") const;
+  
+  // Branches not specified in any FilterBranch call will be dropped by default
+  void DropUnspecifiedBranches() { TObject::SetBit(kDropUnspecifiedBranches); }
+  
+  // Branches not specified in any FilterBranch call will be kept by default
+  void KeepUnspecifiedBranches() { TObject::ResetBit(kDropUnspecifiedBranches); }
+  
+  void FilterBranch(const char* branchName, AliAODBranchReplicator* replicator=0x0);
+  
+  /* Use DisableReferences if and only if the output AOD contains no TRef or TRefArray,
+   otherwise the produced AOD won't be valid.
+   */
+  void DisableReferences() { fEnableReferences=kFALSE; }
+  
+  void EnableReferences() { fEnableReferences=kTRUE; }
+  
+  void AddAODtoTreeUserInfo();
+  
+private:
+  AliAODExtension(const AliAODExtension&);             // Not implemented
+  AliAODExtension& operator=(const AliAODExtension&);  // Not implemented
+  
+private:
+  AliAODEvent             *fAODEvent;               //! Pointer to the AOD event
+  TTree                   *fTreeE;                  //! tree for AOD persistency
+  TFile                   *fFileE;                  //! Output file
+  Int_t                    fNtotal;                 //! Number of processed events
+  Int_t                    fNpassed;                //! Number of events that passed the filter
+  Bool_t                   fSelected;               //! Select current event for filtered AOD's. Made false at event start.
+  
+  TMap*                    fRepFiMap; // which branch(es) to filter out / and or replicate
+  TList*                   fRepFiList; // list of unique filter/replicator
+  
+  Bool_t                   fEnableReferences; // whether or not to enable the TRefTable branch
+  TList*                   fObjectList; //! internal list of which objects to keep 
+  
+  ClassDef(AliAODExtension, 2) // Support for extra AOD branches in a separate AOD file
+};
+
+#endif
index 2c7c4f5..9fdc83b 100644 (file)
@@ -112,16 +112,19 @@ AliAODHandler::AliAODHandler(const char* name, const char* title):
 AliAODHandler::~AliAODHandler() 
 {
  // Destructor.
-  if (fAODEvent) delete fAODEvent;
-  if(fFileA){
+  
+  delete fAODEvent;
+
+  if (fFileA)
+  {
     // is already handled in TerminateIO
     fFileA->Close();
     delete fFileA;
     fTreeA = 0;
   }
-  if (fTreeA) delete fTreeA;
-  if (fExtensions) {fExtensions->Delete(); delete fExtensions;}
-  if (fFilters)    {fFilters->Delete();    delete fFilters;}
+  delete fTreeA;
+  delete fExtensions;
+  delete fFilters;
 }
 
 //______________________________________________________________________________
@@ -167,8 +170,9 @@ Bool_t AliAODHandler::Init(Option_t* opt)
      while ((filteredAOD=(AliAODExtension*)nextf())) {
         filteredAOD->SetEvent(fAODEvent);
         filteredAOD->Init(option);
-     }   
+     }
   }   
+  
   return kTRUE;
 }
 
@@ -425,6 +429,7 @@ void AliAODHandler::StoreMCParticles(){
 Bool_t AliAODHandler::FinishEvent()
 {
   // Fill data structures
+  
   if(fFillAOD && fFillAODRun && fAODEvent){
       fAODEvent->MakeEntriesReferencable();
       fTreeA->BranchRef();
@@ -432,27 +437,34 @@ Bool_t AliAODHandler::FinishEvent()
   }
 
   if (fFillAOD && fFillAODRun) {      
-      if (fExtensions) {
-         TIter next(fExtensions);
-         AliAODExtension *ext;
-         while ((ext=(AliAODExtension*)next())) ext->FinishEvent();
-      }
-      if (fFilters) {   
-         TIter nextf(fFilters);
-         AliAODExtension *ext;
-         while ((ext=(AliAODExtension*)nextf())) {
+    if (fExtensions) {
+      TIter next(fExtensions);
+      AliAODExtension *ext;
+      while ((ext=(AliAODExtension*)next())) ext->FinishEvent();
+    }
+    if (fFilters) {   
+      TIter nextf(fFilters);
+      AliAODExtension *ext;
+      while ((ext=(AliAODExtension*)nextf())) {
              ext->FinishEvent();
-         }  
-      }       
+      }  
+    }       
   }  
-  if (fIsStandard) fAODEvent->ResetStd();
-  if (fAODEvent) {
-    TClonesArray *mcarray = (TClonesArray*)fAODEvent->FindListObject(AliAODMCParticle::StdBranchName()); 
+  
+  if (fIsStandard) 
+  {
+    fAODEvent->ResetStd();    
+  }
+  
+  if (fAODEvent) 
+  {
+    TClonesArray *mcarray = static_cast<TClonesArray*>(fAODEvent->FindListObject(AliAODMCParticle::StdBranchName()));
     if(mcarray) mcarray->Delete();
     
-    AliAODMCHeader *mcHeader = (AliAODMCHeader*)fAODEvent->FindListObject(AliAODMCHeader::StdBranchName()); 
+    AliAODMCHeader *mcHeader = static_cast<AliAODMCHeader*>(fAODEvent->FindListObject(AliAODMCHeader::StdBranchName()));
     if(mcHeader) mcHeader->Reset();
   }
+  
   // Reset AOD replication flag
   fAODIsReplicated = kFALSE;
   return kTRUE;
@@ -463,11 +475,20 @@ Bool_t AliAODHandler::Terminate()
 {
   // Terminate 
   AddAODtoTreeUserInfo();
-  if (fExtensions) {
-    TIter next(fExtensions);
-    AliAODExtension *ext;
-    while ((ext=(AliAODExtension*)next())) ext->GetTree()->GetUserInfo()->Add(ext->GetAOD());
-  }  
+  
+  TIter nextF(fFilters);
+  AliAODExtension *ext;
+  while ((ext=static_cast<AliAODExtension*>(nextF())))
+  {
+    ext->AddAODtoTreeUserInfo();
+  }
+
+  TIter nextE(fExtensions);
+  while ((ext=static_cast<AliAODExtension*>(nextE())))
+  {
+    ext->AddAODtoTreeUserInfo();
+  }
+  
   return kTRUE;
 }
 
@@ -483,16 +504,20 @@ Bool_t AliAODHandler::TerminateIO()
     // When closing the file, the tree is also deleted.
     fTreeA = 0;
   }
-  if (fExtensions) {
-    TIter next(fExtensions);
-    AliAODExtension *ext;
-    while ((ext=(AliAODExtension*)next())) ext->TerminateIO();
+  
+  TIter nextF(fFilters);
+  AliAODExtension *ext;
+  while ((ext=static_cast<AliAODExtension*>(nextF())))
+  {
+    ext->TerminateIO();
   }  
-  if (fFilters) {
-    TIter nextf(fFilters);
-    AliAODExtension *ext;
-    while ((ext=(AliAODExtension*)nextf())) ext->TerminateIO();
+
+  TIter nextE(fExtensions);
+  while ((ext=static_cast<AliAODExtension*>(nextE())))
+  {
+    ext->TerminateIO();
   }  
+  
   return kTRUE;
 }
 
@@ -525,93 +550,100 @@ void AliAODHandler::AddAODtoTreeUserInfo()
 //______________________________________________________________________________
 void AliAODHandler::AddBranch(const char* cname, void* addobj, const char* filename)
 {
-    // Add a new branch to the aod. Added optional filename parameter if the
-    // branch should be written to a separate file.
-    if (strlen(filename)) {
-       AliAODExtension *ext = AddExtension(filename);
-       ext->AddBranch(cname, addobj);
-       return;
-    } else {
-       // Add branch to all filters
-      if (fFilters) {
-         TIter next(fFilters);
-         AliAODExtension *ext;
-         while ((ext=(AliAODExtension*)next())) ext->AddBranch(cname, addobj);
-      }
-    }
-    TDirectory *owd = gDirectory;
-    if (fFileA) {
-      fFileA->cd();
-    }
-    char** apointer = (char**) addobj;
-    TObject* obj = (TObject*) *apointer;
-
-    fAODEvent->AddObject(obj);
-    const Int_t kSplitlevel = 99; // default value in TTree::Branch()
-    const Int_t kBufsize = 32000; // default value in TTree::Branch()
+  // Add a new branch to the aod. Added optional filename parameter if the
+  // branch should be written to a separate file.
+  
+  if (strlen(filename)) 
+  {
+    AliAODExtension *ext = AddExtension(filename);
+    ext->AddBranch(cname, addobj);
+    return;
+  } 
+  
+  // Add branch to all filters
+  // Add branch to all filters
+  if (fFilters) {
+    TIter next(fFilters);
+    AliAODExtension *ext;
+    while ((ext=(AliAODExtension*)next())) ext->AddBranch(cname, addobj);
+  }
+  
+  TDirectory *owd = gDirectory;
+  if (fFileA) 
+  {
+    fFileA->cd();
+  }
 
-    if (!fTreeA->FindBranch(obj->GetName())) {
-      // Do the same as if we book via 
-      // TTree::Branch(TCollection*)
-      
-      fTreeA->Bronch(obj->GetName(), cname, fAODEvent->GetList()->GetObjectRef(obj),
-                    kBufsize, kSplitlevel - 1);
-    }
-    owd->cd();
+  char** apointer = (char**) addobj;
+  TObject* obj = (TObject*) *apointer;
+  
+  fAODEvent->AddObject(obj);
+  
+  const Int_t kSplitlevel = 99; // default value in TTree::Branch()
+  const Int_t kBufsize = 32000; // default value in TTree::Branch()
+  
+  if (!fTreeA->FindBranch(obj->GetName())) 
+  {
+    // Do the same as if we book via 
+    // TTree::Branch(TCollection*)
+    
+    fTreeA->Bronch(obj->GetName(), cname, fAODEvent->GetList()->GetObjectRef(obj),
+                   kBufsize, kSplitlevel - 1);
+  }
+  owd->cd();
 }
 
 //______________________________________________________________________________
 AliAODExtension *AliAODHandler::AddExtension(const char *filename, const char *title)
 {
-// Add an AOD extension with some branches in a different file.
+  // Add an AOD extension with some branches in a different file.
   
-   TString fname(filename);
-   if (!fname.EndsWith(".root")) fname += ".root";
-   if (!fExtensions) {
-      fExtensions = new TObjArray();
-      fExtensions->SetOwner();
-   }   
-   AliAODExtension *ext = (AliAODExtension*)fExtensions->FindObject(fname);
-   if (!ext) {
-      ext = new AliAODExtension(fname, title);
-      fExtensions->Add(ext);
-   }   
-   return ext;
+  TString fname(filename);
+  if (!fname.EndsWith(".root")) fname += ".root";
+  if (!fExtensions) {
+    fExtensions = new TObjArray();
+    fExtensions->SetOwner();
+  }   
+  AliAODExtension *ext = (AliAODExtension*)fExtensions->FindObject(fname);
+  if (!ext) {
+    ext = new AliAODExtension(fname, title);
+    fExtensions->Add(ext);
+  }   
+  return ext;
 }
 
 //______________________________________________________________________________
 AliAODExtension *AliAODHandler::GetExtension(const char *filename) const
 {
-// Getter for AOD extensions via file name.
-   if (!fExtensions) return NULL;
-   return (AliAODExtension*)fExtensions->FindObject(filename);
+  // Getter for AOD extensions via file name.
+  if (!fExtensions) return NULL;
+  return (AliAODExtension*)fExtensions->FindObject(filename);
 }   
 
 //______________________________________________________________________________
 AliAODExtension *AliAODHandler::AddFilteredAOD(const char *filename, const char *filtername)
 {
-// Add an AOD extension that can write only AOD events that pass a user filter.
-   if (!fFilters) {
-      fFilters = new TObjArray();
-      fFilters->SetOwner();
-   } 
-   AliAODExtension *filter = (AliAODExtension*)fFilters->FindObject(filename);
-   if (!filter) {
-      filter = new AliAODExtension(filename, filtername, kTRUE);
-      fFilters->Add(filter);
-   }
-   return filter;
+  // Add an AOD extension that can write only AOD events that pass a user filter.
+  if (!fFilters) {
+    fFilters = new TObjArray();
+    fFilters->SetOwner();
+  } 
+  AliAODExtension *filter = (AliAODExtension*)fFilters->FindObject(filename);
+  if (!filter) {
+    filter = new AliAODExtension(filename, filtername, kTRUE);
+    fFilters->Add(filter);
+  }
+  return filter;
 }      
 
 //______________________________________________________________________________
 AliAODExtension *AliAODHandler::GetFilteredAOD(const char *filename) const
 {
-// Getter for AOD filters via file name.
-   if (!fFilters) return NULL;
-   return (AliAODExtension*)fFilters->FindObject(filename);
+  // Getter for AOD filters via file name.
+  if (!fFilters) return NULL;
+  return (AliAODExtension*)fFilters->FindObject(filename);
 }   
-   
+
 //______________________________________________________________________________
 void AliAODHandler::SetOutputFileName(const char* fname)
 {
@@ -629,25 +661,35 @@ const char *AliAODHandler::GetOutputFileName()
 //______________________________________________________________________________
 const char *AliAODHandler::GetExtraOutputs() const
 {
-// Get extra outputs as a string separated by commas.
-   static TString eoutputs;
-   eoutputs = "";
-   TObject *obj;
-   if (fExtensions) {
-      TIter next1(fExtensions);
-      while ((obj=next1())) {
-         if (!eoutputs.IsNull()) eoutputs += ",";
-         eoutputs += obj->GetName();
-      }
-   }
-   if (fFilters) {
-      TIter next2(fFilters);
-      while ((obj=next2())) {
-         if (!eoutputs.IsNull()) eoutputs += ",";
-         eoutputs += obj->GetName();
-      }
-   }
-   return eoutputs.Data();
+  // Get extra outputs as a string separated by commas.
+  static TString eoutputs;
+  eoutputs = "";
+  TObject *obj;
+  if (fExtensions) {
+    TIter next1(fExtensions);
+    while ((obj=next1())) {
+      if (!eoutputs.IsNull()) eoutputs += ",";
+      eoutputs += obj->GetName();
+    }
+  }
+  if (fFilters) {
+    TIter next2(fFilters);
+    while ((obj=next2())) {
+      if (!eoutputs.IsNull()) eoutputs += ",";
+      eoutputs += obj->GetName();
+    }
+  }
+  return eoutputs.Data();
+}
+
+//______________________________________________________________________________
+Bool_t AliAODHandler::HasExtensions() const
+{
+  // Whether or not we manage extensions
+  
+  if ( fExtensions && fExtensions->GetEntries()>0 ) return kTRUE;
+  
+  return kFALSE;
 }
 
 //______________________________________________________________________________
@@ -686,386 +728,3 @@ void  AliAODHandler::SetMCHeaderInfo(AliAODMCHeader *mcHeader,AliGenEventHeader
 
 }
 
-ClassImp(AliAODExtension)
-
-//-------------------------------------------------------------------------
-//     Support class for AOD extensions. This is created by the user analysis
-//     that requires a separate file for some AOD branches. The name of the 
-//     AliAODExtension object is the file name where the AOD branches will be
-//     stored.
-//-------------------------------------------------------------------------
-
-//______________________________________________________________________________
-AliAODExtension::AliAODExtension() : TNamed(), 
-fAODEvent(0), fTreeE(0), fFileE(0), fNtotal(0), fNpassed(0), 
-fSelected(kFALSE), fRepFiMap(0x0), fRepFiList(0x0), fEnableReferences(kTRUE), fObjectList(0x0)
-{
-  // default ctor
-}
-
-//______________________________________________________________________________
-AliAODExtension::AliAODExtension(const char* name, const char* title, Bool_t isfilter)
-                :TNamed(name,title), 
-                 fAODEvent(0), 
-                 fTreeE(0), 
-                 fFileE(0), 
-                 fNtotal(0), 
-                 fNpassed(0),
-                 fSelected(kFALSE),
-fRepFiMap(0x0),
-fRepFiList(0x0),
-fEnableReferences(kTRUE),
-fObjectList(0x0)
-{
-// Constructor.
-  if (isfilter) {
-    TObject::SetBit(kFilteredAOD);
-    printf("####### Added AOD filter %s\n", name);
-  } else printf("####### Added AOD extension %s\n", name);
-  KeepUnspecifiedBranches();
-}   
-
-//______________________________________________________________________________
-AliAODExtension::~AliAODExtension()
-{
-// Destructor.
-  if(fFileE){
-    // is already handled in TerminateIO
-    fFileE->Close();
-    delete fFileE;
-    fTreeE = 0;
-    fAODEvent = 0;
-  }
-  if (fTreeE) delete fTreeE;
-  if (fRepFiMap) fRepFiMap->DeleteAll();
-  delete fRepFiMap; // the map is owner
-  delete fRepFiList; // the list is not
-  delete fObjectList; // not owner
-}
-
-//______________________________________________________________________________
-void AliAODExtension::AddBranch(const char* cname, void* addobj)
-{
-    // Add a new branch to the aod 
-//    if (IsFilteredAOD()) {
-//       Error("AddBranch", "Not allowed to add branched to filtered AOD's.");
-//       return;
-//    }   
-
-  AliCodeTimerAuto(GetName(),0);
-
-  if (!fAODEvent) {
-    char type[20];
-    gROOT->ProcessLine(Form("TString s_tmp; AliAnalysisManager::GetAnalysisManager()->GetAnalysisTypeString(s_tmp); sprintf((char*)%p, \"%%s\", s_tmp.Data());", type));
-    Init(type);
-  }
-  TDirectory *owd = gDirectory;
-  if (fFileE) {
-    fFileE->cd();
-  }
-  char** apointer = (char**) addobj;
-  TObject* obj = (TObject*) *apointer;
-  
-  fAODEvent->AddObject(obj);
-  
-  TString bname(obj->GetName());
-  
-  if (!fTreeE->FindBranch(bname.Data())) 
-  {
-    Bool_t acceptAdd(kTRUE);
-    
-    if ( TestBit(kDropUnspecifiedBranches) )
-    {
-      // check that this branch is in our list of specified ones...
-      // otherwise do not add it !
-      TIter next(fRepFiMap);
-      TObjString* p;
-      
-      acceptAdd=kFALSE;
-      
-      while ( ( p = static_cast<TObjString*>(next()) ) && !acceptAdd )
-      {
-        if ( p->String() == bname ) acceptAdd=kTRUE;
-      }
-    }
-    
-    if ( acceptAdd ) 
-    {
-      // Do the same as if we book via 
-      // TTree::Branch(TCollection*)
-
-      const Int_t kSplitlevel = 99; // default value in TTree::Branch()
-      const Int_t kBufsize = 32000; // default value in TTree::Branch()
-            
-      fTreeE->Bronch(bname.Data(), cname, fAODEvent->GetList()->GetObjectRef(obj),
-                     kBufsize, kSplitlevel - 1);
-    }
-  }
-  owd->cd();
-}
-
-//______________________________________________________________________________
-Bool_t AliAODExtension::FinishEvent()
-{
-// Fill current event.
-  fNtotal++;
-  if (!IsFilteredAOD()) {
-    fAODEvent->MakeEntriesReferencable();
-    fTreeE->Fill();
-    return kTRUE;
-  }  
-  // Filtered AOD. Fill only if event is selected.
-  if (!fSelected) return kTRUE;
-
-  TIter next(fRepFiList);
-  
-  AliAODBranchReplicator* repfi;
-
-  while ( ( repfi = static_cast<AliAODBranchReplicator*>(next()) ) )
-  {
-    repfi->ReplicateAndFilter(*fAODEvent);
-  }
-  fNpassed++;
-  fTreeE->Fill();
-  fSelected = kFALSE; // so that next event will not be selected unless demanded
-  return kTRUE;
-}  
-
-//______________________________________________________________________________
-Bool_t AliAODExtension::Init(Option_t *option)
-{
-// Initialize IO.
-  AliCodeTimerAuto(GetName(),0);
-  
-  if(!fAODEvent) 
-  {
-    fAODEvent = new AliAODEvent();    
-  }
-  
-  TDirectory *owd = gDirectory;
-  TString opt(option);
-  opt.ToLower();
-  if (opt.Contains("proof")) {
-    // proof
-    // Merging via files. Need to access analysis manager via interpreter.
-    gROOT->ProcessLine(Form("AliAnalysisDataContainer *c_common_out = AliAnalysisManager::GetAnalysisManager()->GetCommonOutputContainer();"));
-    gROOT->ProcessLine(Form("AliAnalysisManager::GetAnalysisManager()->OpenProofFile(c_common_out, \"RECREATE\", \"%s\");", fName.Data()));
-    fFileE = gFile;
-  } else {
-    fFileE = new TFile(GetName(), "RECREATE");
-  }  
-  fTreeE = new TTree("aodTree", "AliAOD tree");
-  
-  delete fObjectList;
-  fObjectList = new TList;
-  fObjectList->SetOwner(kFALSE); // be explicit we're not the owner...
-  TIter next(fAODEvent->GetList());
-  TObject* o;
-  
-  while ( ( o = next() ) )
-  {
-    Bool_t mustKeep(kFALSE);
-    
-    TString test(o->ClassName());
-    test.ToUpper();
-    if (test.Contains("HEADER"))
-    {
-      // do not allow to drop header branch
-      mustKeep=kTRUE;
-    }
-    
-    if ( fRepFiMap && !mustKeep )
-    {
-      TObject* specified = fRepFiMap->FindObject(o->GetName());
-      if (specified)
-      {
-        AliAODBranchReplicator* repfi = dynamic_cast<AliAODBranchReplicator*>(fRepFiMap->GetValue(o->GetName()));
-        if ( repfi ) 
-        {        
-          TList* replicatedList = repfi->GetList();
-          if (replicatedList)
-          {
-            AliAODEvent::AssignIDtoCollection(replicatedList);
-            TIter nextRep(replicatedList);
-            TObject* objRep;
-            while ( ( objRep = nextRep() ) )
-            {
-              if (!fObjectList->FindObject(objRep))
-              {
-                fObjectList->Add(objRep);
-              }
-            }
-          }
-          else
-          {
-            AliError(Form("replicatedList from %s is null !",repfi->GetName()));
-          }
-        }
-      }
-      else
-      {
-        if ( !TestBit(kDropUnspecifiedBranches) ) 
-        {
-          // object o will be transmitted to the output AOD, unchanged
-          fObjectList->Add(o);
-        }
-      }
-    } 
-    else
-    {
-      if ( mustKeep || !TestBit(kDropUnspecifiedBranches) )
-      {
-        // object o will be transmitted to the output AOD, unchanged
-        fObjectList->Add(o);
-      }
-    }
-  }
-
-  next.Reset();
-  
-  while ( ( o = next() ) )
-  {
-    TObject* out = fObjectList->FindObject(o->GetName());
-    
-    TString status;
-    
-    if ( out != o && out ) 
-    {
-      status = "REPLICATED";      
-    }
-    else if ( out ) 
-    {
-      status = "COPIED AS IS";      
-    }
-    else 
-    {
-      status = "DROPPED";          
-    }
-    
-    AliInfo(Form("OBJECT IN %20s %p -> OUT %p %s",
-                 o->GetName(),o,out,status.Data()));
-  }
-
-  if (fEnableReferences) fTreeE->BranchRef();
-
-  fTreeE->Branch(fObjectList);
-    
-  owd->cd();
-  
-  return kTRUE;
-}
-
-//______________________________________________________________________________
-void AliAODExtension::Print(Option_t* opt) const
-{
-  // Print info about this extension
-  
-  cout << opt << Form("AliAODExtension - %s - %s",GetName(),GetTitle()) << endl;
-  if ( !fEnableReferences ) 
-  {
-    cout << opt << opt << "References are disabled ! Hope you know what you are doing !" << endl;
-  }
-  if ( TestBit(kDropUnspecifiedBranches) )
-  {
-    cout << opt << opt << "All branches not explicitely specified will be dropped" << endl;
-  }
-  
-  TIter next(fRepFiMap);
-  TObjString* s;
-  
-  TString skipped;
-  
-  while ( ( s = static_cast<TObjString*>(next()) ) )
-  {
-    AliAODBranchReplicator* br = static_cast<AliAODBranchReplicator*>(fRepFiMap->GetValue(s->String().Data()));
-    if ( !br ) 
-    {
-      skipped += s->String();
-      skipped += ' ';
-    }
-  }
-
-    
-  if ( skipped.Length() )
-  {
-    cout << opt << opt << "Specified branches that will be skipped altogether : " << skipped.Data() << endl;
-  }
-  
-  next.Reset();
-  
-  while ( ( s = static_cast<TObjString*>(next()) ) )
-  {
-    AliAODBranchReplicator* br = static_cast<AliAODBranchReplicator*>(fRepFiMap->GetValue(s->String().Data()));
-    
-    if (br)
-    {
-      cout << opt << opt << "Branch " << s->String() 
-      << " will be filtered by class " << br->ClassName() << endl;
-    }
-  }
-}
-
-//______________________________________________________________________________
-void AliAODExtension::SetEvent(AliAODEvent *event)
-{
-// Connects to an external event
-   if (!IsFilteredAOD()) {
-      Error("SetEvent", "Not allowed to set external event for filtered AOD's");   
-      return;
-   }
-   // Use the copy constructor or assignment operator to synchronize with external event.
-//   AliAODEvent &other = *event;
-//   if (!fAODEvent)     fAODEvent = new AliAODEvent(other);
-//   else if (fSelected) *fAODEvent = other;
-   fAODEvent = event;
-}
-   
-//______________________________________________________________________________
-Bool_t AliAODExtension::TerminateIO()
-{
-  // Terminate IO
-  if (TObject::TestBit(kFilteredAOD))
-    printf("AOD Filter %s: events processed: %d   passed: %d\n", GetName(), fNtotal, fNpassed);
-  else
-    printf("AOD extension %s: events processed: %d\n", GetName(), fNtotal);
-  if (fFileE) {
-    fFileE->Write();
-    fFileE->Close();
-    delete fFileE;
-    fFileE = 0;
-    fTreeE = 0;
-    fAODEvent = 0;
-  }
-  return kTRUE;
-}
-
-//______________________________________________________________________________
-void AliAODExtension::FilterBranch(const char* branchName, AliAODBranchReplicator* repfi)
-{
-  // Specify a filter/replicator for a given branch
-  //
-  // If repfi=0x0, this will disable the branch (in the output) completely.
-  //
-  // repfi is adopted by this class, i.e. user should not delete it.
-  //
-  // WARNING : branch name must be exact.
-  //
-  // See also the documentation for AliAODBranchReplicator class.
-  //
-  
-  if (!fRepFiMap)
-  {
-    fRepFiMap = new TMap;
-    fRepFiMap->SetOwnerKeyValue(kTRUE,kTRUE);
-    fRepFiList = new TList;
-    fRepFiList->SetOwner(kFALSE);
-  }
-  
-  fRepFiMap->Add(new TObjString(branchName),repfi);
-  
-  if (repfi && !fRepFiList->FindObject(repfi))
-  {
-    // insure we get unique and non-null replicators in this list
-    fRepFiList->Add(repfi);
-  }
-}
index 9056334..4534108 100644 (file)
@@ -18,7 +18,7 @@ class TTree;
 class TObjArray;
 class AliMCEventHandler;
 class AliAODMCHeader;
-class AliAODExtension;
+#include "AliAODExtension.h" // should be a forward declaration : class AliAODExtension;
 class AliGenEventHeader;
 class TMap;
 class AliAnalysisFilter;
@@ -71,8 +71,10 @@ class AliAODHandler : public AliVEventHandler {
     void                 FillTree();
     void                 AddAODtoTreeUserInfo();
     void                 AddBranch(const char* cname, void* addobj, const char *fname="");
+  
     AliAODExtension*     AddExtension(const char *filename, const char *title="");                 
     AliAODExtension*     AddFilteredAOD(const char *filename, const char *filtername);
+//    AliAODExtension*     FindExtensionContainingBranch(const char* bname) const;
     Bool_t               IsStandard()                         const {return fIsStandard;}
     Bool_t               GetFillAOD()                         const {return fFillAOD;} 
     Bool_t               NeedsHeaderReplication()             const {return  fNeedsHeaderReplication;}
@@ -93,14 +95,16 @@ class AliAODHandler : public AliVEventHandler {
     void                 SetMCEventHandler(AliMCEventHandler* mcH) {fMCEventH = mcH;} // For internal use
     void StoreMCParticles(); // Store MC particles, only to be called from AliAnalyisTaskMCParticleFilter
 
+  Bool_t HasExtensions() const;
+  
   void Print(Option_t* opt="") const;
   
  private:
-    void SetMCHeaderInfo(AliAODMCHeader *mcHeader,AliGenEventHeader *genHeader); // Utility function t catch different types of eventheaders
-    AliAODHandler(const AliAODHandler&);             // Not implemented
-    AliAODHandler& operator=(const AliAODHandler&);  // Not implemented
+  void SetMCHeaderInfo(AliAODMCHeader *mcHeader,AliGenEventHeader *genHeader); // Utility function t catch different types of eventheaders
+  AliAODHandler(const AliAODHandler&);             // Not implemented
+  AliAODHandler& operator=(const AliAODHandler&);  // Not implemented
   void PrintExtensions(const TObjArray& array) const;
-  
+
  private:
     Bool_t                   fIsStandard;                         // Flag for standard aod creation
     Bool_t                   fFillAOD;                            // Flag for filling of the AOD tree at the end (all or nothing evt by evt)
@@ -125,81 +129,8 @@ class AliAODHandler : public AliVEventHandler {
     TString                  fFileName;               //  Output file name
     TObjArray               *fExtensions;             //  List of extensions
     TObjArray               *fFilters;                //  List of filtered AOD's
-    ClassDef(AliAODHandler, 6)
-};
-
-//-------------------------------------------------------------------------
-//     Support class for AOD extensions. This is created by the user analysis
-//     that requires a separate file for some AOD branches. The name of the 
-//     AliAODExtension object is the file name where the AOD branches will be
-//     stored.
-//     Author: Andrei Gheata, CERN
-//-------------------------------------------------------------------------
-
-class AliAODBranchReplicator;
-
-class AliAODExtension : public TNamed {
-
-public:
 
-enum EAliAODExtensionFlags {
-   kFilteredAOD      = BIT(14),
-   kDropUnspecifiedBranches = BIT(15)
+  ClassDef(AliAODHandler, 6)
 };
-    
-  AliAODExtension();
-    AliAODExtension(const char* name, const char* title, Bool_t isfilter=kFALSE);
-    virtual ~AliAODExtension();
-    void                 AddBranch(const char* cname, void* addobj);
-    Bool_t               FinishEvent();
-    Int_t                GetNtotal() const         {return fNtotal;}
-    Int_t                GetNpassed() const        {return fNpassed;}
-    const char*          GetOutputFileName() const {return TNamed::GetName();}
-    AliAODEvent*         GetAOD() const            {return fAODEvent;}
-    TTree*               GetTree() const           {return fTreeE;}
-    Bool_t               Init(Option_t *option);
-    Bool_t               IsFilteredAOD() const     {return TObject::TestBit(kFilteredAOD);}
-    Bool_t               IsEventSelected() const   {return fSelected;}
-    void                 SelectEvent(Bool_t flag=kTRUE)  {fSelected = flag;}
-    void                 SetEvent(AliAODEvent *event);
-    void                 SetOutputFileName(const char* fname) {TNamed::SetName(fname);}
-    Bool_t               TerminateIO();
 
-  void Print(Option_t* opt="") const;
-  
-  // Branches not specified in any FilterBranch call will be dropped by default
-  void DropUnspecifiedBranches() { TObject::SetBit(kDropUnspecifiedBranches); }
-    
-  // Branches not specified in any FilterBranch call will be kept by default
-  void KeepUnspecifiedBranches() { TObject::ResetBit(kDropUnspecifiedBranches); }
-    
-  void FilterBranch(const char* branchName, AliAODBranchReplicator* replicator=0x0);
-
-  /* Use DisableReferences if and only if the output AOD contains no TRef or TRefArray,
-   otherwise the produced AOD won't be valid.
-   */
-  void DisableReferences() { fEnableReferences=kFALSE; }
-  
-  void EnableReferences() { fEnableReferences=kTRUE; }
-  
- private:
-    AliAODExtension(const AliAODExtension&);             // Not implemented
-    AliAODExtension& operator=(const AliAODExtension&);  // Not implemented
-
- private:
-    AliAODEvent             *fAODEvent;               //! Pointer to the AOD event
-    TTree                   *fTreeE;                  //! tree for AOD persistency
-    TFile                   *fFileE;                  //! Output file
-    Int_t                    fNtotal;                 //! Number of processed events
-    Int_t                    fNpassed;                //! Number of events that passed the filter
-    Bool_t                   fSelected;               //! Select current event for filtered AOD's. Made false at event start.
-
-    TMap*                    fRepFiMap; // which branch(es) to filter out / and or replicate
-    TList*                   fRepFiList; // list of unique filter/replicator
-  
-    Bool_t                   fEnableReferences; // whether or not to enable the TRefTable branch
-    TList*                   fObjectList; //! internal list of which objects to keep 
-  
-  ClassDef(AliAODExtension, 2) // Support for extra AOD branches in a separate AOD file
-};
 #endif
index dd01e1e..f0b9178 100644 (file)
@@ -1,4 +1,4 @@
-set ( SRCS  AliAODEvent.cxx AliAODHeader.cxx AliAODTrack.cxx AliAODPid.cxx AliAODVertex.cxx AliAODCluster.cxx AliAODCaloCluster.cxx AliAODPmdCluster.cxx AliAODFmdCluster.cxx AliAODJet.cxx AliAODJetEventBackground.cxx AliAODPhoton.cxx AliAODRedCov.cxx AliAODRecoDecay.cxx AliAODHandler.cxx AliAODTracklets.cxx AliAODTagCreator.cxx AliAODv0.cxx AliAODcascade.cxx AliAODCaloCells.cxx AliAODInputHandler.cxx AliAODDiJet.cxx AliAODMCParticle.cxx AliAODMCHeader.cxx AliAODPWG4Particle.cxx AliAODPWG4ParticleCorrelation.cxx AliAODDimuon.cxx AliAODpidUtil.cxx AliAODCentrality.cxx AliAODBranchReplicator.cxx AliAODVZERO.cxx)
+set ( SRCS  AliAODEvent.cxx AliAODHeader.cxx AliAODTrack.cxx AliAODPid.cxx AliAODVertex.cxx AliAODCluster.cxx AliAODCaloCluster.cxx AliAODPmdCluster.cxx AliAODFmdCluster.cxx AliAODJet.cxx AliAODJetEventBackground.cxx AliAODPhoton.cxx AliAODRedCov.cxx AliAODRecoDecay.cxx AliAODExtension.cxx AliAODHandler.cxx AliAODTracklets.cxx AliAODTagCreator.cxx AliAODv0.cxx AliAODcascade.cxx AliAODCaloCells.cxx AliAODInputHandler.cxx AliAODDiJet.cxx AliAODMCParticle.cxx AliAODMCHeader.cxx AliAODPWG4Particle.cxx AliAODPWG4ParticleCorrelation.cxx AliAODDimuon.cxx AliAODpidUtil.cxx AliAODCentrality.cxx AliAODBranchReplicator.cxx AliAODVZERO.cxx)
 
 string(REPLACE ".cxx" ".h" HDRS "${SRCS}")