- New class AliAnalysisDataWrapper used for streaming output results from PROOF to
authoragheata <agheata@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 2 May 2007 08:26:22 +0000 (08:26 +0000)
committeragheata <agheata@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 2 May 2007 08:26:22 +0000 (08:26 +0000)
local client. The class is just a data wrapper that implements Merge() method.
Wrappers have the same name as the data containers exporting the data, which is then
imported by the corresponding container on the client. Used only on PROOF mode
does not provide any user API (framework utility). This fixes current streaming
in PROOF mode.
- All input tree branches are disabled. Analysis tasks should connect to needed
branches inside MyTask::ConnectInputData() by testing first if the branch address
is already taken, then calling SetBranchAddress():
    char ** address = (char **)GetBranchAddress(0, "ESD");
    if (address)
    {
      fESD = (AliESD*)(*address);
    }
    else
    {
      fESD = new AliESD();
      SetBranchAddress(0, "ESD", &fESD); // first task taking the branch enables it
    }
- virtual AliAnalysisTask::Notify() implemented. This method should be implemented
by the derived user task only if current chain file changes need to be treated.
Used currently by AliAnalysisTaskRL class to handle correclty AliRunLoader pointer.
- Methods: MyTask::CreateOutputObjects() and MyTask::Terminate() now called also
for non-event loop tasks (e.g. fitting).

12 files changed:
ANALYSIS/ANALYSISLinkDef.h
ANALYSIS/AliAnalysisDataContainer.cxx
ANALYSIS/AliAnalysisDataContainer.h
ANALYSIS/AliAnalysisDataSlot.cxx
ANALYSIS/AliAnalysisManager.cxx
ANALYSIS/AliAnalysisManager.h
ANALYSIS/AliAnalysisSelector.cxx
ANALYSIS/AliAnalysisSelector.h
ANALYSIS/AliAnalysisTask.cxx
ANALYSIS/AliAnalysisTask.h
ANALYSIS/AliAnalysisTaskRL.cxx
ANALYSIS/AliAnalysisTaskRL.h

index bc4bfa7..8cb375c 100644 (file)
@@ -5,6 +5,7 @@
 #pragma link off all functions;
 
 #pragma link C++ class  AliAnalysisDataContainer+;
+#pragma link C++ class  AliAnalysisDataWrapper+;
 #pragma link C++ class  AliAnalysisTask+;
 #pragma link C++ class  AliAnalysisDataSlot+;
 #pragma link C++ class  AliAnalysisManager+;
index 0aa772a..004491f 100644 (file)
@@ -354,4 +354,98 @@ void AliAnalysisDataContainer::SetProducer(AliAnalysisTask *prod, Int_t islot)
       if (!prod->GetListOfTasks()->FindObject(cons)) prod->Add(cons);
    }   
 }   
+
+//______________________________________________________________________________
+AliAnalysisDataWrapper *AliAnalysisDataContainer::ExportData() const
+{
+// Wraps data for sending it through the net.
+   AliAnalysisDataWrapper *pack = 0;
+   if (!fData) return pack;
+   pack = new AliAnalysisDataWrapper(fData);
+   pack->SetName(fName.Data());
+   return pack;
+}
+
+//______________________________________________________________________________
+void AliAnalysisDataContainer::ImportData(AliAnalysisDataWrapper *pack)
+{
+// Unwraps data from a data wrapper.
+   if (pack) {
+      fData = pack->Data();
+      fDataReady = kTRUE;
+   }   
+}      
       
