New developments of the analysis framework - selectorised version of the manager...
authorpanos <panos@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 22 Nov 2006 14:59:58 +0000 (14:59 +0000)
committerpanos <panos@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 22 Nov 2006 14:59:58 +0000 (14:59 +0000)
13 files changed:
ANALYSIS/AliAnalysisDataContainer.cxx
ANALYSIS/AliAnalysisDataContainer.h
ANALYSIS/AliAnalysisDataSlot.cxx
ANALYSIS/AliAnalysisDataSlot.h
ANALYSIS/AliAnalysisManager.cxx
ANALYSIS/AliAnalysisManager.h
ANALYSIS/AliAnalysisRLContainer.cxx
ANALYSIS/AliAnalysisTask.cxx
ANALYSIS/AliAnalysisTask.h
ANALYSIS/AnalysisExtraLinkDef.h [new file with mode: 0644]
ANALYSIS/AnalysisTaskLinkDef.h
ANALYSIS/libANALYSIS_EXTRA.pkg [new file with mode: 0644]
ANALYSIS/libANALYSIS_NEW.pkg

index 1326ebd..0238858 100644 (file)
@@ -57,7 +57,7 @@ ClassImp(AliAnalysisDataContainer)
 AliAnalysisDataContainer::AliAnalysisDataContainer() : TNamed(),
                           fDataReady(kFALSE),
                           fOwnedData(kFALSE),
-                          fFileName(),
+                          fFile(NULL),
                           fData(NULL),
                           fType(NULL),
                           fProducer(NULL),
