X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=ANALYSIS%2FAliAnalysisTask.cxx;h=1d5b591e46ba09a7c5ec2d802ca8f1c465fbdc20;hb=226abfec1d2bd6abafb2842a110351dbe4f935dd;hp=68cd15b927afd758ca97609210035473a830ab38;hpb=d3106602d3c855aa5df55fbfcee909b983a83f4e;p=u%2Fmrichter%2FAliRoot.git diff --git a/ANALYSIS/AliAnalysisTask.cxx b/ANALYSIS/AliAnalysisTask.cxx index 68cd15b927a..1d5b591e46b 100644 --- a/ANALYSIS/AliAnalysisTask.cxx +++ b/ANALYSIS/AliAnalysisTask.cxx @@ -45,52 +45,115 @@ // AliAnalysisDataContainer *cont) // To connect a slot to a data container, the data types declared by both must // match. +// +// The method ConnectInputData() has to be overloaded by the derived class in order to +// set the branch address or connect to a branch address in case the input +// slots are connected to trees. +// Example: +// MyAnalysisTask::ConnectInputData(Option_t *) +// { +// // One should first check if the branch address was taken by some other task +// char ** address = (char **)GetBranchAddress(0, "ESD"); +// if (address) { +// fESD = (AliESD*)(*address); +// } else { +// fESD = new AliESD(); +// SetBranchAddress(0, "ESD", &fESD); +// } +// } +// +// The method LocalInit() may be implemented to call locally (on the client) +// all initialization methods of the class. It is not mandatory and was created +// in order to minimize the complexity and readability of the analysis macro. +// DO NOT create in this method the histigrams or task output objects that will +// go in the task output containers. Use CreateOutputObjects for that. +// +// The method CreateOutputObjects() has to be implemented an will contain the +// objects that should be created only once per session (e.g. output +// histograms) +// +// void MyAnalysisTask::CreateOutputObjects() +//{ + // create histograms +// fhPt = new TH1F("fhPt","This is the Pt distribution",15,0.1,3.1); +// fhPt->SetStats(kTRUE); +// fhPt->GetXaxis()->SetTitle("P_{T} [GeV]"); +// fhPt->GetYaxis()->SetTitle("#frac{dN}{dP_{T}}"); +// fhPt->GetXaxis()->SetTitleColor(1); +// fhPt->SetMarkerStyle(kFullCircle); +// } +// +// The method Terminate() will be called by the framework once at the end of +// data processing. Overload this if needed. DO NOT ASSUME that the pointers +// to histograms defined in CreateOutputObjects() are valid, since this is +// not true in case of PROOF. Restore the pointer values like: +// +//void MyAnalysisTask::Terminate(Option_t *) +//{ +// fhPt = (TH1F*)GetOutputData(0); +// ... +//} + +// //============================================================================== -#include "TClass.h" +#include +#include +#include +#include +#include -#include "AliLog.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) { // Default constructor. - fReady = kFALSE; - fNinputs = 0; - fNoutputs = 0; - fOutputReady = 0; - fPublishedData = 0; - fInputs = 0; - fOutputs = 0; } //______________________________________________________________________________ AliAnalysisTask::AliAnalysisTask(const char *name, const char *title) - :TTask(name,title) + :TTask(name,title), + fReady(kFALSE), + fInitialized(kFALSE), + fNinputs(0), + fNoutputs(0), + fOutputReady(NULL), + fPublishedData(NULL), + fInputs(NULL), + fOutputs(NULL) { -// Named constructor. - fReady = kFALSE; - fNinputs = 0; - fNoutputs = 0; - fOutputReady = 0; - fPublishedData = 0; +// Constructor. fInputs = new TObjArray(2); fOutputs = new TObjArray(2); } //______________________________________________________________________________ AliAnalysisTask::AliAnalysisTask(const AliAnalysisTask &task) - :TTask(task) + :TTask(task), + fReady(task.fReady), + fInitialized(task.fInitialized), + fNinputs(task.fNinputs), + fNoutputs(task.fNoutputs), + fOutputReady(NULL), + fPublishedData(NULL), + fInputs(NULL), + fOutputs(NULL) { // Copy ctor. - fReady = task.IsReady(); - fNinputs = task.GetNinputs(); - fNoutputs = task.GetNoutputs(); fInputs = new TObjArray((fNinputs)?fNinputs:2); fOutputs = new TObjArray((fNoutputs)?fNoutputs:2); fPublishedData = 0; @@ -107,6 +170,7 @@ AliAnalysisTask::AliAnalysisTask(const AliAnalysisTask &task) AliAnalysisTask::~AliAnalysisTask() { // Dtor. + if (fTasks) fTasks->Clear(); if (fInputs) {fInputs->Delete(); delete fInputs;} if (fOutputs) {fOutputs->Delete(); delete fOutputs;} } @@ -115,22 +179,22 @@ AliAnalysisTask::~AliAnalysisTask() AliAnalysisTask& AliAnalysisTask::operator=(const AliAnalysisTask& task) { // Assignment - if (&task != this) { - TTask::operator=(task); - fReady = task.IsReady(); - 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; iAddAt(task.GetInputSlot(i),i); - fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2]; - for (i=0; iAddAt(task.GetOutputSlot(i),i); - } - } + 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; iAddAt(new AliAnalysisDataSlot(*task.GetInputSlot(i)),i); + fOutputReady = new Bool_t[(fNoutputs)?fNoutputs:2]; + for (i=0; iAddAt(new AliAnalysisDataSlot(*task.GetOutputSlot(i)),i); + } return *this; } @@ -145,7 +209,7 @@ Bool_t AliAnalysisTask::AreSlotsConnected() for (i=0; iAt(i); if (!slot) { - AliError(Form("Input slot %i of task %s not defined !",i,GetName())); + Error("AreSlotsConnected", "Input slot %d of task %s not defined !",i,GetName()); return kFALSE; } if (!slot->IsConnected()) return kFALSE; @@ -153,7 +217,7 @@ Bool_t AliAnalysisTask::AreSlotsConnected() for (i=0; iAt(i); if (!slot) { - AliError(Form("Output slot %i of task %s not defined !",i,GetName())); + Error("AreSlotsConnected", "Output slot %d of task %s not defined !",i,GetName()); return kFALSE; } if (!slot->IsConnected()) return kFALSE; @@ -163,18 +227,27 @@ Bool_t AliAnalysisTask::AreSlotsConnected() } //______________________________________________________________________________ -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; + Bool_t single_shot = IsPostEventLoop(); + AliAnalysisDataContainer *cinput; for (Int_t islot=0; islotGetContainer(); + 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; } //______________________________________________________________________________ @@ -183,13 +256,12 @@ Bool_t AliAnalysisTask::ConnectInput(Int_t islot, AliAnalysisDataContainer *cont // Connect an input slot to a data container. AliAnalysisDataSlot *input = GetInputSlot(islot); if (!input) { - AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName())); + Error("ConnectInput","Input slot %i not defined for analysis task %s", islot, GetName()); return kFALSE; } // Check type matching if (!input->GetType()->InheritsFrom(cont->GetType())) { - AliError(Form("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())); + 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; } // Connect the slot to the container as input @@ -206,17 +278,18 @@ Bool_t AliAnalysisTask::ConnectOutput(Int_t islot, AliAnalysisDataContainer *con // Connect an output slot to a data container. AliAnalysisDataSlot *output = GetOutputSlot(islot); if (!output) { - AliError(Form("Output slot %i not defined for analysis task %s", islot, GetName())); + Error("ConnectOutput","Output slot %i not defined for analysis task %s", islot, GetName()); return kFALSE; } // Check type matching if (!output->GetType()->InheritsFrom(cont->GetType())) { - AliError(Form("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())); + 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; } // Connect the slot to the container as output if (!output->ConnectContainer(cont)) return kFALSE; + // Set event loop type the same as for the task + cont->SetPostEventLoop(IsPostEventLoop()); // Declare this as the data producer cont->SetProducer(this, islot); AreSlotsConnected(); @@ -229,17 +302,13 @@ void AliAnalysisTask::DefineInput(Int_t islot, TClass *type) // Define an input slot and its type. AliAnalysisDataSlot *input = new AliAnalysisDataSlot(type, this); if (fNinputsAddAt(input, islot); + fInputs->AddAtAndExpand(input, islot); } //______________________________________________________________________________ void AliAnalysisTask::DefineOutput(Int_t islot, TClass *type) { // Define an output slot and its type. - if (islot<0) { - AliError(Form("Cannot define negative output slot number for task %s", GetName())); - return; - } AliAnalysisDataSlot *output = new AliAnalysisDataSlot(type, this); if (fNoutputsAddAt(output, islot); + fOutputs->AddAtAndExpand(output, islot); } //______________________________________________________________________________ @@ -256,7 +325,7 @@ TClass *AliAnalysisTask::GetInputType(Int_t islot) const // Retreive type of a given input slot. AliAnalysisDataSlot *input = GetInputSlot(islot); if (!input) { - AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName())); + Error("GetInputType","Input slot %d not defined for analysis task %s", islot, GetName()); return NULL; } return (input->GetType()); @@ -268,7 +337,7 @@ TClass *AliAnalysisTask::GetOutputType(Int_t islot) const // Retreive type of a given output slot. AliAnalysisDataSlot *output = GetOutputSlot(islot); if (!output) { - AliError(Form("Output slot %i not defined for analysis task %s", islot, GetName())); + Error("GetOutputType","Output slot %d not defined for analysis task %s", islot, GetName()); return NULL; } return (output->GetType()); @@ -281,12 +350,144 @@ TObject *AliAnalysisTask::GetInputData(Int_t islot) const // the object has to be statically cast to the appropriate type. AliAnalysisDataSlot *input = GetInputSlot(islot); if (!input) { - AliError(Form("Input slot %i not defined for analysis task %s", islot, GetName())); + 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 +{ +// Retreive output data for a slot. Normally called in UserTask::Terminate to +// get a valid pointer to data even in case of Proof. + 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 +{ +// 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::EnableBranch(Int_t islot, const char *bname) const +{ +// Call this in ConnectInputData() to enable only the branches needed by this +// task. "*" will enable everything. + 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() +{ +// Optional method that is called in SlaveTerminate phase. +// Used for calling aditional methods just after the last event was processed ON +// THE WORKING NODE. The call is made also in local case. +// Do NOT delete output objects here since they will have to be sent for +// merging in PROOF mode - use class destructor for cleanup. +} + +//______________________________________________________________________________ +void AliAnalysisTask::ConnectInputData(Option_t *) +{ +// Overload and connect your branches here. +} + +//______________________________________________________________________________ +void AliAnalysisTask::LocalInit() +{ +// The method LocalInit() may be implemented to call locally (on the client) +// all initialization methods of the class. It is not mandatory and was created +// in order to minimize the complexity and readability of the analysis macro. +// DO NOT create in this method the histigrams or task output objects that will +// go in the task output containers. Use CreateOutputObjects for that. +} + +//______________________________________________________________________________ +void AliAnalysisTask::CreateOutputObjects() +{ +// Called once per task either in PROOF or local mode. Overload to put some +// task initialization and/or create your output objects here. +} + +//______________________________________________________________________________ +TFile *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) { + Error("OpenFile", "No output slot for task %s with index %d", GetName(), iout); + return NULL; + } + // Method delegated to the analysis manager (A.G. 02/11/09) + AliAnalysisDataContainer *cont = GetOutputSlot(iout)->GetContainer(); + return AliAnalysisManager::OpenFile(cont, option); +} + +//______________________________________________________________________________ +Bool_t AliAnalysisTask::Notify() +{ +// Overload this IF you need to treat input file change. + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t AliAnalysisTask::NotifyBinChange() +{ +// Overload this IF you need to treat bin change in event mixing. + return kTRUE; +} + +//______________________________________________________________________________ +void AliAnalysisTask::Terminate(Option_t *) +{ +// Method called by the framework at the end of data processing. +} + //______________________________________________________________________________ Bool_t AliAnalysisTask::PostData(Int_t iout, TObject *data, Option_t *option) { @@ -297,11 +498,11 @@ Bool_t AliAnalysisTask::PostData(Int_t iout, TObject *data, Option_t *option) fPublishedData = 0; AliAnalysisDataSlot *output = GetOutputSlot(iout); if (!output) { - AliError(Form("Output slot %i not defined for analysis task %s", iout, GetName())); + Error("PostData","Output slot %i not defined for analysis task %s", iout, GetName()); return kFALSE; } if (!output->IsConnected()) { - AliError(Form("Output slot %i of analysis task %s not connected to any data container", iout, GetName())); + Error("PostData","Output slot %i of analysis task %s not connected to any data container", iout, GetName()); return kFALSE; } if (!fOutputReady) { @@ -358,7 +559,7 @@ void AliAnalysisTask::PrintTask(Option_t *option, Int_t indent) const AliAnalysisDataContainer *cont; for (Int_t i=0; iSetChecked(kFALSE); else { for (islot=0; islotGetContainer(); - cont->PrintContainer(option, indent); + if (cont) cont->PrintContainer(option, indent); + } +} + +//______________________________________________________________________________ +void AliAnalysisTask::SetPostEventLoop(Bool_t flag) +{ +// Set the task execution mode - run after event loop or not. All output +// containers of this task will get the same type. + TObject::SetBit(kTaskPostEventLoop,flag); + AliAnalysisDataContainer *cont; + Int_t islot; + for (islot=0; islotGetContainer(); + if (cont) cont->SetPostEventLoop(flag); } } +