+ClassImp (AliAnalysisDataWrapper)
+
+//______________________________________________________________________________
+AliAnalysisDataWrapper &AliAnalysisDataWrapper::operator=(const AliAnalysisDataWrapper &other)
+{
+// Assignment.
+   if (&other != this) {
+      TNamed::operator=(other);
+      fData = other.fData;
+   }   
+   return *this;
+}
+
+//______________________________________________________________________________
+Long64_t AliAnalysisDataWrapper::Merge(TCollection *list)
+{
+// Merge a list of containers with this one. Containers in the list must have
+// data of the same type.
+   if (!fData) return 0;
+   if (!list || list->IsEmpty()) return 1;
+
+   printf("Merging %d data wrappers %s\n", list->GetSize()+1, GetName());
+   TMethodCall callEnv;
+   if (fData->InheritsFrom(TSeqCollection::Class())) {
+      TSeqCollection *coll = (TSeqCollection*)fData;
+      if (coll->IsEmpty()) return 0;
+      Int_t nentries = coll->GetEntries();
+      AliAnalysisDataWrapper *top;
+      TIter next(list);
+      TSeqCollection *collcrt = 0;
+      TList *list1 = 0;
+      for (Int_t i=0; i<nentries; i++) {
+         list1 = new TList();
+         top = new AliAnalysisDataWrapper(coll->At(i));
+         next.Reset();
+         while ((collcrt=(TSeqCollection*)next())) 
+            list1->Add(new AliAnalysisDataWrapper(collcrt->At(i)));
+         if (!top->Merge(list1)) {
+            list1->Delete();
+            delete list1;
+            return 0;   
+         }   
+         list1->Delete();
+         delete list1;
+      }
+      return nentries;
+   }   
+   
+   if (fData->IsA())
+      callEnv.InitWithPrototype(fData->IsA(), "Merge", "TCollection*");
+   if (!callEnv.IsValid()) {
+      cout << "No merge interface for data stored by " << GetName() << ". Merging not possible !" << endl;
+      return 1;
+   }
+
+   TIter next(list);
+   AliAnalysisDataWrapper *cont;
+   // Make a list where to temporary store the data to be merged.
+   TList *collectionData = new TList();
+   Int_t count = 0; // object counter
+   while ((cont=(AliAnalysisDataWrapper*)next())) {
+      TObject *data = cont->Data();
+      if (!data) continue;
+      if (strcmp(cont->GetName(), GetName())) continue;
+      collectionData->Add(data);
+      count++;
+   }
+   callEnv.SetParam((Long_t) collectionData);
+   callEnv.Execute(fData);
+   delete collectionData;
+
+   return count+1;
+}
index e5978a2..5e58383 100644 (file)
@@ -27,6 +27,7 @@ class TClass;
 class TObjArray;
 class TCollection;
 class AliAnalysisTask;
+class AliAnalysisDataWrapper;
 class AliESD;
 
 class AliAnalysisDataContainer : public TNamed {
@@ -59,6 +60,9 @@ enum ENotifyMessage {
    void                      SetProducer(AliAnalysisTask *prod, Int_t islot);
    void                      AddConsumer(AliAnalysisTask *cons, Int_t islot);
    void                      DeleteData();
+   // Wrapping
+   AliAnalysisDataWrapper   *ExportData() const;
+   void                      ImportData(AliAnalysisDataWrapper *pack);
    // Container status checking
    Bool_t                    IsDataReady() const  {return fDataReady;}
    Bool_t                    IsOwnedData() const  {return fOwnedData;}
@@ -86,4 +90,33 @@ protected:
    
    ClassDef(AliAnalysisDataContainer,1)  // Class describing a data container for analysis
 };
+
+//==============================================================================
+//   AliAnalysysDataWrapper - A basic wrapper for exchanging via the network
+// the data held by AliAnalysisDataContainer between the master and the client
+// in PROOF case. 
+//==============================================================================
+
+class AliAnalysisDataWrapper : public TNamed {
+
+public:
+   AliAnalysisDataWrapper() : TNamed(), fData(NULL) {}
+   AliAnalysisDataWrapper(TObject *data) : TNamed(), fData(data) {}
+   AliAnalysisDataWrapper(const AliAnalysisDataWrapper &other) 
+                        : TNamed(other), fData(other.fData) {}
+   virtual ~AliAnalysisDataWrapper() {}
+   
+   // Assignment
+   AliAnalysisDataWrapper &operator=(const AliAnalysisDataWrapper &other);
+
+   TObject                  *Data() const {return fData;}
+   // Merging
+   virtual Long64_t          Merge(TCollection *list);
+
+protected:
+   TObject                  *fData;       // Wrapped data
+
+   ClassDef(AliAnalysisDataWrapper, 1) // Data wrapper class for exchange via the net
+};
+
 #endif
index 379f9fa..de55e65 100644 (file)
@@ -143,11 +143,11 @@ Bool_t AliAnalysisDataSlot::SetBranchAddress(const char *branchname, void *addre
 // 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)) {
-     cout<<"Branch address for "<<branchname<<" already set by other task. Call first GetBranchAddress() in "<<fParent->GetName()<<"::Init()"<<endl;
-     //AliError(Form("Branch address for %s already set by other task. Call first GetBranchAddress() in %s::Init()",branchname, fParent->GetName()));
+      Error("SetBranchAddress","Branch address for %s already set by other task. Call first GetBranchAddress() in %s::ConnectInputData()",branchname, fParent->GetName());
       return kFALSE;
    }
    TTree *tree = (TTree*)GetData();
+   tree->SetBranchStatus(branchname,1);
    tree->SetBranchAddress(branchname, address);
    return kTRUE;
 }   