@@ -71,7 +71,7 @@ AliAnalysisDataContainer::AliAnalysisDataContainer(const char *name, TClass *typ
                          :TNamed(name,""),
                           fDataReady(kFALSE),
                           fOwnedData(kTRUE),
-                          fFileName(),
+                          fFile(NULL),
                           fData(NULL),
                           fType(type),
                           fProducer(NULL),
@@ -85,7 +85,7 @@ AliAnalysisDataContainer::AliAnalysisDataContainer(const AliAnalysisDataContaine
                          :TNamed(cont),
                           fDataReady(cont.fDataReady),
                           fOwnedData(kFALSE),
-                          fFileName(cont.fFileName),
+                          fFile(cont.fFile),
                           fData(cont.fData),
                           fType(cont.fType),
                           fProducer(cont.fProducer),
@@ -105,6 +105,10 @@ AliAnalysisDataContainer::~AliAnalysisDataContainer()
 // Destructor. Deletes data ! (What happens if data is a container ???)
    if (fData && fOwnedData) delete fData;
    if (fConsumers) delete fConsumers;
+   if (fFile) {
+      fFile->Close();
+      delete fFile;
+   }   
 }
 
 //______________________________________________________________________________
@@ -115,7 +119,7 @@ AliAnalysisDataContainer &AliAnalysisDataContainer::operator=(const AliAnalysisD
       TNamed::operator=(cont);
       fDataReady = cont.fDataReady;
       fOwnedData = kFALSE;  // !!! Data owned by cont.
-      fFileName = cont.fFileName;
+      fFile = cont.fFile;
       fData = cont.fData;
       fType = cont.fType;
       fProducer = cont.fProducer;
@@ -129,22 +133,22 @@ AliAnalysisDataContainer &AliAnalysisDataContainer::operator=(const AliAnalysisD
 }      
 
 //______________________________________________________________________________
-Bool_t AliAnalysisDataContainer::SetData(TObject *data, Option_t *option)
+Bool_t AliAnalysisDataContainer::SetData(TObject *data, Option_t *)
 {
 // Set the data as READY only if it was published by the producer.
-// If option is not empty the data will be saved in the file fFileName and option
-// describes the method to opent the file: NEW/CREATE, RECREATE, UPDATE
    // If there is no producer declared, this is a top level container.
    AliAnalysisTask *task;
+   Bool_t init = kFALSE;
    Int_t i, nc;
    if (!fProducer) {
+      if (data != fData) init = kTRUE;
       fData = data;
       fDataReady = kTRUE;
       if (fConsumers) {
          nc = fConsumers->GetEntriesFast();
          for (i=0; i<nc; i++) {
             task = (AliAnalysisTask*)fConsumers->At(i);
-            task->CheckNotify();
+            task->CheckNotify(init);
          }
       }      
       return kTRUE;
@@ -153,17 +157,6 @@ Bool_t AliAnalysisDataContainer::SetData(TObject *data, Option_t *option)
    if (fProducer->GetPublishedData()==data) {
       fData = data;
       fDataReady = kTRUE;
-      if (strlen(option)) {
-         if (!fFileName.Length()) {
-            AliWarning(Form("Cannot write data since file name for container %s was not set", GetName()));
-            return kFALSE;
-         }
-         TFile *f = new TFile(fFileName.Data(), option);
-         if (!f->IsZombie()) {
-            fData->Write();
-            f->Write();
-         }   
-      }
       if (fConsumers) {
          nc = fConsumers->GetEntriesFast();
          for (i=0; i<nc; i++) {
@@ -180,27 +173,48 @@ Bool_t AliAnalysisDataContainer::SetData(TObject *data, Option_t *option)
 }
 
 //______________________________________________________________________________
-void AliAnalysisDataContainer::SetFileName(const char *name)
+void AliAnalysisDataContainer::OpenFile(const char *name, Option_t *option)
 {
-// Data will be written to this file if it is set using SetData(data, option)
+// Data will be written to this file at the end of processing.
 // Option represent the way the file is accessed: NEW, APPEND, ...
-   fFileName = name;
+   if (fFile) {
+      fFile->Close();
+      delete fFile;
+   }
+   fFile =  new TFile(name, option);
+   if (fFile->IsZombie()) {
+      AliError(Form("Cannot open file %s with option %s",name,option));
+      fFile = 0;
+   }   
 }   
 
 //______________________________________________________________________________
+void AliAnalysisDataContainer::WriteData()
+{
+// Write data to the file.
+   if (fFile) {
+      TDirectory *cursav = gDirectory;
+      fFile->cd();
+      fData->Write();
+//      fFile->Write();
+      if (cursav) cursav->cd();
+   }   
+}
+
+//______________________________________________________________________________
 void AliAnalysisDataContainer::GetEntry(Long64_t ientry)
 {
 // If data is ready and derives from TTree or from TBranch, this will get the
 // requested entry in memory if not already loaded.
    if (!fDataReady) return;
-   Bool_t is_tree = fType->InheritsFrom(TTree::Class());
-   if (is_tree) {
+   Bool_t istree = fType->InheritsFrom(TTree::Class());
+   if (istree) {
       TTree *tree = (TTree*)fData;
       if (tree->GetReadEntry() != ientry) tree->GetEntry(ientry);
       return;
    }   
-   Bool_t is_branch = fType->InheritsFrom(TBranch::Class());
-   if (is_branch) {
+   Bool_t isbranch = fType->InheritsFrom(TBranch::Class());
+   if (isbranch) {
       TBranch *branch = (TBranch*)fData;
       if (branch->GetReadEntry() != ientry) branch->GetEntry(ientry);
       return;
index 4c49ca2..2bdcd5b 100644 (file)
@@ -20,7 +20,7 @@
 #endif
 
 class TClass;
-class TString;
+class TFile;
 class TObjArray;
 class AliAnalysisTask;
 class AliESD;
@@ -47,9 +47,10 @@ enum ENotifyMessage {
    TObjArray                *GetConsumers() const {return fConsumers;}
    virtual void              GetEntry(Long64_t ientry);
    // Setters
+   void                      ResetDataReady()     {fDataReady = kFALSE;}
    virtual Bool_t            SetData(TObject *data, Option_t *option="");
    void                      SetDataOwned(Bool_t flag) {fOwnedData = flag;}
-   void                      SetFileName(const char *name);
+   void                      OpenFile(const char *name, Option_t *option="RECREATE");
    void                      SetProducer(AliAnalysisTask *prod, Int_t islot);
    void                      AddConsumer(AliAnalysisTask *cons, Int_t islot);
    void                      DeleteData();
@@ -63,11 +64,12 @@ enum ENotifyMessage {
    virtual void              NotifyChange(ENotifyMessage /*type*/) {;}
    // Print connected tasks/status
    void                      PrintContainer(Option_t *option="all", Int_t indent=0) const;
+   void                      WriteData();
    
 protected:
    Bool_t                    fDataReady;  // Flag that data is ready
    Bool_t                    fOwnedData;  // Flag data ownership
-   TString                   fFileName;   // Name of the file that will store the data if requested
+   TFile                    *fFile;       // File storing the data
    TObject                  *fData;       // Contained data
    TClass                   *fType;       // Type of contained data
    AliAnalysisTask          *fProducer;   // Analysis task to which the slot belongs
index ffbc848..a083d95 100644 (file)
@@ -40,6 +40,7 @@
 //==============================================================================
 
 #include "TClass.h"
+#include "TTree.h"
 #include "AliLog.h"
 
 #include "AliAnalysisDataSlot.h"
@@ -77,6 +78,45 @@ Bool_t AliAnalysisDataSlot::ConnectContainer(AliAnalysisDataContainer *cont)
 }   
 
 //______________________________________________________________________________
+void *AliAnalysisDataSlot::GetBranchAddress(const char *branchname) const
+{
+// Retrieve the address for a given branch. One should always test this before
+// using SetBranchAddress because the address gets set by the first caller.
+// Call this in MyTask::Init()
+   if (!fType->InheritsFrom(TTree::Class())) {
+      AliFatal(Form("Cannot call GetBranchAddress() for data slot of task %s not pointing to tree-type data", fParent->GetName()));
+      return NULL;
+   }
+   if (!IsDataReady()) {
+      AliFatal(Form("Cannot call GetBranchAddress() for data slot of task %s while data is not ready", fParent->GetName()));
+      return NULL;
+   }
+   TTree *tree = (TTree*)GetData();
+   TBranch *br = tree->GetBranch(branchname);
+   if (!br) {   
+      AliFatal(Form("Branch %s not found in tree %s as input of task %s...", 
+               branchname, tree->GetName(), fParent->GetName()));
+      return NULL;
+   }
+   return br->GetAddress();
+}   
+
+//______________________________________________________________________________
+Bool_t AliAnalysisDataSlot::SetBranchAddress(const char *branchname, void *address)
+{
+// Set a branch address for input tree. To be called during MyTask::Init()
+// only if GetBranchAddress() returns a NULL pointer for a tree-type slot.
+   if (GetBranchAddress(branchname)) {
+      AliError(Form("Branch address for %s already set by other task. Call first GetBranchAddress() in %s::Init()",
+               branchname, fParent->GetName()));
+      return kFALSE;
+   }
+   TTree *tree = (TTree*)GetData();
+   tree->SetBranchAddress(branchname, address);
+   return kTRUE;
+}   
+      
+//______________________________________________________________________________
 TObject *AliAnalysisDataSlot::GetData() const
 {
 // Retreives the data from the container if it is ready.
index b0513e8..25cb7ca 100644 (file)
@@ -34,6 +34,8 @@ public:
    // Connect some container to the slot
    Bool_t                    ConnectContainer(AliAnalysisDataContainer *cont);
    // Getters
+   void                     *GetBranchAddress(const char *branch) const;
+   Bool_t                    SetBranchAddress(const char *branch, void *address);
    TClass                   *GetType() const      {return fType;}
    AliAnalysisTask          *GetParent() const    {return fParent;}
    AliAnalysisDataContainer *GetContainer() const {return fContainer;}
index aa59c14..581d8ea 100644 (file)
@@ -26,6 +26,8 @@
 //==============================================================================
 
 #include "TClass.h"
+#include "TFile.h"
+#include "TTree.h"
 #include "AliLog.h"
 
 #include "AliAnalysisManager.h"
@@ -37,6 +39,7 @@ ClassImp(AliAnalysisManager)
 
 //______________________________________________________________________________
 AliAnalysisManager::AliAnalysisManager() : TSelector(),
+                    fTree(NULL),
                     fInitOK(kFALSE),
                     fContainers(NULL),
                     fInputs(NULL),
@@ -61,6 +64,7 @@ AliAnalysisManager::AliAnalysisManager() : TSelector(),
 //______________________________________________________________________________
 AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
                    :TSelector(other),
+                    fTree(NULL),
                     fInitOK(kFALSE),
                     fContainers(NULL),
                     fInputs(NULL),
@@ -86,6 +90,7 @@ AliAnalysisManager& AliAnalysisManager::operator=(const AliAnalysisManager& othe
 // Assignment
    if (&other != this) {
       TSelector::operator=(other);
+      fTree       = other.fTree;
       fInitOK     = other.fInitOK;
       fContainers = new TObjArray(*other.fContainers);
       fInputs     = new TObjArray(*other.fInputs);
@@ -110,35 +115,69 @@ AliAnalysisManager::~AliAnalysisManager()
    if (fTopTasks) delete fTopTasks;
    if (fZombies) delete fZombies;
 }
-
 //______________________________________________________________________________
-void AliAnalysisManager::Init(TTree */*tree*/)
+Int_t AliAnalysisManager::GetEntry(Long64_t entry, Int_t getall)
+{
+// Read one entry of the tree or a whole branch.
+   return fTree ? fTree->GetTree()->GetEntry(entry, getall) : 0;
+}
+   
+//______________________________________________________________________________
+void AliAnalysisManager::Init(TTree *tree)
 {
   // The Init() function is called when the selector needs to initialize
   // a new tree or chain. Typically here the branch addresses of the tree
   // will be set. It is normaly not necessary to make changes to the
   // generated code, but the routine can be extended by the user if needed.
   // Init() will be called many times when running with PROOF.
+   printf("AliAnalysisManager::Init(%s)\n", tree->GetName());
+   if (!fInitOK) {
+      AliError("You have to call InitAnalysis first");
+      return;
+   }   
+   if (!tree) return;
+   fTree = tree;
+   AliAnalysisDataContainer *top = (AliAnalysisDataContainer*)fInputs->At(0);
+   top->SetData(tree);
 }
 
 //______________________________________________________________________________
-void AliAnalysisManager::Begin(TTree */*tree*/)
+void AliAnalysisManager::Begin(TTree *tree)
 {
   // The Begin() function is called at the start of the query.
   // When running with PROOF Begin() is only called on the client.
   // The tree argument is deprecated (on PROOF 0 is passed).
+   printf("AliAnalysisManager::Begin(%s)\n", tree->GetName());
+   Init(tree);
 }
 
 //______________________________________________________________________________
-void AliAnalysisManager::SlaveBegin(TTree */*tree*/)
+void AliAnalysisManager::SlaveBegin(TTree *tree)
 {
   // The SlaveBegin() function is called after the Begin() function.
   // When running with PROOF SlaveBegin() is called on each slave server.
   // The tree argument is deprecated (on PROOF 0 is passed).
+   printf("AliAnalysisManager::SlaveBegin(%s)\n", tree->GetName());
+   Init(tree);
 }
 
 //______________________________________________________________________________
-Bool_t AliAnalysisManager::Process(Long64_t /*entry*/)
+Bool_t AliAnalysisManager::Notify()
+{
+   // The Notify() function is called when a new file is opened. This
+   // can be either for a new TTree in a TChain or when when a new TTree
+   // is started when using PROOF. It is normaly not necessary to make changes
+   // to the generated code, but the routine can be extended by the
+   // user if needed. The return value is currently not used.
+   if (fTree) {
+      TFile *curfile = fTree->GetCurrentFile();
+      if (curfile) printf("AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
+   }
+   return kTRUE;
+}    
+
+//______________________________________________________________________________
+Bool_t AliAnalysisManager::Process(Long64_t entry)
 {
   // The Process() function is called for each entry in the tree (or possibly
   // keyed object in the case of PROOF) to be processed. The entry argument
@@ -157,7 +196,11 @@ Bool_t AliAnalysisManager::Process(Long64_t /*entry*/)
   //  The entry is always the local entry number in the current tree.
   //  Assuming that fChain is the pointer to the TChain being processed,
   //  use fChain->GetTree()->GetEntry(entry).
-  return kFALSE;
+  
+//   printf("AliAnalysisManager::Process(%lld)\n", entry);
+   GetEntry(entry);
+   ExecAnalysis();
+   return kTRUE;
 }
 
 //______________________________________________________________________________
@@ -166,6 +209,19 @@ void AliAnalysisManager::SlaveTerminate()
   // The SlaveTerminate() function is called after all entries or objects
   // have been processed. When running with PROOF SlaveTerminate() is called
   // on each slave server.
+
+   printf("AliAnalysisManager::SlaveTerminate()\n");
+   if (!fOutput)
+   {
+     AliError("ERROR: Output list not initialized.");
+     return;
+   }
+   TIter next(fOutputs);
+   AliAnalysisDataContainer *output;
+   while ((output=(AliAnalysisDataContainer *)next())) {
+      output->SetDataOwned(kFALSE);
+      fOutput->Add(output->GetData());
+   }   
 }
 
 //______________________________________________________________________________
@@ -174,6 +230,14 @@ void AliAnalysisManager::Terminate()
   // The Terminate() function is the last function to be called during
   // a query. It always runs on the client, it can be used to present
   // the results graphically or save the results to file.
+   printf("AliAnalysisManager::Terminate()\n");
+   AliAnalysisDataContainer *output;
+   AliAnalysisTask *task;
+   TIter next(fOutputs);
+   while ((output=(AliAnalysisDataContainer *)next())) output->WriteData();
+   TIter next1(fTasks);
+   // Call Terminate() for tasks
+   while ((task=(AliAnalysisTask*)next1())) task->Terminate();
 }
 
 //______________________________________________________________________________
@@ -261,14 +325,14 @@ Bool_t AliAnalysisManager::InitAnalysis()
 // and data containers are properly connected
    // Check for input/output containers
    fInitOK = kFALSE;
-   if (!fInputs->GetEntriesFast()) {
-      AliError("No input container defined. At least one container should store input data");
-      return kFALSE;
-   }   
-   if (!fOutputs->GetEntriesFast()) {
-      AliError("No output container defined. At least one container should store output data");
-      return kFALSE;
-   }   
+//   if (!fInputs->GetEntriesFast()) {
+//      AliError("No input container defined. At least one container should store input data");
+//      return kFALSE;
+//   }   
+//   if (!fOutputs->GetEntriesFast()) {
+//      AliError("No output container defined. At least one container should store output data");
+//      return kFALSE;
+//   }   
    // Check for top tasks (depending only on input data containers)
    if (!fTasks->First()) {
       AliError("Analysis have no tasks !");
@@ -279,38 +343,38 @@ Bool_t AliAnalysisManager::InitAnalysis()
    AliAnalysisDataContainer *cont;
    Int_t ntop = 0;
    Int_t nzombies = 0;
-   Bool_t is_zombie = kFALSE;
-   Bool_t is_top = kTRUE;
+   Bool_t iszombie = kFALSE;
+   Bool_t istop = kTRUE;
    Int_t i;
    while ((task=(AliAnalysisTask*)next())) {
-      is_top = kTRUE;
-      is_zombie = kFALSE;
+      istop = kTRUE;
+      iszombie = kFALSE;
       Int_t ninputs = task->GetNinputs();
-      if (!ninputs) {
-         task->SetZombie();
-         fZombies->Add(task);
-         nzombies++;
-         AliWarning(Form("Task %s has no input slots defined ! Declared zombie...",task->GetName()));
-         continue;
-      }
+//      if (!ninputs) {
+//         task->SetZombie();
+//         fZombies->Add(task);
+//         nzombies++;
+//         AliWarning(Form("Task %s has no input slots defined ! Declared zombie...",task->GetName()));
+//         continue;
+//      }
       for (i=0; i<ninputs; i++) {
          cont = task->GetInputSlot(i)->GetContainer();
          if (!cont) {
-            if (!is_zombie) {
+            if (!iszombie) {
                task->SetZombie();
                fZombies->Add(task);
                nzombies++;
-               is_zombie = kTRUE;
+               iszombie = kTRUE;
             }   
             AliWarning(Form("Input slot %i of task %s has no container connected ! Declared zombie...",
                        i,task->GetName()));
          }
-         if (is_zombie) continue;
+         if (iszombie) continue;
          // Check if cont is an input container
-         if (is_top && !fInputs->FindObject(cont)) is_top=kFALSE;
+         if (istop && !fInputs->FindObject(cont)) istop=kFALSE;
          // Connect to parent task
       }
-      if (is_top) {
+      if (istop) {
          ntop++;
          fTopTasks->Add(task);
       }
@@ -342,6 +406,7 @@ Bool_t AliAnalysisManager::InitAnalysis()
          return kFALSE;
       }   
    }
+   fInitOK = kTRUE;
    return kTRUE;
 }   
 
@@ -366,10 +431,36 @@ void AliAnalysisManager::ResetAnalysis()
 void AliAnalysisManager::ExecAnalysis(Option_t *option)
 {
 // Execute analysis.
-   TIter next(fTopTasks);
+   if (!fInitOK) {
+      AliError("Analysis manager was not initialized !");
+      return;
+   }   
    AliAnalysisTask *task;
-   while ((task=(AliAnalysisTask*)next()))
+   // Check if the top tree is active.
+   if (fTree) {
+      TIter next(fTasks);
+   // De-activate all tasks
+      while ((task=(AliAnalysisTask*)next())) task->SetActive(kFALSE);
+      AliAnalysisDataContainer *cont = (AliAnalysisDataContainer*)fInputs->At(0);
+      if (!cont) {
+         AliError("Cannot execute analysis in TSelector mode without at least one top container");
+         return;
+      }   
+      cont->SetData(fTree); // This will notify all consumers
+      TIter next1(cont->GetConsumers());
+      while ((task=(AliAnalysisTask*)next1())) {
+//         task->SetActive(kTRUE);
+         task->ExecuteTask(option);
+      }
+      return;
+   }   
+   // The event loop is not controlled by TSelector   
+   TIter next2(fTopTasks);
+   while ((task=(AliAnalysisTask*)next2())) {
+      task->SetActive(kTRUE);
+      printf("executing %s\n", task->GetName());
       task->ExecuteTask(option);
+   }   
 }
 
 //______________________________________________________________________________
index 771a494..8ee6c3b 100644 (file)
@@ -36,12 +36,16 @@ enum EAliAnalysisContType {
    // Selector-specific methods
    virtual void        Init(TTree *tree);   
    virtual void        Begin(TTree *tree);
+   virtual Bool_t      Notify();
    virtual void        SlaveBegin(TTree *tree);
+   virtual Bool_t      ProcessCut(Long64_t entry) {return Process(entry);}
    virtual Bool_t      Process(Long64_t entry);
+   virtual Int_t       GetEntry(Long64_t entry, Int_t getall = 0);
    virtual void        SlaveTerminate();
    virtual void        Terminate();
 
    // Getters
+   TTree              *GetTree() const       {return fTree;}
    TObjArray          *GetContainers() const {return fContainers;}
    TObjArray          *GetInputs() const     {return fInputs;}
    TObjArray          *GetOutputs() const    {return fOutputs;}
@@ -75,6 +79,7 @@ enum EAliAnalysisContType {
    void                 PrintStatus(Option_t *option="all") const;
 
 protected:
+   TTree               *fTree;         // Input tree in case of TSelector model
    Bool_t               fInitOK;       // Initialisation done
    TObjArray           *fContainers;   //-> List of all containers
    TObjArray           *fInputs;       //-> List of containers with input data
index 6c35e24..7c1a577 100644 (file)
@@ -18,6 +18,9 @@
 
 //==============================================================================
 //   AliAnalysysRLContainer - 
+//
+//
+//
 //==============================================================================
 
 #include "AliAnalysisRLContainer.h"
index 4e8b68d..82208d2 100644 (file)
 //                                    AliAnalysisDataContainer *cont)
 // To connect a slot to a data container, the data types declared by both must
 // match.
+//
+// The method Init will be called once per session at the moment when the data is
+// available at all input slots. 
+// The method Init() has to be overloaded by the derived class in order to:
+// 1. Define objects that should be created only once per session (e.g. output
+//    histograms)
+// 2. Set the branch address or connect to a branch address in case the input
+//    slots are connected to trees.
+//
+// Example:
+// MyAnalysisTask::Init(Option_t *)
+// {
+//    if (!fHist1) fHist1 = new TH1F("h1", ....);
+//    if (!fHist2) fHist2 = new TH1F("h2", ....);
+//    fESD = GetBranchAddress(islot=0, "ESD");
+//    if (!fESD) SetBranchAddress(islot=0, "ESD", &fESD);
+// }
+//
+// The method Terminate() will be called by the framework once at the end of
+// data processing. Overload this if needed.
+//
 //==============================================================================
 
 #include "TClass.h"
@@ -59,6 +80,7 @@ ClassImp(AliAnalysisTask)
 //______________________________________________________________________________
 AliAnalysisTask::AliAnalysisTask()
                 :fReady(kFALSE),
+                 fInitialized(kFALSE),
                  fNinputs(0),
                  fNoutputs(0),
                  fOutputReady(NULL),
@@ -73,6 +95,7 @@ AliAnalysisTask::AliAnalysisTask()
 AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
                 :TTask(name,title),
                  fReady(kFALSE),
+                 fInitialized(kFALSE),
                  fNinputs(0),
                  fNoutputs(0),
                  fOutputReady(NULL),
@@ -89,6 +112,7 @@ AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
 AliAnalysisTask::AliAnalysisTask(const AliAnalysisTask &task)
                 :TTask(task),
                  fReady(task.fReady),
+                 fInitialized(task.fInitialized),
                  fNinputs(task.fNinputs),
                  fNoutputs(task.fNoutputs),                 
                  fOutputReady(NULL),
@@ -124,6 +148,7 @@ AliAnalysisTask& AliAnalysisTask::operator=(const AliAnalysisTask& task)
    if (&task == this) return *this;
    TTask::operator=(task);
    fReady       = task.IsReady();
+   fInitialized = task.IsInitialized();
    fNinputs     = task.GetNinputs();
    fNoutputs    = task.GetNoutputs();
    fInputs      = new TObjArray((fNinputs)?fNinputs:2);
@@ -168,11 +193,12 @@ Bool_t AliAnalysisTask::AreSlotsConnected()
 }
 
 //______________________________________________________________________________
-void AliAnalysisTask::CheckNotify()
+void AliAnalysisTask::CheckNotify(Bool_t init)
 {
 // Check if data is available from all inputs. Change the status of the task
 // accordingly. This method is called automatically for all tasks connected
 // to a container where the data was published.
+   if (init) fInitialized = kFALSE;
    for (Int_t islot=0; islot<fNinputs; islot++) {
       if (!GetInputData(islot)) {
          SetActive(kFALSE);
@@ -180,6 +206,11 @@ void AliAnalysisTask::CheckNotify()
       }   
    }   
    SetActive(kTRUE);
+   if (fInitialized) return;
+   TDirectory *cursav = gDirectory;
+   Init();
+   if (cursav) cursav->cd();
+   fInitialized = kTRUE;
 }
 
 //______________________________________________________________________________
@@ -293,6 +324,41 @@ TObject *AliAnalysisTask::GetInputData(Int_t islot) const
 }
 
 //______________________________________________________________________________
+char *AliAnalysisTask::GetBranchAddress(Int_t islot, const char *branch) const
+{
+// Check if a branch with a given name from the specified input is connected
+// to some address. Call this in Init() before trying to call SetBranchAddress()
+// since the adress may be set by other task.
+   return (char *)GetInputSlot(islot)->GetBranchAddress(branch);
+}
+
+//______________________________________________________________________________
+Bool_t AliAnalysisTask::SetBranchAddress(Int_t islot, const char *branch, void *address) const
+{
+// Connect an object address to a branch of the specified input.
+   return GetInputSlot(islot)->SetBranchAddress(branch, address);
+}   
+
+//______________________________________________________________________________
+void AliAnalysisTask::Init(Option_t *)
+{
+// Branch address initialization.
+}
+
+//______________________________________________________________________________
+void AliAnalysisTask::Terminate(Option_t *)
+{
+// Method called by the framework at the end of data processing.
+}
+
+//______________________________________________________________________________
+void AliAnalysisTask::OpenFile(Int_t iout, const char *name, Option_t *option) const
+{
+// Set data at output iout to be written in the specified file.
+   GetOutputSlot(iout)->GetContainer()->OpenFile(name, option);
+}   
+
+//______________________________________________________________________________
 Bool_t AliAnalysisTask::PostData(Int_t iout, TObject *data, Option_t *option)
 {
 // Post output data for a given ouput slot in the corresponding data container.
index cb53b22..b44588a 100644 (file)
@@ -25,77 +25,96 @@ class AliAnalysisDataSlot;
 class AliAnalysisDataContainer;
 
 class AliAnalysisTask : public TTask {
-public:
-enum EAnalysisTaskFlags {
-   kTaskUsed    = BIT(14),
-   kTaskZombie  = BIT(15),
-   kTaskChecked = BIT(16)
-};   
-protected:
-   // Define the input/output slots (called by user in the ctor of the derived class)
-   //=== CALL IN THE CONSTRUCTOR OF DERIVED CLASS TO DEFINE INPUTS/OUTPUTS ===
-   void                      DefineInput(Int_t islot, TClass *type);
-   void                      DefineOutput(Int_t islot, TClass *type);
-   //=====================================================================
-
-   // Post output data (called by Exec() when data is ready)
-   //=== CALL IN EXEC() FOR EACH OUTPUT WHEN READY ===
-   Bool_t                    PostData(Int_t iout, TObject *data, Option_t *option="");
-   //=====================================================================
-
-public:
-   AliAnalysisTask();
-   AliAnalysisTask(const char *name, const char *title);
-   AliAnalysisTask(const AliAnalysisTask &task); 
-   virtual ~AliAnalysisTask();
-   
-   // Assignment
-   AliAnalysisTask& operator=(const AliAnalysisTask &task);
-   // Conect inputs/outputs to data containers (by AliAnalysisModule)
-   Bool_t                    ConnectInput(Int_t islot, AliAnalysisDataContainer *cont);
-   Bool_t                    ConnectOutput(Int_t islot, AliAnalysisDataContainer *cont);
-   // Check connectivity
-   Bool_t                    AreSlotsConnected();
-   // Check if data for all inputs is ready
-   void                      CheckNotify();
-   // Check if there are illegal circular dependencies
-   Bool_t                    CheckCircularDeps();
-   // Getters
-   Int_t                     GetNinputs() const  {return fNinputs;}
-   Int_t                     GetNoutputs() const {return fNoutputs;}
-   TObject                  *GetPublishedData() const {return fPublishedData;}
-   AliAnalysisDataSlot      *GetInputSlot(Int_t islot) const  {return (AliAnalysisDataSlot*)fInputs->At(islot);}
-   AliAnalysisDataSlot      *GetOutputSlot(Int_t islot) const {return (AliAnalysisDataSlot*)fOutputs->At(islot);}
-   TClass                   *GetInputType(Int_t islot) const;
-   TClass                   *GetOutputType(Int_t islot) const;
-   // === USE THIS TO RETREIVE INPUT DATA AND STATICALLY CAST IT TO THE DECLARED TYPE
-   TObject                  *GetInputData(Int_t islot) const;
-   //=====================================================================
-   Bool_t                    IsOutputReady(Int_t islot) const {return fOutputReady[islot];}
-   Bool_t                    IsChecked() const  {return TObject::TestBit(kTaskChecked);}
-   Bool_t                    IsReady() const  {return fReady;}
-   Bool_t                    IsUsed() const   {return TObject::TestBit(kTaskUsed);}
-   Bool_t                    IsZombie() const {return TObject::TestBit(kTaskZombie);}
-   void                      PrintTask(Option_t *option="all", Int_t indent=0) const;
-   void                      PrintContainers(Option_t *option="all", Int_t indent=0) const;
-   void                      SetChecked(Bool_t flag=kTRUE) {TObject::SetBit(kTaskChecked,flag);}
-   void                      SetUsed(Bool_t flag=kTRUE);
-   void                      SetZombie(Bool_t flag=kTRUE) {TObject::SetBit(kTaskZombie,flag);}
-   // Main task execution 
-   //=== IMPLEMENT THIS !!! ==============================================
-   virtual void              Exec(Option_t *option) = 0;
-   //=====================================================================
-   Bool_t                    HasExecuted() const {return fHasExecuted;}
-   
-protected:
-   Bool_t                    fReady;      // Flag if the task is ready
-   Int_t                     fNinputs;    // Number of inputs
-   Int_t                     fNoutputs;   // Number of outputs
-   Bool_t                   *fOutputReady; //[fNoutputs] Flags for output readyness
-   TObject                  *fPublishedData; // !published data
-   TObjArray                *fInputs;     // Array of input slots
-   TObjArray                *fOutputs;    // Array of output slots
-   
-   ClassDef(AliAnalysisTask,1)  // Class describing an analysis task
+ public:
+  enum EAnalysisTaskFlags {
+    kTaskUsed    = BIT(14),
+    kTaskZombie  = BIT(15),
+    kTaskChecked = BIT(16)
+  };   
+  
+  AliAnalysisTask();
+  AliAnalysisTask(const char *name, const char *title);
+  AliAnalysisTask(const AliAnalysisTask &task); 
+  virtual ~AliAnalysisTask();
+  
+  // Assignment
+  AliAnalysisTask& operator=(const AliAnalysisTask &task);
+  // Conect inputs/outputs to data containers (by AliAnalysisModule)
+  Bool_t                    ConnectInput(Int_t islot, AliAnalysisDataContainer *cont);
+  Bool_t                    ConnectOutput(Int_t islot, AliAnalysisDataContainer *cont);
+  // Check connectivity
+  Bool_t                    AreSlotsConnected();
+  // Check if data for all inputs is ready
+  void                      CheckNotify(Bool_t init=kFALSE);
+  // Check if there are illegal circular dependencies
+  Bool_t                    CheckCircularDeps();
+  // Getters
+  Int_t                     GetNinputs() const  {return fNinputs;}
+  Int_t                     GetNoutputs() const {return fNoutputs;}
+  TObject                  *GetPublishedData() const {return fPublishedData;}
+  AliAnalysisDataSlot      *GetInputSlot(Int_t islot) const  {return (AliAnalysisDataSlot*)fInputs->At(islot);}
+  AliAnalysisDataSlot      *GetOutputSlot(Int_t islot) const {return (AliAnalysisDataSlot*)fOutputs->At(islot);}
+  TClass                   *GetInputType(Int_t islot) const;
+  TClass                   *GetOutputType(Int_t islot) const;
+  // === USE THIS TO RETREIVE INPUT DATA AND STATICALLY CAST IT TO THE DECLARED TYPE
+  TObject                  *GetInputData(Int_t islot) const;
+  Bool_t                    IsOutputReady(Int_t islot) const {return fOutputReady[islot];}
+  Bool_t                    IsChecked() const  {return TObject::TestBit(kTaskChecked);}
+  Bool_t                    IsInitialized() const  {return fInitialized;}
+  Bool_t                    IsReady() const  {return fReady;}
+  Bool_t                    IsUsed() const   {return TObject::TestBit(kTaskUsed);}
+  Bool_t                    IsZombie() const {return TObject::TestBit(kTaskZombie);}
+  void                      PrintTask(Option_t *option="all", Int_t indent=0) const;
+  void                      PrintContainers(Option_t *option="all", Int_t indent=0) const;
+  void                      SetChecked(Bool_t flag=kTRUE) {TObject::SetBit(kTaskChecked,flag);}
+  void                      SetUsed(Bool_t flag=kTRUE);
+  void                      SetZombie(Bool_t flag=kTRUE) {TObject::SetBit(kTaskZombie,flag);}
+  // Main task execution 
+  //=== IMPLEMENT THIS !!! ==============================================
+  virtual void              Exec(Option_t *option) = 0;
+  //=====================================================================
+  Bool_t                    HasExecuted() const {return fHasExecuted;}
+  //=====================================================================
+  // === OVERLOAD THIS IF YOU WANT TO DO SOMETHING WITH THE OUTPUT
+  virtual void              Terminate(Option_t *option="");
+  //=====================================================================
+  
+ protected:
+  // Define the input/output slots (called by user in the ctor of the derived class)
+  //=== CALL IN THE CONSTRUCTOR OF DERIVED CLASS TO DEFINE INPUTS/OUTPUTS ===
+  void                      DefineInput(Int_t islot, TClass *type);
+  void                      DefineOutput(Int_t islot, TClass *type);
+  //=====================================================================
+  
+  //=====================================================================
+  // === OVERLOAD THIS TO CONNECT TREE BRANCHES AT INPUT SLOTS. YOU
+  // SHOULD DEFINE HERE ALSO THE OBJECTS TO BE CONNECTED TO YOUR OUTPUTS
+  virtual void              Init(Option_t *option="");
+  //=====================================================================
+  
+  // Post output data (called by Exec() when data is ready)
+  //=== CALL IN EXEC() FOR EACH OUTPUT WHEN READY ===
+  Bool_t                    PostData(Int_t iout, TObject *data, Option_t *option="");
+  //=====================================================================
+  
+  // === USE THIS FIRST IN YOUR Init() TO CHECH IF A BRANCH IS ALREADY CONNECTED
+  // TO SOME ADDRESS.
+  char                     *GetBranchAddress(Int_t islot, const char *branch) const;
+  // === CALL THIS AFTERWARDS IN Init() IF THE BRANCH ADDRESS IS NOT YET SET
+  Bool_t                    SetBranchAddress(Int_t islot, const char *branch, void *address) const;
+  //=====================================================================
+  // === CALL THIS IN INIT IF THE OUTPUT IS TO BE WRITTEN AT OUTPUT IOUT
+  void                      OpenFile(Int_t iout, const char *name, Option_t *option) const;
+  
+  Bool_t                    fReady;      // Flag if the task is ready
+  Bool_t                    fInitialized; // True if Init() was called
+  Int_t                     fNinputs;    // Number of inputs
+  Int_t                     fNoutputs;   // Number of outputs
+  Bool_t                   *fOutputReady; //[fNoutputs] Flags for output readyness
+  TObject                  *fPublishedData; // !published data
+  TObjArray                *fInputs;     // Array of input slots
+  TObjArray                *fOutputs;    // Array of output slots
+  
+  ClassDef(AliAnalysisTask,2)  // Class describing an analysis task
 };
 #endif
diff --git a/ANALYSIS/AnalysisExtraLinkDef.h b/ANALYSIS/AnalysisExtraLinkDef.h
new file mode 100644 (file)
index 0000000..9548f15
--- /dev/null
@@ -0,0 +1,9 @@
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class  AliAnalysisRLContainer+;
+
+#endif
index 8ef9a4e..b9c40e2 100644 (file)
@@ -5,7 +5,6 @@
 #pragma link off all functions;
 
 #pragma link C++ class  AliAnalysisDataContainer+;
-#pragma link C++ class  AliAnalysisRLContainer+;
 #pragma link C++ class  AliAnalysisTask+;
 #pragma link C++ class  AliAnalysisDataSlot+;
 #pragma link C++ class  AliAnalysisManager+;
diff --git a/ANALYSIS/libANALYSIS_EXTRA.pkg b/ANALYSIS/libANALYSIS_EXTRA.pkg
new file mode 100644 (file)
index 0000000..9ed84ae
--- /dev/null
@@ -0,0 +1,7 @@
+SRCS= AliAnalysisRLContainer.cxx
+
+HDRS= $(SRCS:.cxx=.h) 
+
+DHDR:=AnalysisExtraLinkDef.h
+
+EXPORT:=$(HDRS)
index 4c9b0b3..36ead3a 100644 (file)
@@ -1,4 +1,4 @@
-SRCS= AliAnalysisDataContainer.cxx AliAnalysisRLContainer.cxx \
+SRCS= AliAnalysisDataContainer.cxx \
       AliAnalysisTask.cxx AliAnalysisDataSlot.cxx AliAnalysisManager.cxx
 
 HDRS= $(SRCS:.cxx=.h)