- 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 bc4bfa790b9e4f69f17e1454dc2b29521695dcec..8cb375cea76481accb4ae7e5fc4fc4587c778e53 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 0aa772a5a2ddc3c195efa43128de4a35b66a8342..004491f031b35d88c47568461e6169603a336201 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 e5978a28108a4e80b9ab08ec1612a83634eb0383..5e583830c4e380ef96277c53edad6e89b9e280ab 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 379f9fa520b876c3b21c27faefabe8fbdcf727be..de55e65e451fb0d6fc902ba72138c3a4015d26f4 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 ab8e0352435d904ef559c621c5214169e0d8f9bb..7e29eb7b95fd9f91f72bdb548aa163437edafee5 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 0085423c9ced5d6c5d8a2fb1fb17ba979a031714..a6021dcd7229ace2022baf2b039ca30e1e36576f 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 a585053ad12c540dce33884d789268f2b959a92f..0cd1ac115ef3cbc26b0215d2c8674ec942c08e52 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 93c4e42c01d7a8006a218af320edcce4adcb7390..a3b41f619a9e20d683653217b87e845a15e6efff 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 2efecdfb76055aea4669df7973e9efd0d780eff3..b35021ceeb7b56b441bcbd00d52c9d99986a0855 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 698890cb1a09f91029d97d9faa28aa85845c1526..2303583662e1ee75e3c4b8d696fdf0f87f39674b 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 993bf068ba233335b76c5e54a4a6d09def25f7e0..04c97d56db964d183aa1d6bd9bc1dec2cd386375 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
   //
@@ -69,6 +69,13 @@ Bool_t AliAnalysisTaskRL::GetEntry(Long64_t ientry) {
   return kTRUE;
 }
 
+//___________________________________________________________________________
+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
@@ -76,12 +83,6 @@ AliRunLoader *AliAnalysisTaskRL::GetRunLoader() {
   // "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 6bce6f493fd15c9e6a50bcba056f326424577de4..e2b08f0143d8c901ad9abe3701192619875ae0ff 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