index ab8e035..7e29eb7 100644 (file)
@@ -167,7 +167,7 @@ void AliAnalysisManager::Init(TTree *tree)
   // Init() will be called many times when running with PROOF.
    if (!tree) return;
    if (fDebug > 1) {
-      printf("AliAnalysisManager::Init(%s)\n", tree->GetName());
+      printf("->AliAnalysisManager::Init(%s)\n", tree->GetName());
    }
    if (!fInitOK) InitAnalysis();
    if (!fInitOK) return;
@@ -178,6 +178,9 @@ void AliAnalysisManager::Init(TTree *tree)
       return;
    }
    top->SetData(tree);
+   if (fDebug > 1) {
+      printf("<-AliAnalysisManager::Init(%s)\n", tree->GetName());
+   }
 }
 
 //______________________________________________________________________________
@@ -199,7 +202,7 @@ void AliAnalysisManager::SlaveBegin(TTree *tree)
   // When running with PROOF SlaveBegin() is called on each slave server.
   // The tree argument is deprecated (on PROOF 0 is passed).
    if (fDebug > 1) {
-      cout << "AliAnalysisManager::SlaveBegin()" << endl;
+      cout << "->AliAnalysisManager::SlaveBegin()" << endl;
    }
 
    TIter next(fTasks);
@@ -208,6 +211,9 @@ void AliAnalysisManager::SlaveBegin(TTree *tree)
    while ((task=(AliAnalysisTask*)next())) 
       task->CreateOutputObjects();
    if (fMode == kLocalAnalysis) Init(tree);   
+   if (fDebug > 1) {
+      cout << "<-AliAnalysisManager::SlaveBegin()" << endl;
+   }
 }
 
 //______________________________________________________________________________
@@ -221,6 +227,11 @@ Bool_t AliAnalysisManager::Notify()
    if (fTree) {
       TFile *curfile = fTree->GetCurrentFile();
       if (curfile && fDebug>1) printf("AliAnalysisManager::Notify() file: %s\n", curfile->GetName());
+      TIter next(fTasks);
+      AliAnalysisTask *task;
+      // Call Notify for all tasks
+      while ((task=(AliAnalysisTask*)next())) 
+         task->Notify();      
    }
    return kTRUE;
 }    
@@ -246,19 +257,23 @@ Bool_t AliAnalysisManager::Process(Long64_t entry)
   //  Assuming that fChain is the pointer to the TChain being processed,
   //  use fChain->GetTree()->GetEntry(entry).
    if (fDebug > 1) {
-      cout << "AliAnalysisManager::Process()" << endl;
+      cout << "->AliAnalysisManager::Process()" << endl;
    }
    GetEntry(entry);
    ExecAnalysis();
