#include <Riostream.h>
#include <TFile.h>
#include <TClass.h>
#include <TCollection.h>
#include <TTree.h>
#include <TROOT.h>
#include "AliAnalysisTask.h"
#include "AliAnalysisDataSlot.h"
#include "AliAnalysisDataContainer.h"
#include "AliAnalysisManager.h"
ClassImp(AliAnalysisTask)
AliAnalysisTask::AliAnalysisTask()
:fReady(kFALSE),
fInitialized(kFALSE),
fNinputs(0),
fNoutputs(0),
fOutputReady(NULL),
fPublishedData(NULL),
fInputs(NULL),
fOutputs(NULL),
fBranchNames()
{
}
AliAnalysisTask::AliAnalysisTask(const char *name, const char *title)
:TTask(name,title),
fReady(kFALSE),
fInitialized(kFALSE),
fNinputs(0),
fNoutputs(0),
fOutputReady(NULL),
fPublishedData(NULL),
fInputs(NULL),
fOutputs(NULL),
fBranchNames()
{
fInputs = new TObjArray(2);
fOutputs = new TObjArray(2);
}
AliAnalysisTask::AliAnalysisTask(const AliAnalysisTask &task)
:TTask(task),
fReady(task.fReady),
fInitialized(task.fInitialized),
fNinputs(task.fNinputs),
fNoutputs(task.fNoutputs),
fOutputReady(NULL),
fPublishedData(NULL),
fInputs(NULL),
fOutputs(NULL),
fBranchNames(task.fBranchNames)
{
fInputs = new TObjArray((fNinputs)?fNinputs:2);
fOutputs = new TObjArray((fNoutputs)?fNoutputs:2);
fPublishedData = 0;
Int_t i;
for (i=0; i<fNinputs; i++) fInputs->AddAt(task.GetInputSlot(i),i);
fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
for (i=0; i<fNoutputs; i++) {
fOutputReady[i] = IsOutputReady(i);
fOutputs->AddAt(task.GetOutputSlot(i),i);
}
}
AliAnalysisTask::~AliAnalysisTask()
{
if (fTasks) fTasks->Clear();
if (fInputs) {fInputs->Delete(); delete fInputs;}
if (fOutputs) {fOutputs->Delete(); delete fOutputs;}
}
AliAnalysisTask& AliAnalysisTask::operator=(const AliAnalysisTask& task)
{
if (&task == this) return *this;
TTask::operator=(task);
fReady = task.IsReady();
fInitialized = task.IsInitialized();
fNinputs = task.GetNinputs();
fNoutputs = task.GetNoutputs();
fInputs = new TObjArray((fNinputs)?fNinputs:2);
fOutputs = new TObjArray((fNoutputs)?fNoutputs:2);
fPublishedData = 0;
Int_t i;
for (i=0; i<fNinputs; i++) fInputs->AddAt(new AliAnalysisDataSlot(*task.GetInputSlot(i)),i);
fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2];
for (i=0; i<fNoutputs; i++) {
fOutputReady[i] = IsOutputReady(i);
fOutputs->AddAt(new AliAnalysisDataSlot(*task.GetOutputSlot(i)),i);
}
fBranchNames = task.fBranchNames;
return *this;
}
Bool_t AliAnalysisTask::AreSlotsConnected()
{
fReady = kFALSE;
if (!fNinputs || !fNoutputs) return kFALSE;
Int_t i;
AliAnalysisDataSlot *slot;
for (i=0; i<fNinputs; i++) {
slot = (AliAnalysisDataSlot*)fInputs->At(i);
if (!slot) {
Error("AreSlotsConnected", "Input slot %d of task %s not defined !",i,GetName());
return kFALSE;
}
if (!slot->IsConnected()) return kFALSE;
}
for (i=0; i<fNoutputs; i++) {
slot = (AliAnalysisDataSlot*)fOutputs->At(i);
if (!slot) {
Error("AreSlotsConnected", "Output slot %d of task %s not defined !",i,GetName());
return kFALSE;
}
if (!slot->IsConnected()) return kFALSE;
}
fReady = kTRUE;
return kTRUE;
}
void AliAnalysisTask::CheckNotify(Bool_t init)
{
if (init) fInitialized = kFALSE;
Bool_t single_shot = IsPostEventLoop();
AliAnalysisDataContainer *cinput;
for (Int_t islot=0; islot<fNinputs; islot++) {
cinput = GetInputSlot(islot)->GetContainer();
if (!cinput->GetData() || (single_shot && !cinput->IsPostEventLoop())) {
SetActive(kFALSE);
return;
}
}
SetActive(kTRUE);
if (fInitialized) return;
TDirectory *cursav = gDirectory;
ConnectInputData();
if (cursav) cursav->cd();
fInitialized = kTRUE;
}
Bool_t AliAnalysisTask::CheckPostData() const
{
Bool_t dataPosted = kTRUE;
AliAnalysisDataContainer *coutput;
AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
for (Int_t islot=0; islot<fNoutputs; islot++) {
coutput = GetOutputSlot(islot)->GetContainer();
if (!coutput) continue;
if (coutput->IsExchange() || !mgr->GetOutputs()->FindObject(coutput) || coutput==mgr->GetCommonOutputContainer()) continue;
if (!coutput->GetData()) {
Error("CheckPostData", "Data not posted for slot #%d of task %s (%s)",
islot, GetName(), ClassName());
dataPosted = kFALSE;
}
}
CheckOwnership();
return dataPosted;
}
Bool_t AliAnalysisTask::CheckOwnership() const
{
TObject *outdata;
for (Int_t islot=0; islot<fNoutputs; islot++) {
outdata = GetOutputData(islot);
if (outdata && outdata->InheritsFrom(TCollection::Class())) {
TCollection *coll = (TCollection*)outdata;
if (!coll->IsOwner()) {
Error("CheckOwnership","####### IMPORTANT! ####### \n\n\n\
Task %s (%s) posts a container that is not owner at output #%d. This may apply for other embedded containers. \n\n\
####### FIX YOUR CODE, THIS WILL PRODUCE A FATAL ERROR IN FUTURE! ##########", GetName(), ClassName(), islot);
return kFALSE;
}
}
}
return kTRUE;
}
Bool_t AliAnalysisTask::ConnectInput(Int_t islot, AliAnalysisDataContainer *cont)
{
AliAnalysisDataSlot *input = GetInputSlot(islot);
if (!input) {
Error("ConnectInput","Input slot %i not defined for analysis task %s", islot, GetName());
return kFALSE;
}
if (!input->GetType()->InheritsFrom(cont->GetType())) {
Error("ConnectInput","Data type %s for input %i of task %s not matching container %s of type %s",input->GetType()->GetName(), islot, GetName(), cont->GetName(), cont->GetType()->GetName());
return kFALSE;
}
if (!input->ConnectContainer(cont)) return kFALSE;
cont->AddConsumer(this, islot);
AreSlotsConnected();
return kTRUE;
}
Bool_t AliAnalysisTask::ConnectOutput(Int_t islot, AliAnalysisDataContainer *cont)
{
AliAnalysisDataSlot *output = GetOutputSlot(islot);
if (!output) {
Error("ConnectOutput","Output slot %i not defined for analysis task %s", islot, GetName());
return kFALSE;
}
if (!output->GetType()->InheritsFrom(cont->GetType())) {
Error("ConnectOutput","Data type %s for output %i of task %s not matching container %s of type %s",output->GetType()->GetName(), islot, GetName(), cont->GetName(), cont->GetType()->GetName());
return kFALSE;
}
if (!output->ConnectContainer(cont)) return kFALSE;
cont->SetPostEventLoop(IsPostEventLoop());
cont->SetProducer(this, islot);
AreSlotsConnected();
return kTRUE;
}
void AliAnalysisTask::DefineInput(Int_t islot, TClass *type)
{
AliAnalysisDataSlot *input = new AliAnalysisDataSlot(type, this);
if (fNinputs<islot+1) fNinputs = islot+1;
fInputs->AddAtAndExpand(input, islot);
}
void AliAnalysisTask::DefineOutput(Int_t islot, TClass *type)
{
AliAnalysisDataSlot *output = new AliAnalysisDataSlot(type, this);
if (fNoutputs<islot+1) {
fNoutputs = islot+1;
if (fOutputReady) delete [] fOutputReady;
fOutputReady = new Bool_t[fNoutputs];
memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
}
fOutputs->AddAtAndExpand(output, islot);
}
TClass *AliAnalysisTask::GetInputType(Int_t islot) const
{
AliAnalysisDataSlot *input = GetInputSlot(islot);
if (!input) {
Error("GetInputType","Input slot %d not defined for analysis task %s", islot, GetName());
return NULL;
}
return (input->GetType());
}
TClass *AliAnalysisTask::GetOutputType(Int_t islot) const
{
AliAnalysisDataSlot *output = GetOutputSlot(islot);
if (!output) {
Error("GetOutputType","Output slot %d not defined for analysis task %s", islot, GetName());
return NULL;
}
return (output->GetType());
}
TObject *AliAnalysisTask::GetInputData(Int_t islot) const
{
AliAnalysisDataSlot *input = GetInputSlot(islot);
if (!input) {
Error("GetInputData","Input slot %d not defined for analysis task %s", islot, GetName());
return NULL;
}
return (input->GetData());
}
TObject *AliAnalysisTask::GetOutputData(Int_t islot) const
{
AliAnalysisDataSlot *output = GetOutputSlot(islot);
if (!output) {
Error("GetOutputData","Input slot %d not defined for analysis task %s", islot, GetName());
return NULL;
}
return (output->GetData());
}
char *AliAnalysisTask::GetBranchAddress(Int_t islot, const char *branch) const
{
return (char *)GetInputSlot(islot)->GetBranchAddress(branch);
}
Bool_t AliAnalysisTask::SetBranchAddress(Int_t islot, const char *branch, void *address) const
{
return GetInputSlot(islot)->SetBranchAddress(branch, address);
}
void AliAnalysisTask::EnableBranch(Int_t islot, const char *bname) const
{
AliAnalysisDataSlot *input = GetInputSlot(islot);
if (!input || !input->GetType()->InheritsFrom(TTree::Class())) {
Error("EnableBranch", "Wrong slot type #%d for task %s: not TTree-derived type", islot, GetName());
return;
}
TTree *tree = (TTree*)input->GetData();
if (!strcmp(bname, "*")) {
tree->SetBranchStatus("*",1);
return;
}
AliAnalysisDataSlot::EnableBranch(bname, tree);
}
void AliAnalysisTask::FinishTaskOutput()
{
}
void AliAnalysisTask::ConnectInputData(Option_t *)
{
}
void AliAnalysisTask::LocalInit()
{
}
void AliAnalysisTask::CreateOutputObjects()
{
}
TFile *AliAnalysisTask::OpenFile(Int_t iout, Option_t *option) const
{
if (iout<0 || iout>=fNoutputs) {
Error("OpenFile", "No output slot for task %s with index %d", GetName(), iout);
return NULL;
}
AliAnalysisDataContainer *cont = GetOutputSlot(iout)->GetContainer();
return AliAnalysisManager::OpenFile(cont, option);
}
Bool_t AliAnalysisTask::Notify()
{
return kTRUE;
}
Bool_t AliAnalysisTask::NotifyBinChange()
{
return kTRUE;
}
void AliAnalysisTask::Terminate(Option_t *)
{
}
Bool_t AliAnalysisTask::PostData(Int_t iout, TObject *data, Option_t *option)
{
fPublishedData = 0;
AliAnalysisDataSlot *output = GetOutputSlot(iout);
if (!output) {
Error("PostData","Output slot %i not defined for analysis task %s", iout, GetName());
return kFALSE;
}
if (!output->IsConnected()) {
Error("PostData","Output slot %i of analysis task %s not connected to any data container", iout, GetName());
return kFALSE;
}
if (!fOutputReady) {
fOutputReady = new Bool_t[fNoutputs];
memset(fOutputReady, 0, fNoutputs*sizeof(Bool_t));
}
fOutputReady[iout] = kTRUE;
fPublishedData = data;
return (output->GetContainer()->SetData(data, option));
}
void AliAnalysisTask::SetUsed(Bool_t flag)
{
if (TestBit(kTaskUsed)==flag) return;
TObject::SetBit(kTaskUsed,flag);
Int_t nd = fTasks->GetSize();
AliAnalysisTask *task;
for (Int_t i=0; i<nd; i++) {
task = (AliAnalysisTask*)fTasks->At(i);
task->SetUsed(flag);
}
}
void AliAnalysisTask::Reset()
{
fActive = kFALSE;
fHasExecuted = kFALSE;
Int_t islot;
AliAnalysisDataContainer *cont;
for (islot=0; islot<fNinputs; islot++) {
cont = GetInputSlot(islot)->GetContainer();
if (cont && cont->IsExchange()) cont->Reset();
}
}
Bool_t AliAnalysisTask::CheckCircularDeps()
{
if (IsChecked()) return kTRUE;
SetChecked();
TList *tasks = GetListOfTasks();
Int_t ntasks = tasks->GetSize();
AliAnalysisTask *task;
for (Int_t i=0; i<ntasks; i++) {
task = (AliAnalysisTask*)tasks->At(i);
if (task->CheckCircularDeps()) return kTRUE;
}
SetChecked(kFALSE);
return kFALSE;
}
Bool_t AliAnalysisTask::ProducersTouched() const
{
Int_t islot;
AliAnalysisDataContainer *cont;
for (islot=0; islot<fNinputs; islot++) {
cont = GetInputSlot(islot)->GetContainer();
if (cont && !cont->IsTouched()) return kFALSE;
}
return kTRUE;
}
void AliAnalysisTask::PrintTask(Option_t *option, Int_t indent) const
{
Int_t islot;
AliAnalysisDataContainer *cont;
if (fActive) return;
if (!ProducersTouched()) return;
TString opt(option);
opt.ToLower();
Bool_t dep = (opt.Contains("dep"))?kTRUE:kFALSE;
TString ind;
for (Int_t i=0; i<indent; i++) ind += " ";
if (!dep || (dep && IsChecked())) {
printf("______________________________________________________________________________\n");
printf("%s\n", Form("%stask: %s ACTIVE=%i POST_LOOP=%i", ind.Data(), GetName(),IsActive(),IsPostEventLoop()));
if (dep) const_cast<AliAnalysisTask*>(this)->SetChecked(kFALSE);
else {
for (islot=0; islot<fNinputs; islot++) {
printf("%s", Form("%s INPUT #%i: %s <- ",ind.Data(),islot, GetInputType(islot)->GetName()));
cont = GetInputSlot(islot)->GetContainer();
if (cont) printf(" [%s]\n", cont->GetName());
else printf(" [NO CONTAINER]\n");
}
for (islot=0; islot<fNoutputs; islot++) {
printf("%s", Form("%s OUTPUT #%i: %s -> ",ind.Data(),islot, GetOutputType(islot)->GetName()));
cont = GetOutputSlot(islot)->GetContainer();
if (cont) printf(" [%s]\n", cont->GetName());
else printf(" [NO CONTAINER]\n");
}
}
}
((AliAnalysisTask*)this)->SetActive(kTRUE);
PrintContainers(option, indent+3);
if (!fBranchNames.IsNull()) printf("%sRequested branches: %s\n", ind.Data(), fBranchNames.Data());
}
void AliAnalysisTask::PrintContainers(Option_t *option, Int_t indent) const
{
AliAnalysisDataContainer *cont;
TString ind;
for (Int_t i=0; i<indent; i++) ind += " ";
Int_t islot;
for (islot=0; islot<fNoutputs; islot++) {
cont = GetOutputSlot(islot)->GetContainer();
if (cont) cont->PrintContainer(option, indent);
}
}
void AliAnalysisTask::SetPostEventLoop(Bool_t flag)
{
TObject::SetBit(kTaskPostEventLoop,flag);
AliAnalysisDataContainer *cont;
Int_t islot;
for (islot=0; islot<fNoutputs; islot++) {
cont = GetOutputSlot(islot)->GetContainer();
if (cont) cont->SetPostEventLoop(flag);
}
}
void AliAnalysisTask::GetBranches(const char *type, TString &result) const
{
result = "";
if (fBranchNames.IsNull()) return;
Int_t index1 = fBranchNames.Index(type);
if (index1<0) return;
index1 += 1+strlen(type);
Int_t index2 = fBranchNames.Index(" ", index1);
if (index2<0) index2 = fBranchNames.Length();
result = fBranchNames(index1, index2-index1);
}