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...

results matching ""

    No results matching ""