+   if (fDebug > 1) {
+      cout << "<-AliAnalysisManager::Process()" << endl;
+   }
    return kTRUE;
 }
 
 //______________________________________________________________________________
 void AliAnalysisManager::PackOutput(TList *target)
 {
-  // Pack all output data containers in the output list.
+  // Pack all output data containers in the output list. Called at SlaveTerminate
+  // stage in PROOF case for each slave.
    if (fDebug > 1) {
-      cout << "AliAnalysisManager::PackOutput()" << endl;
+      cout << "->AliAnalysisManager::PackOutput()" << endl;
    }   
    if (!target) {
       Error("PackOutput", "No target. Aborting.");
@@ -266,55 +281,43 @@ void AliAnalysisManager::PackOutput(TList *target)
    }
 
    if (fMode == kProofAnalysis) {
-      AliAnalysisDataContainer *top = (AliAnalysisDataContainer*)fInputs->At(0);
-      if (!top) {
-          cout<<"Error: No top input container !" <<endl;
-          return;
-      }
-      top->SetData(0);
-
       TIter next(fOutputs);
       AliAnalysisDataContainer *output;
       while ((output=(AliAnalysisDataContainer*)next())) {
-         if (fDebug > 1) printf("   Packing container %s\n", output->GetName());
-         if (output->GetData()) target->Add(output);
-//         output->SetDataOwned(kFALSE);
+         if (fDebug > 1) printf("   Packing container %s...\n", output->GetName());
+         if (output->GetData()) target->Add(output->ExportData());
       }
    } 
-   fContainers->Clear();
    if (fDebug > 1) {
-      printf("   ->output list contains %d containers\n", target->GetSize());
+      printf("<-AliAnalysisManager::PackOutput: output list contains %d containers\n", target->GetSize());
    }
 }
 
 //______________________________________________________________________________
-void AliAnalysisManager::ReplaceOutputContainers(TList *source)
+void AliAnalysisManager::ImportWrappers(TList *source)
 {
-// Replace all exising containers with the ones coming in source.
+// Import data in output containers from wrappers coming in source.
+   if (fDebug > 1) {
+      cout << "->AliAnalysisManager::ImportWrappers()" << endl;
+   }   
    TIter next(fOutputs);
-   AliAnalysisDataContainer *cont, *output;
+   AliAnalysisDataContainer *cont;
+   AliAnalysisDataWrapper   *wrap;
+   Int_t icont = 0;
    while ((cont=(AliAnalysisDataContainer*)next())) {
-      output = (AliAnalysisDataContainer*)source->FindObject(cont->GetName());
-      if (!output) {
-         printf("Error: container %s not found in analysis output !\n", cont->GetName());
+      wrap = (AliAnalysisDataWrapper*)source->FindObject(cont->GetName());
+      if (!wrap && fDebug>1) {
+         printf("(WW) ImportWrappers: container %s not found in analysis output !\n", cont->GetName());
          continue;
       }
-      if (fDebug > 1) printf("...Replacing output container %s\n", output->GetName());
-      if (cont->GetFileName()) printf("    -> %s\n", output->GetFileName());
-      Int_t ntasks = fTasks->GetEntries();
-      AliAnalysisTask *task;
-      AliAnalysisDataSlot *oslot;
-      for (Int_t i=0; i<ntasks; i++) {
-         task = (AliAnalysisTask*)fTasks->At(i);
-         Int_t nout = task->GetNoutputs();
-         for (Int_t iout=0; iout<nout; iout++) {
-            oslot = task->GetOutputSlot(iout);
-            if (oslot->GetContainer() == cont) oslot->ConnectContainer(output);
-         }
-      }
-//      output->GetConsumers()->Delete();
-//      if (output->GetProducer()) delete output->GetProducer();
+      icont++;
+      if (fDebug > 1) printf("   Importing data for container %s\n", wrap->GetName());
+      if (cont->GetFileName()) printf("    -> %s\n", cont->GetFileName());
+      cont->ImportData(wrap);
    }         
+   if (fDebug > 1) {
+      cout << "<-AliAnalysisManager::ImportWrappers(): "<< icont << " containers imported" << endl;
+   }   
 }
 
 //______________________________________________________________________________
@@ -322,31 +325,22 @@ void AliAnalysisManager::UnpackOutput(TList *source)
 {
   // Called by AliAnalysisSelector::Terminate. Output containers should
   // be in source in the same order as in fOutputs.
-
+   if (fDebug > 1) {
+      cout << "->AliAnalysisManager::UnpackOutput()" << endl;
+   }   
    if (!source) {
-      Error("PackOutput", "No target. Aborting.");
+      Error("UnpackOutput", "No target. Aborting.");
       return;
    }
    if (fDebug > 1) {
-      printf("AliAnalysisManager::UnpackOutput(): %d containers\n", source->GetSize());
       printf("   Source list contains %d containers\n", source->GetSize());
    }   
 
-   if (fMode == kProofAnalysis) {
-      ReplaceOutputContainers(source);
-      fOutputs->Clear();
-   }
-
-   TCollection *collection = source;
-   if (fMode == kLocalAnalysis) collection = fOutputs;
-   TIter next(collection);
+   if (fMode == kProofAnalysis) ImportWrappers(source);
 
+   TIter next(fOutputs);
    AliAnalysisDataContainer *output;
    while ((output=(AliAnalysisDataContainer*)next())) {
-      if (fMode == kProofAnalysis) {
-         output->SetDataOwned(kTRUE);
-         fOutputs->Add(output);
-      }
       if (!output->GetData()) continue;
       // Check if the output need to be written to a file.
       const char *filename = output->GetFileName();
@@ -365,6 +359,9 @@ void AliAnalysisManager::UnpackOutput(TList *source)
       }
       output->GetData()->Write();      
    }
+   if (fDebug > 1) {
+      cout << "<-AliAnalysisManager::UnpackOutput()" << endl;
+   }   
 }
 
 //______________________________________________________________________________
