AliAnalysisDataContainer::AliAnalysisDataContainer() : TNamed(),
fDataReady(kFALSE),
fOwnedData(kFALSE),
- fFileName(),
+ fFile(NULL),
fData(NULL),
fType(NULL),
fProducer(NULL),
:TNamed(name,""),
fDataReady(kFALSE),
fOwnedData(kTRUE),
- fFileName(),
+ fFile(NULL),
fData(NULL),
fType(type),
fProducer(NULL),
:TNamed(cont),
fDataReady(cont.fDataReady),
fOwnedData(kFALSE),
- fFileName(cont.fFileName),
+ fFile(cont.fFile),
fData(cont.fData),
fType(cont.fType),
fProducer(cont.fProducer),
// 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;
+ }
}
//______________________________________________________________________________
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;
}
//______________________________________________________________________________
-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;
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++) {
}
//______________________________________________________________________________
-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;
#endif
class TClass;
-class TString;
+class TFile;
class TObjArray;
class AliAnalysisTask;
class AliESD;
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();
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
//==============================================================================
#include "TClass.h"
+#include "TTree.h"
#include "AliLog.h"
#include "AliAnalysisDataSlot.h"
return kTRUE;
}
+//______________________________________________________________________________
+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
{
// 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;}
//==============================================================================
#include "TClass.h"
+#include "TFile.h"
+#include "TTree.h"
#include "AliLog.h"
#include "AliAnalysisManager.h"
//______________________________________________________________________________
AliAnalysisManager::AliAnalysisManager() : TSelector(),
+ fTree(NULL),
fInitOK(kFALSE),
fContainers(NULL),
fInputs(NULL),
//______________________________________________________________________________
AliAnalysisManager::AliAnalysisManager(const AliAnalysisManager& other)
:TSelector(other),
+ fTree(NULL),
fInitOK(kFALSE),
fContainers(NULL),
fInputs(NULL),
// Assignment
if (&other != this) {
TSelector::operator=(other);
+ fTree = other.fTree;
fInitOK = other.fInitOK;
fContainers = new TObjArray(*other.fContainers);
fInputs = new TObjArray(*other.fInputs);
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
// 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;
}
//______________________________________________________________________________
// 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());
+ }
}
//______________________________________________________________________________
// 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();
}
//______________________________________________________________________________
// 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 !");
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);
}
return kFALSE;
}
}
+ fInitOK = kTRUE;
return kTRUE;
}
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);
+ }
}
//______________________________________________________________________________
// 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;}
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
//==============================================================================
// AliAnalysysRLContainer -
+//
+//
+//
//==============================================================================
#include "AliAnalysisRLContainer.h"
// 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"
//______________________________________________________________________________
AliAnalysisTask::AliAnalysisTask()
:fReady(kFALSE),
+ fInitialized(kFALSE),
fNinputs(0),
fNoutputs(0),
fOutputReady(NULL),
AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
:TTask(name,title),
fReady(kFALSE),
+ fInitialized(kFALSE),
fNinputs(0),
fNoutputs(0),
fOutputReady(NULL),
AliAnalysisTask::AliAnalysisTask(const AliAnalysisTask &task)
:TTask(task),
fReady(task.fReady),
+ fInitialized(task.fInitialized),
fNinputs(task.fNinputs),
fNoutputs(task.fNoutputs),
fOutputReady(NULL),
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);
}
//______________________________________________________________________________
-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);
}
}
SetActive(kTRUE);
+ if (fInitialized) return;
+ TDirectory *cursav = gDirectory;
+ Init();
+ if (cursav) cursav->cd();
+ fInitialized = kTRUE;
}
//______________________________________________________________________________
return (input->GetData());
}
+//______________________________________________________________________________
+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)
{
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
--- /dev/null
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class AliAnalysisRLContainer+;
+
+#endif
#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+;
--- /dev/null
+SRCS= AliAnalysisRLContainer.cxx
+
+HDRS= $(SRCS:.cxx=.h)
+
+DHDR:=AnalysisExtraLinkDef.h
+
+EXPORT:=$(HDRS)
-SRCS= AliAnalysisDataContainer.cxx AliAnalysisRLContainer.cxx \
+SRCS= AliAnalysisDataContainer.cxx \
AliAnalysisTask.cxx AliAnalysisDataSlot.cxx AliAnalysisManager.cxx
HDRS= $(SRCS:.cxx=.h)