This method has to be called INSIDE the user redefined CreateOutputObjects
authoragheata <agheata@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 3 May 2007 11:52:02 +0000 (11:52 +0000)
committeragheata <agheata@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 3 May 2007 11:52:02 +0000 (11:52 +0000)
method, before creating each object corresponding to the output containers
that are to be written to a file. This need to be done in general for the big output
objects that may not fit memory during processing.
- 'option' is the file opening option.
========================================================================
NOTE !: The method call will be ignored in PROOF mode, in which case the
results have to be streamed back to the client and written just before Terminate()
========================================================================

Example:

void MyAnaTask::CreateOutputObjects() {
   OpenFile(0);   // Will open the file for the object to be written at output #0
   fAOD = new TTree("AOD for D0toKPi");
   OpenFile(1);
   // now some histos that should go in the file of the second output container
   fHist1 = new TH1F("my quality check hist1",...);
   fHist2 = new TH2F("my quality check hist2",...);
}

ANALYSIS/AliAnalysisDataContainer.cxx
ANALYSIS/AliAnalysisDataContainer.h
ANALYSIS/AliAnalysisManager.cxx
ANALYSIS/AliAnalysisTask.cxx
ANALYSIS/AliAnalysisTask.h

index 004491f..a3597c2 100644 (file)
@@ -66,6 +66,7 @@ AliAnalysisDataContainer::AliAnalysisDataContainer() : TNamed(),
                           fConsumers(NULL)
 {
 // Dummy ctor.
+   TObject::SetBit(kContEvtByEvt, kTRUE);
 }
 
 //______________________________________________________________________________