@@ -374,12 +371,15 @@ void AliAnalysisManager::Terminate()
   // a query. It always runs on the client, it can be used to present
   // the results graphically.
    if (fDebug > 1) {
-      cout << "AliAnalysisManager::Terminate()" << endl;
+      cout << "->AliAnalysisManager::Terminate()" << endl;
    }   
    AliAnalysisTask *task;
    TIter next(fTasks);
    // Call Terminate() for tasks
    while ((task=(AliAnalysisTask*)next())) task->Terminate();
+   if (fDebug > 1) {
+      cout << "<-AliAnalysisManager::Terminate()" << endl;
+   }   
 }
 
 //______________________________________________________________________________
@@ -576,18 +576,25 @@ void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree)
    }
    if (fMode == kGridAnalysis) {
       Warning("StartAnalysis", "GRID analysis mode not implemented. Running local.");
-      fMode = kLocalAnalysis; 
-   }     
+      fMode = kLocalAnalysis;
+   }
    char line[128];   
+   // Disable by default all branches
+   if (tree) tree->SetBranchStatus("*",0);
    TChain *chain = dynamic_cast<TChain*>(tree);
    switch (fMode) {
       case kLocalAnalysis:
          if (!tree) {
+            TIter next(fTasks);
+            AliAnalysisTask *task;
+            // Call CreateOutputObjects for all tasks
+            while ((task=(AliAnalysisTask*)next())) task->CreateOutputObjects();
             ExecAnalysis();
+            Terminate();
             return;
          } 
          // Run tree-based analysis via AliAnalysisSelector  
-         gROOT->ProcessLine(".L $ALICE_ROOT/ANALYSIS/AliAnalysisSelector.cxx+");
+         gROOT->ProcessLine(".L AliAnalysisSelector.cxx+");
          cout << "===== RUNNING LOCAL ANALYSIS " << GetName() << " ON TREE " << tree->GetName() << endl;
          sprintf(line, "AliAnalysisSelector *selector = new AliAnalysisSelector((AliAnalysisManager*)0x%lx);",(ULong_t)this);
          gROOT->ProcessLine(line);
index 0085423..a6021dc 100644 (file)
@@ -102,7 +102,7 @@ enum EAliAnalysisExecMode {
    void                 PrintStatus(Option_t *option="all") const;
 
 protected:
-   void                 ReplaceOutputContainers(TList *source);
+   void                 ImportWrappers(TList *source);
 
 private:
    TTree               *fTree;         //! Input tree in case of TSelector model
index a585053..0cd1ac1 100644 (file)
@@ -57,12 +57,18 @@ void AliAnalysisSelector::Init(TTree *tree)
       Error("Init", "Analysis manager NULL !");
       return;
    }
+   if (fAnalysis->GetDebugLevel()>1) {
+      cout << "->AliAnalysisSelector->Init()" << endl;
+   }   
    if (!tree) {
       Error("Init", "Input tree is NULL !");
       return;
    }
    fAnalysis->Init(tree);
    fInitialized = kTRUE;
+   if (fAnalysis->GetDebugLevel()>1) {
+      cout << "<-AliAnalysisSelector->Init()" << endl;
+   }   
 }
 
 //______________________________________________________________________________
