2. Writing your class
2.1 Creating a template for your class
All analysis task are derived from AliAnalysisTaskSE, this provides us with a 'common framework' in which to do analysis (i.e. all analyses have the same base methods)..
AliAnalysisTaskSE::AliAnalysisTaskSE();
AliAnalysisTaskSE::AliAnalysisTaskSE(const char *);
AliAnalysisTaskSE::~AliAnalysisTaskSE();
AliAnalysisTaskSE::UserCreateOutputObjects(); // histos
AliAnalysisTaskSE::UserExec (Option_t *); // analysis
AliAnalysisTaskSE::Terminate (Option_t *); // finish
We'll use a fixed format for writing our class
- The header file(.h) which contains function prototypes
- The implementation file(.cxx), in which the code is implemented
- An AddTask.C macro which creates an instance of your class and configures it
Let's start by looking at our header, as here all functions are defined
# ifndef AliAnalysisTaskMyTask_H
# define AliAnalysisTaskMyTask_H
class AliAnalysisTaskMyTask : public AliAnalysisTaskSE
{
public :
// two class constructors
AliAnalysisTaskMyTask();
AliAnalysisTaskMyTask(const char *name);
// class destructor
virtual ~AliAnalysisTaskMyTask();
// called once at beginning of runtime
virtual void UserCreateOutputObjects();
// called for each event
virtual void UserExec(Option_t * option);
// called at end of analysis
virtual void Terminate(Option_t * option);
ClassDef (AliAnalysisTaskMyTask, 1);
};
# endif
2.2 Adding our histogram
Let's start filling in the blanks, and add a histogram, an output list and some more...
2.2.1 Changes to the header
Class members must be defined in the header
...
class AliAnalysisTaskMyTask : public AliAnalysisTaskSE
...
private :
AliAODEvent* fAOD; //! input event
TList* fOutputList; //! output list
TH1F* fHistPt; //! dummy histogram
...
- Pointers to objects that are initialized at run-time (the User... methods) should have //! at the end - we will explain later
- We use an output list to have one common output object, rather than many
2.2.2 Implementation to the .cxx
ROOT requires two class constructors ... (we'll get later to why this is
necessary)
AliAnalysisTaskMyTask::AliAnalysisTaskMyTask() :
AliAnalysisTaskSE(),
fAOD(0), fOutputList(0), fHistPt(0)
{
// ROOT IO constructor , don 't allocate memory here !
}
AliAnalysisTaskMyTask::AliAnalysisTaskMyTask(const char* name)
: AliAnalysisTaskSE(name),
fAOD(0), fOutputList(0), fHistPt(0)
{
DefineInput(0, TChain::Class());
DefineOutput(1, TList::Class());
}
- In the constructor, we initialize members to their default values ...
- ... and tell the task what the in- and output is
Objects that are output are initialized in the function UserCreateOutputObjects()
...
# include "TList .h"
# include "TH1F .h"
...
AliAnalysisTaskMyTask::UserCreateOutputObjects()
{
// create a new TList that OWNS its objects
fOutputList = new TList();
fOutputList->SetOwner(kTRUE);
// create our histo and add it to the list
fHistPt = new TH1F("fHistPt", "fHistPt", 100, 0, 100);
fOutputList->Add(fHistPt);
// add the list to our output file
PostData(1, fOutputList);
}
The function UserExec() is called for each event, this is the 'heart' of our analysis
...
# include "AliAODEvent .h"
...
AliAnalysisTaskMyTask::UserExec(Option_t *)
{
// get an event from the analysis manager
fAOD = dynamic_cast < AliAODEvent *> InputEvent ();
// check if there actually is an event
if (! fAOD ) return ;
// let 's loop over the trakcs and fill our histogram
// first we get the number of tracks
Int_t iTracks (fAOD->GetNumberOfTracks());
// and then loop over them
for(Int_t i(0) ; i < iTracks; i ++){
AliAODTrack * track = static_cast < AliAODTrack *>( fAOD ->GetTrack (i));
if (! track ) continue ;
// here we do some track selection
if (! track -> TestFilterbit (128) continue ;
// fill our histogram
fHistPt -> Fill (track ->Pt ());
}
// and save the data gathered in this iteration
The AddMyTask.C macro instantiates our task (class), define its in- and output and connect it to the analysis manager
AliAnalysisTaskMyTask* AddMyTask(TString name = "name") {
AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
TString fileName = AliAnalysisManager::GetCommonFileName();
fileName += ":MyTask"; // create a subfolder in the file
// now we create an instance of your task
AliAnalysisTaskMyTask* task = new AliAnalysisTaskMyTask(name.Data());
// add your task to the manager
mgr->AddTask(task);
// connect the manager to your task
mgr->ConnectInput(task,0,mgr->GetCommonInputContainer());
// same for the output
mgr->ConnectOutput(task,1,mgr->CreateContainer("MyOutputContainer", TList::Class(), AliAnalysisManager::kOutputContainer, fileName.Data()));
// important : return a pointer to your task
return task ;
}
That's it, now let's run our class...