@@ -81,6 +82,7 @@ AliAnalysisDataContainer::AliAnalysisDataContainer(const char *name, TClass *typ
 {
 // Default constructor.
    SetTitle(fType->GetName());
+   TObject::SetBit(kContEvtByEvt, kTRUE);
 }
 
 //______________________________________________________________________________
index 5e58383..011ff4b 100644 (file)
@@ -38,6 +38,9 @@ enum ENotifyMessage {
    kSaveData,
    kFileChange
 };   
+enum EAnalysisContainerFlags {
+   kContEvtByEvt
+};     
    AliAnalysisDataContainer();
    AliAnalysisDataContainer(const AliAnalysisDataContainer &cont);
    AliAnalysisDataContainer(const char *name, TClass *type);
@@ -56,6 +59,7 @@ enum ENotifyMessage {
    void                      ResetDataReady()     {fDataReady = kFALSE;}
    virtual Bool_t            SetData(TObject *data, Option_t *option="");
    void                      SetDataOwned(Bool_t flag) {fOwnedData = flag;}
+   void                      SetEventByEvent(Bool_t flag=kTRUE) {TObject::SetBit(kContEvtByEvt,flag);}
    void                      SetFileName(const char *filename) {fFileName = filename;}
    void                      SetProducer(AliAnalysisTask *prod, Int_t islot);
    void                      AddConsumer(AliAnalysisTask *cons, Int_t islot);
@@ -65,6 +69,7 @@ enum ENotifyMessage {
    void                      ImportData(AliAnalysisDataWrapper *pack);
    // Container status checking
    Bool_t                    IsDataReady() const  {return fDataReady;}
+   Bool_t                    IsEventByEvent() const {return TObject::TestBit(kContEvtByEvt);}
    Bool_t                    IsOwnedData() const  {return fOwnedData;}
    Bool_t                    ClientsExecuted() const;
    Bool_t                    HasConsumers() const {return (fConsumers != 0);}
index f235c35..9bb0f22 100644 (file)
@@ -208,8 +208,11 @@ void AliAnalysisManager::SlaveBegin(TTree *tree)
    TIter next(fTasks);
    AliAnalysisTask *task;
    // Call CreateOutputObjects for all tasks
-   while ((task=(AliAnalysisTask*)next())) 
+   while ((task=(AliAnalysisTask*)next())) {
+      TDirectory *curdir = gDirectory;
       task->CreateOutputObjects();
+      if (curdir) curdir->cd();
+   }   
    if (fMode == kLocalAnalysis) Init(tree);   
    if (fDebug > 1) {
       cout << "<-AliAnalysisManager::SlaveBegin()" << endl;
@@ -594,7 +597,11 @@ void AliAnalysisManager::StartAnalysis(const char *type, TTree *tree)
             TIter next(fTasks);
             AliAnalysisTask *task;
             // Call CreateOutputObjects for all tasks
-            while ((task=(AliAnalysisTask*)next())) task->CreateOutputObjects();
+            while ((task=(AliAnalysisTask*)next())) {
+               TDirectory *curdir = gDirectory;
+               task->CreateOutputObjects();
+               if (curdir) curdir->cd();
+            }   
             ExecAnalysis();
             Terminate();
             return;
index 2f8db1b..e901b9d 100644 (file)
 //==============================================================================
 
 #include <Riostream.h>
-#include <TDirectory.h>
+#include <TFile.h>
 #include <TClass.h>
 
 #include "AliAnalysisTask.h"
 #include "AliAnalysisDataSlot.h"
 #include "AliAnalysisDataContainer.h"
+#include "AliAnalysisManager.h"
 
 ClassImp(AliAnalysisTask)
 
@@ -119,6 +120,7 @@ AliAnalysisTask::AliAnalysisTask()
                  fOutputs(NULL)
 {
 // Default constructor.
+   TObject::SetBit(kTaskEvtByEvt, kTRUE);
 }
 
 //______________________________________________________________________________
@@ -134,6 +136,7 @@ AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
                  fOutputs(NULL)                 
 {
 // Constructor.
+   TObject::SetBit(kTaskEvtByEvt, kTRUE);
    fInputs      = new TObjArray(2);
    fOutputs     = new TObjArray(2);
 }
@@ -401,6 +404,36 @@ void AliAnalysisTask::CreateOutputObjects()
 }
 
 //______________________________________________________________________________
+void AliAnalysisTask::OpenFile(Int_t iout, Option_t *option) const
+{
+// This method has to be called INSIDE the user redefined CreateOutputObjects
+// method, before creating each object corresponding to the output containers
+// that are to be written to a file. This need to be done in general for the big output
+// objects that may not fit memory during processing. 
+// - 'option' is the file opening option.
+//=========================================================================
+// NOTE !: The method call will be ignored in PROOF mode, in which case the 
+// results have to be streamed back to the client and written just before Terminate()
+//=========================================================================
+//
+// Example:
+// void MyAnaTask::CreateOutputObjects() {
+//    OpenFile(0);   // Will open the file for the object to be written at output #0
+//    fAOD = new TTree("AOD for D0toKPi");
+//    OpenFile(1);
+// now some histos that should go in the file of the second output container
+//    fHist1 = new TH1F("my quality check hist1",...);
+//    fHist2 = new TH2F("my quality check hist2",...);
+// }
+   
+   if (iout<0 || iout>=fNoutputs) return;
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   if (!mgr || mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis) return;
+   AliAnalysisDataContainer *cont = GetOutputSlot(iout)->GetContainer();
+   if (strlen(cont->GetFileName())) new TFile(cont->GetFileName(), option);
+}
+
+//______________________________________________________________________________
 Bool_t AliAnalysisTask::Notify()
 {
 // Overload this IF you need to treat input file change.
index 34c4c2c..d92f918 100644 (file)
@@ -29,8 +29,9 @@ class AliAnalysisTask : public TTask {
   enum EAnalysisTaskFlags {
     kTaskUsed    = BIT(14),
     kTaskZombie  = BIT(15),
-    kTaskChecked = BIT(16)
-  };   
+    kTaskChecked = BIT(16),
+    kTaskEvtByEvt = BIT(17)
+  };
 
  protected:
   Bool_t                    fReady;         // Flag if the task is ready
@@ -65,8 +66,9 @@ class AliAnalysisTask : public TTask {
   // === 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 CreateOutputObjects IF THE OUTPUT IS TO BE WRITTEN AT OUTPUT IOUT
-//  void                      OpenFile(Int_t iout, const char *name, Option_t *option) const;
+  // === CALL THIS IN CreateOutputObjects BEFORE CREATING THE OBJECT FOR EACH 
+  // OUTPUT IOUT THAT HAS TO BE WRITTEN TO A FILE
+  void                      OpenFile(Int_t iout, Option_t *option="") const;
   
 public:  
   AliAnalysisTask();
@@ -105,6 +107,7 @@ public:
   TObject                  *GetOutputData(Int_t islot) const;  
   Bool_t                    IsOutputReady(Int_t islot) const {return fOutputReady[islot];}
   Bool_t                    IsChecked() const  {return TObject::TestBit(kTaskChecked);}
+  Bool_t                    IsExecPerEvent() const {return TObject::TestBit(kTaskEvtByEvt);}
   Bool_t                    IsInitialized() const  {return fInitialized;}
   Bool_t                    IsReady() const  {return fReady;}
   Bool_t                    IsUsed() const   {return TObject::TestBit(kTaskUsed);}
@@ -112,6 +115,7 @@ public:
   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                      SetExecPerEvent(Bool_t flag=kTRUE) {TObject::SetBit(kTaskEvtByEvt,flag);}
   void                      SetUsed(Bool_t flag=kTRUE);
   void                      SetZombie(Bool_t flag=kTRUE) {TObject::SetBit(kTaskZombie,flag);}
   // Main task execution