@@ -70,6 +76,9 @@ void AliAnalysisSelector::Begin(TTree *)
 {
 // Assembly the input list.
    RestoreAnalysisManager();
+   if (fAnalysis && fAnalysis->GetDebugLevel()>1) {
+      cout << "->AliAnalysisSelector->Init: Analysis manager restored" << endl;
+   }   
 }
 
 //______________________________________________________________________________
@@ -77,18 +86,40 @@ void AliAnalysisSelector::SlaveBegin(TTree *tree)
 {
 // Called on each worker. We "unpack" analysis manager here and call InitAnalysis.
    RestoreAnalysisManager();
-   if (fAnalysis) fAnalysis->SlaveBegin(tree);   
+   if (fAnalysis) {
+      if (fAnalysis->GetDebugLevel()>1) {
+         cout << "->AliAnalysisSelector->SlaveBegin() after Restore" << endl;
+      }   
+      fAnalysis->SlaveBegin(tree);   
+      if (fAnalysis->GetDebugLevel()>1) {
+         cout << "<-AliAnalysisSelector->SlaveBegin()" << endl;
+      }   
+   }   
 }      
 
 //______________________________________________________________________________
+Bool_t AliAnalysisSelector::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 (fAnalysis) fAnalysis->Notify();
+}   
+
+//______________________________________________________________________________
 Bool_t AliAnalysisSelector::Process(Long64_t entry)
 {
 // Event loop.
    if (fAnalysis->GetDebugLevel() >1 ) {
-      printf("AliAnalysisSelector::Process()\n");
+      cout << "->AliAnalysisSelector::Process()" << endl;
    }   
    fAnalysis->GetEntry(entry); // Not needed anymore in version 2
    fAnalysis->ExecAnalysis();
+   if (fAnalysis->GetDebugLevel() >1 ) {
+      cout << "<-AliAnalysisSelector::Process()" << endl;
+   }   
    return kTRUE;
 }   
 
@@ -102,6 +133,9 @@ void AliAnalysisSelector::RestoreAnalysisManager()
       while ((obj=next())) {
          if (obj->IsA() == AliAnalysisManager::Class()) {
             fAnalysis = (AliAnalysisManager*)obj;
+            if (fAnalysis->GetDebugLevel()>1) {
+               cout << "->AliAnalysisSelector->RestoreAnalysisManager: Analysis manager restored" << endl;
+            }   
             break;
          }
       }
@@ -119,9 +153,12 @@ void AliAnalysisSelector::SlaveTerminate()
   // have been processed. When running with PROOF SlaveTerminate() is called
   // on each slave server.
    if (fAnalysis->GetDebugLevel() >1 ) {
-      printf("AliAnalysisSelector::SlaveTerminate()\n");
+      cout << "->AliAnalysisSelector::SlaveTerminate()" << endl;
    }   
    fAnalysis->PackOutput(fOutput);
+   if (fAnalysis->GetDebugLevel() >1 ) {
+      cout << "<-AliAnalysisSelector::SlaveTerminate()" << endl;
+   }   
 }  
 
 //______________________________________________________________________________
@@ -135,8 +172,11 @@ void AliAnalysisSelector::Terminate()
       return;
    }   
    if (fAnalysis->GetDebugLevel() >1 ) {
-      printf("AliAnalysisSelector::Terminate()\n");
+      cout << "->AliAnalysisSelector::Terminate()" << endl;
    }   
    fAnalysis->UnpackOutput(fOutput);
    fAnalysis->Terminate();   
+   if (fAnalysis->GetDebugLevel() >1 ) {
+      cout << "<-AliAnalysisSelector::Terminate()" << endl;
+   }   
 }
index 93c4e42..a3b41f6 100644 (file)
@@ -36,7 +36,7 @@ public:
    virtual void        Init(TTree *tree);
    virtual void        Begin(TTree *);
    virtual void        SlaveBegin(TTree *tree);
-   virtual Bool_t      Notify() {return kTRUE;}   
+   virtual Bool_t      Notify();   
    virtual Bool_t      Process(Long64_t entry);
    virtual void        SlaveTerminate();
    virtual void        Terminate();
index 2efecdf..b35021c 100644 (file)
@@ -380,7 +380,15 @@ void AliAnalysisTask::ConnectInputData(Option_t *)
 //______________________________________________________________________________
 void AliAnalysisTask::CreateOutputObjects()
 {
-// Overload and create your output objects here.
+// Called once per task either in PROOF or local mode. Overload to put some 
+// task initialization and/or create your output objects here.
+}
+
+//______________________________________________________________________________
+Bool_t AliAnalysisTask::Notify()
+{
+// Overload this IF you need to treat input file change.
+   return kTRUE;
 }
 
 //______________________________________________________________________________
index 698890c..2303583 100644 (file)
@@ -79,6 +79,8 @@ public:
   //=====================================================================
   // === OVERLOAD THIS AND CREATE YOUR OUTPUT OBJECTS (HISTOGRAMS,DATA) HERE
   virtual void              CreateOutputObjects();
+  // === OVERLOAD THIS IF YOU NEED TO TREAT INPUT FILE CHANGE
+  virtual Bool_t            Notify();
   // Conect inputs/outputs to data containers (by AliAnalysisModule)
   Bool_t                    ConnectInput(Int_t islot, AliAnalysisDataContainer *cont);
   Bool_t                    ConnectOutput(Int_t islot, AliAnalysisDataContainer *cont);
index 993bf06..04c97d5 100644 (file)
@@ -37,7 +37,7 @@ ClassImp(AliAnalysisTaskRL)
 AliAnalysisTaskRL::AliAnalysisTaskRL() :
   AliAnalysisTask(),
   fTree(0), fRunLoader(0),
-  fKinematicsLoaded(kFALSE), fHeaderLoaded(kFALSE), fTreeNumber(-1) {
+  fKinematicsLoaded(kFALSE), fHeaderLoaded(kFALSE) {
   //
   // Constructor. Initialization of pointers
   //
@@ -70,18 +70,19 @@ Bool_t AliAnalysisTaskRL::GetEntry(Long64_t ientry) {
 }
 
 //___________________________________________________________________________
+Bool_t AliAnalysisTaskRL::Notify() {
+// The file has changed or there is a new tree. Delete the run loader.
+   DeleteRunLoader();
+   return kTRUE;
+}   
+
+//___________________________________________________________________________
 AliRunLoader *AliAnalysisTaskRL::GetRunLoader() {
   // Returns AliRun instance corresponding to current ESD active in fTree
   // Loads galice.root, the file is identified by replacing "AliESDs" to
   // "galice" in the file path of the ESD file. 
 
   fTree = (TTree *)AliAnalysisTask::GetInputData(0);
-  Int_t iTree = ((TChain *)AliAnalysisTask::GetInputData(0))->GetTreeNumber();
-  if (iTree != fTreeNumber) {
-      DeleteRunLoader();
-      fTreeNumber = iTree;
-  }
-  
       
   if (!fRunLoader) {
     if (!fTree->GetCurrentFile())
index 6bce6f4..e2b08f0 100644 (file)
@@ -24,6 +24,8 @@ class AliAnalysisTaskRL : public AliAnalysisTask {
   AliAnalysisTaskRL();
   AliAnalysisTaskRL(const char *name, const char *title);
   virtual ~AliAnalysisTaskRL();
+  
+  virtual Bool_t Notify();
 
  protected:
   Bool_t        GetEntry(Long64_t ientry);
@@ -35,15 +37,14 @@ class AliAnalysisTaskRL : public AliAnalysisTask {
  private:
   void DeleteRunLoader();
 
-  TTree        *fTree; //pointer to the ESD tree
+  TTree        *fTree; //! pointer to the ESD tree
   AliRunLoader *fRunLoader; //! pointer to the RunLoader if galice.root was opened
   Bool_t        fKinematicsLoaded; // determines if the stack is properly loaded (AliRunLoader::LoadKinematics() succeeded), this is needed because the GetStack returnes a invalid stack object when the function failed
   Bool_t fHeaderLoaded; // determines if the header is properly loaded
-  Int_t  fTreeNumber;   // Number of the tree currently processes (poor man's Notify())
   
   AliAnalysisTaskRL(const AliAnalysisTaskRL&);
   AliAnalysisTaskRL& operator=(const AliAnalysisTaskRL&);
  
-  ClassDef(AliAnalysisTaskRL,1);  // Class describing an analysis task
+  ClassDef(AliAnalysisTaskRL,2);  // Class describing an analysis task
 };
 #endif