An example how to use the class is also provided, including a macro.
--- /dev/null
+#--------------------------------------------------------------------------------#
+# Package File for PWG0FP #
+# Author : Andras Agocs, Johny Jose (johny.jose@cern.ch) #
+# Variables Defined : #
+# #
+# SRCS - C++ source files #
+# HDRS - C++ header files #
+# DHDR - ROOT Dictionary Linkdef header file #
+# CSRCS - C source files #
+# CHDRS - C header files #
+# EINCLUDE - Include directories #
+# EDEFINE - Compiler definitions #
+# ELIBS - Extra libraries to link #
+# ELIBSDIR - Extra library directories #
+# PACKFFLAGS - Fortran compiler flags for package #
+# PACKCXXFLAGS - C++ compiler flags for package #
+# PACKCFLAGS - C compiler flags for package #
+# PACKSOFLAGS - Shared library linking flags #
+# PACKLDFLAGS - Module linker flags #
+# PACKBLIBS - Libraries to link (Executables only) #
+# EXPORT - Header files to be exported #
+# CINTHDRS - Dictionary header files #
+# CINTAUTOLINK - Set automatic dictionary generation #
+# ARLIBS - Archive Libraries and objects for linking (Executables only) #
+# SHLIBS - Shared Libraries and objects for linking (Executables only) #
+#--------------------------------------------------------------------------------#
+
+set ( SRCS FirstPhysics/AliAnalysisTaskFPexample.cxx FirstPhysics/AliAnalysisTaskFirstPhysics.cxx)
+
+string ( REPLACE ".cxx" ".h" HDRS "${SRCS}" )
+
+set ( DHDR PWG0FPLinkDef.h)
+
+set ( EINCLUDE PWG0/FirstPhysics)
+
+if( ALICE_TARGET STREQUAL "win32gcc")
+
+ set ( PACKSOFLAGS ${SOFLAGS} -L${ALICE_ROOT}/lib/tgt_${ALICE_TARGET} -lSTEERBase -lESD -lANALYSIS -L${ROOTLIBDIR} -lEG)
+
+endif( ALICE_TARGET STREQUAL "win32gcc")
+
--- /dev/null
+
+void AddTaskFPexample(AliAnalysisManager *mgr,
+ AliAnalysisAlien *plugin,
+ const char *runtype,
+ const bool useRealData,
+ const char *taskname,
+ const Int_t gridRun = -1)
+{
+ if (!mgr) {
+ Printf("ERROR: undefined manager, FPexample won't be added");
+ return;
+ }
+ if (!plugin) {
+ Printf("ERROR: undefined alien plugin, FPexample won't be added");
+ return;
+ }
+ // create task
+ gROOT->LoadMacro("AliAnalysisTaskFirstPhysics.cxx++g");
+ gROOT->LoadMacro("AliAnalysisHistosVertex.cxx++g");
+ gROOT->LoadMacro("AliAnalysisTaskFPexample.cxx++g");
+
+ AliAnalysisTaskFPexample* task = new AliAnalysisTaskFPexample(taskname);
+ task->SelectCollisionCandidates(AliVEvent::kMB); // if physics selection performed in UserExec(), this line should be commented
+ task->SetCutTrackPt(0.15, 1e10);
+ task->SetCutEta(0.8);
+ task->SetCutVertexZ(10);
+ mgr->AddTask(task);
+
+ // set output root file name for different analysis
+ TString outfilename;
+ if (runtype == "grid") {
+ outfilename = TString::Format("grid_%d_%s.root", gridRun, useRealData ? "data" : "sim");
+ plugin->SetDefaultOutputs(kFALSE);
+ plugin->SetOutputFiles(outfilename);
+ } else {
+ outfilename = TString::Format("%s_xx_%s.root", runtype, useRealData ? "data" : "sim");
+ }
+
+ // create containers for input/output
+ AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();
+ AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("coutput1", TList::Class(), AliAnalysisManager::kOutputContainer, outfilename.Data());
+ // connect input/output
+ mgr->ConnectInput(task, 0, cinput);
+ mgr->ConnectOutput(task, 1, coutput1);
+}
--- /dev/null
+
+#include "AliAnalysisTaskFPexample.h"
+
+#include "TH1D.h"
+#include "TH2D.h"
+#include "TCanvas.h"
+#include "TList.h"
+#include "TString.h"
+
+#include "AliAnalysisManager.h"
+#include "AliESDtrackCuts.h"
+#include "AliESDEvent.h"
+#include "AliESDHeader.h"
+#include "AliMCEvent.h"
+#include "AliMultiplicity.h"
+#include "AliTriggerAnalysis.h"
+
+ClassImp(AliAnalysisTaskFPexample)
+
+//________________________________________________________________________
+AliAnalysisTaskFPexample::AliAnalysisTaskFPexample(const char *name) :
+ AliAnalysisTaskFirstPhysics(name),
+ fhTrackPt(0),
+ fh2TrackPhiEta(0),
+ fhMulITSTPC(0),
+ fhMulITSSA(0),
+ fhMulSPD(0),
+ fh2TrackletsPhiEta(0),
+ fh2TracksPhiTPCchi2(0)
+{
+ DefineOutput(1, TList::Class());
+}
+
+//________________________________________________________________________
+AliAnalysisTaskFPexample::~AliAnalysisTaskFPexample()
+{
+ // Destructor. Clean-up the output list, but not the histograms that are put inside
+ // (the list is owner and will clean-up these histograms). Protect in PROOF case.
+ if (fOutput && !AliAnalysisManager::GetAnalysisManager()->IsProofMode()) {
+ delete fOutput;
+ }
+ for (Int_t i = 0; i < knTrackCuts; i ++) {
+ delete fTrackCuts[i];
+ fTrackCuts[i] = 0;
+ }
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskFPexample::UserCreateOutputObjects()
+{
+ PrepareOutputList();
+ // Define cuts
+ PrepareDefaultTrackCuts();
+
+ // Create histograms
+ const Int_t ptbins = 15;
+ const Double_t ptlow = 0.1, ptup = 3.1;
+ const Int_t etabins = 40;
+ const Double_t etalow = -2.0, etaup = 2.0;
+ const Int_t mulbins = 200;
+ const Int_t phibins = 120;
+
+ fhTrackPt = UserHisto1d("fhTrackPt", "p_{T} distribution for ESD",
+ "P_{T} (GeV/c)", ptbins, ptlow, ptup);
+ fh2TrackPhiEta = UserHisto2d("fh2TrackPhiEta", "ESD tracks",
+ "#Phi", phibins, 0, 2 * TMath::Pi(),
+ "#eta", etabins, etalow, etaup);
+ fhMulITSTPC = UserHisto1d("fhMulITSTPC", "N_{CH} distribution for ITS+TPC tracks",
+ "N_{CH}", mulbins, 0, mulbins);
+ fhMulITSSA = UserHisto1d("fhMulITSSA", "N_{CH} distribution for ITS SA tracks",
+ "N_{CH}", mulbins, 0, mulbins);
+ fhMulSPD = UserHisto1d("fhMulSPD", "N_{CH} distribution for SPD tracklets",
+ "N_{CH}", mulbins, 0, mulbins);
+ fh2TrackletsPhiEta = UserHisto2d("fh2TrackletsPhiEta", "Tracklets",
+ "#Phi", phibins, 0, 2 * TMath::Pi(),
+ "#eta", etabins, etalow, etaup);
+ fh2TracksPhiTPCchi2 = UserHisto2d("fh2TracksPhiTPCchi2", "ESD tracks #Phi vs. TPC #chi^{2}",
+ "#Phi", phibins, 0, 2 * TMath::Pi(),
+ "#chi^{2}", 500, 0, 500);
+
+ PostData(1, fOutput); // Post data for ALL output slots >0 here, to get at least an empty histogram
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskFPexample::UserExec(Option_t *)
+{
+ if (!GetESDEvent()) {
+ AliError("Unable to read the ESD");
+ return;
+ }
+ if (!CheckVertex()) {
+ return;
+ }
+
+ const Int_t nESDTracks = fESD->GetNumberOfTracks();
+
+ Int_t iHighestID = 0;
+ for (Int_t iTrack = 0; iTrack < nESDTracks; iTrack++) {
+ if (fESD->GetTrack(iTrack)->GetLabel() > iHighestID) {
+ iHighestID = fESD->GetTrack(iTrack)->GetLabel();
+ }
+ }
+ const Int_t nMaxID = iHighestID + 1;
+ bool aGlobalBits[nMaxID], aPureITSBits[nMaxID];
+ for (Int_t iFlag = 0; iFlag < nMaxID; iFlag++) {
+ aGlobalBits[iFlag] = false;
+ aPureITSBits[iFlag] = false;
+ }
+
+ // flags for secondary and rejected tracks
+ const int kRejectBit = BIT(15); // set this bit in ESD tracks if it is rejected by a cut
+ const int kSecondaryBit = BIT(16); // set this bit in ESD tracks if it is secondary according to a cut
+
+ Int_t nTracksITSTPC = 0; // multiplicity counters
+ Int_t nTracksITSSA = 0;
+ Int_t nTrackletsSPD = 0;
+
+ for(Int_t iTrack = 0; iTrack < nESDTracks; iTrack++){
+ AliESDtrack* esdTrack = fESD->GetTrack(iTrack);
+ // if track is a secondary from a V0, flag as a secondary
+ if (esdTrack->IsOn(AliESDtrack::kMultInV0)) {
+ esdTrack->SetBit(kSecondaryBit);
+ continue;
+ }
+ AliESDtrack* tpcTrack = AliESDtrackCuts::GetTPCOnlyTrack(fESD, esdTrack->GetID());
+ // check tracks with ITS part
+ if (esdTrack->IsOn(AliESDtrack::kITSin)) {
+ if (!esdTrack->IsOn(AliESDtrack::kITSpureSA)) { // track has ITS part but is not an ITS_SA
+ // TPC+ITS
+ if (esdTrack->IsOn(AliESDtrack::kTPCin)) { // Global track, has ITS and TPC contributions
+ if (fTrackCuts[kTrackCutQGlo]->AcceptTrack(esdTrack)) { // good ITS+TPC track
+ if (fTrackCuts[kTrackCutDCAwSPD]->AcceptTrack(esdTrack)
+ || fTrackCuts[kTrackCutDCAwoSPD]->AcceptTrack(esdTrack)) {
+ nTracksITSTPC++;
+ fhTrackPt->Fill(esdTrack->Pt());
+ fh2TrackPhiEta->Fill(esdTrack->Phi(), esdTrack->Eta());
+ if (tpcTrack) {
+ fh2TracksPhiTPCchi2->Fill(esdTrack->Phi(), tpcTrack->GetTPCchi2());
+ }
+ } else {
+ esdTrack->SetBit(kSecondaryBit); // large DCA -> secondary, don't count either track not associated tracklet
+ }
+ } else {
+ esdTrack->SetBit(kRejectBit); // bad quality, don't count the track, but may count tracklet if associated
+ }
+ } else if (fTrackCuts[kTrackCutQITS]->AcceptTrack(esdTrack)) { // good ITS complementary track
+ if (fTrackCuts[kTrackCutDCAwSPD]->AcceptTrack(esdTrack)
+ || fTrackCuts[kTrackCutDCAwoSPD]->AcceptTrack(esdTrack)) {
+ nTracksITSTPC++;
+ fhTrackPt->Fill(esdTrack->Pt());
+ fh2TrackPhiEta->Fill(esdTrack->Phi(), esdTrack->Eta());
+ if (tpcTrack) {
+ fh2TracksPhiTPCchi2->Fill(esdTrack->Phi(), tpcTrack->GetTPCchi2());
+ }
+ } else {
+ esdTrack->SetBit(kSecondaryBit); // large DCA -> secondary, don't count either track not associated tracklet
+ }
+ } else {
+ esdTrack->SetBit(kRejectBit); // bad quality, don't count the track, but may count tracklet if associated
+ }
+ } else { // pure ITS SA tracks
+ if (fTrackCuts[kTrackCutQITS]->AcceptTrack(esdTrack)) { // good ITSSA track
+ if (fTrackCuts[kTrackCutDCAwSPD]->AcceptTrack(esdTrack)
+ || fTrackCuts[kTrackCutDCAwoSPD]->AcceptTrack(esdTrack)) {
+ nTracksITSSA++;
+ } else {
+ esdTrack->SetBit(kRejectBit);
+ }
+ } else {
+ esdTrack->SetBit(kRejectBit);
+ }
+ }
+ }
+ if (tpcTrack) {
+ delete tpcTrack;
+ }
+ }
+
+ // get multiplicity from ITS tracklets to complement TPC+ITS, and ITS pure SA
+ const AliMultiplicity* multiplicitySPD = fESD->GetMultiplicity(); // spd multiplicity object
+ Int_t id1, id2, id3, id4;
+ AliESDtrack *tr1 = 0, *tr3 = 0;
+ for (Int_t iTracklet = 0; iTracklet < multiplicitySPD->GetNumberOfTracklets(); iTracklet++) {
+ if (TMath::Abs(multiplicitySPD->GetEta(iTracklet)) > GetCutEta()) {
+ continue; // eta selection for tracklets
+ }
+ nTrackletsSPD++;
+ fh2TrackletsPhiEta->Fill(multiplicitySPD->GetPhi(iTracklet), multiplicitySPD->GetEta(iTracklet));
+ // if counting tracks+tracklets, check if clusters were already used in tracks
+ // and get the id of the tracks in which they were used
+
+ // references for eventual Global/ITS_SA tracks
+ multiplicitySPD->GetTrackletTrackIDs(iTracklet, 0, id1, id2);
+ tr1 = id1 >= 0 ? fESD->GetTrack(id1) : 0;
+
+ // references for eventual ITS_SA_pure tracks
+ multiplicitySPD->GetTrackletTrackIDs(iTracklet, 1, id3, id4);
+ tr3 = id3 >= 0 ? fESD->GetTrack(id3) : 0;
+
+ // are both clusters from the same tracks? If not, skip the
+ // tracklet (shouldn't change things much)
+ if (id1 != id2 || id3 != id4) {
+ continue;
+ }
+
+ // has associated global track been associated to a previous tracklet?
+ bool bUsedInGlobal = (id1 != -1) ? aGlobalBits[id1] : false;
+ // has associated pure ITS track been associated to a previous tracklet?
+ bool bUsedInPureITS = (id3 != -1) ? aPureITSBits[id3] : false;
+
+ // counting tracklet as global+complementary track
+ if ((tr1 && !tr1->TestBit(kSecondaryBit)) // reject as secondary
+ && (tr1 && tr1->TestBit(kRejectBit))) { // already accounted
+ if (!bUsedInGlobal) {
+ nTracksITSTPC++;
+ if (id1 > 0) {
+ // mark global track linked to this tracklet as associated
+ aGlobalBits[id1] = true;
+ }
+ }
+ } else if (id1 < 0) {
+ nTracksITSTPC++;
+ }
+
+ // counting tracklet as ITS SA pure track
+ if ((tr3 && tr3->TestBit(kSecondaryBit))
+ && (tr3 && !tr3->TestBit(kRejectBit))) {
+ if (!bUsedInPureITS) {
+ nTracksITSSA++;
+ if (id3 > 0) {
+ // mark global track linked to this tracklet as associated
+ aPureITSBits[id3] = true;
+ }
+ }
+ } else if (id3 < 0) {
+ nTracksITSSA++;
+ }
+
+ }
+ fhMulITSTPC->Fill(nTracksITSTPC);
+ fhMulITSSA->Fill(nTracksITSSA);
+ fhMulSPD->Fill(nTrackletsSPD);
+
+ PostData(1, fOutput);
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskFPexample::Terminate(Option_t *)
+{
+ // Draw result to screen, or perform fitting, normalizations
+ // don't get too fancy, keep your histos raw and massage them with macros
+
+ fOutput = dynamic_cast<TList*> (GetOutputData(1));
+ if(!fOutput) {
+ Printf("ERROR: could not retrieve TList fOutput");
+ return;
+ }
+
+ if (!(GetHisto1FromOutput("fhTrackPt", fhTrackPt) &&
+ GetHisto2FromOutput("fh2TrackPhiEta", fh2TrackPhiEta) &&
+ GetHisto1FromOutput("fhMulITSTPC", fhMulITSTPC) &&
+ GetHisto1FromOutput("fhMulITSSA", fhMulITSSA) &&
+ GetHisto1FromOutput("fhMulSPD", fhMulSPD) &&
+ GetHisto2FromOutput("fh2TrackletsPhiEta", fh2TrackletsPhiEta) &&
+ GetHisto2FromOutput("fh2TracksPhiTPCchi2", fh2TracksPhiTPCchi2))) {
+ AliError("Couldn't load every histogram from output.");
+ return;
+ }
+
+ TCanvas *c = new TCanvas("AliAnalysisTaskFPexample", "Data Quality Quick Overview");
+ c->Divide(2, 2);
+ c->cd(1)->SetLogy();
+ fhTrackPt->DrawCopy("E");
+ c->cd(2);
+ fh2TrackPhiEta->DrawCopy("");
+ c->cd(3)->SetLogy();
+ fhMulITSTPC->DrawCopy("E");
+ c->cd(4)->SetLogy();
+ fhMulITSSA->DrawCopy("");
+}
--- /dev/null
+
+#ifndef ALIANALYSISTASKFPEXAMPLE_H
+#define ALIANALYSISTASKFPEXAMPLE_H
+
+class AliAnalysisHistosVertex;
+#include "AliAnalysisTaskFirstPhysics.h"
+
+class AliAnalysisTaskFPexample : public AliAnalysisTaskFirstPhysics {
+ public:
+ AliAnalysisTaskFPexample(const char *name = "You should have given a name to this analysis");
+ virtual ~AliAnalysisTaskFPexample();
+
+ virtual void UserCreateOutputObjects();
+ virtual void UserExec(Option_t *option);
+ virtual void Terminate(Option_t *);
+
+ private:
+
+ TH1D *fhTrackPt; // pT spectrum of tracks
+ TH2D *fh2TrackPhiEta; // ESD tracks
+ TH1D *fhMulITSTPC; // multiplicity distribution from TPC tracks and ITS tracks
+ TH1D *fhMulITSSA; // multiplicity distribution from ITS standalone
+ TH1D *fhMulSPD; // multiplicity distribution from SPD tracklets
+ TH2D *fh2TrackletsPhiEta; // tracklet distribution
+ TH2D *fh2TracksPhiTPCchi2; // track chi2 from TPC vs. azimuthal angle
+
+ AliAnalysisTaskFPexample(const AliAnalysisTaskFPexample&); // not implemented
+ AliAnalysisTaskFPexample& operator=(const AliAnalysisTaskFPexample&); // not implemented
+
+ ClassDef(AliAnalysisTaskFPexample, 1);
+};
+
+#endif
+
--- /dev/null
+
+#include "AliAnalysisTaskFirstPhysics.h"
+
+#include "TH1D.h"
+#include "TH2D.h"
+#include "TList.h"
+#include "TString.h"
+
+#include "AliAnalysisTaskSE.h"
+#include "AliAnalysisManager.h"
+#include "AliESDtrackCuts.h"
+#include "AliESDEvent.h"
+#include "AliESDHeader.h"
+#include "AliMCEvent.h"
+#include "AliMultiplicity.h"
+
+#include "AliGenEventHeader.h"
+#include "AliGenPythiaEventHeader.h"
+#include "AliGenDPMjetEventHeader.h"
+#include "AliStack.h"
+
+ClassImp(AliAnalysisTaskFirstPhysics)
+
+//________________________________________________________________________
+AliAnalysisTaskFirstPhysics::AliAnalysisTaskFirstPhysics(const char *name) :
+ AliAnalysisTaskSE(name),
+ fESD(0),
+ fMCEvent(0),
+ fOutput(0),
+ fbReadMC(0),
+ fMCProcessType(kProcND),
+ fTrigger(0),
+ fCutTrackPtMin(0.15),
+ fCutTrackPtMax(100),
+ fCutEta(0.8),
+ fCutVertexZ(10)
+{
+ DefineOutput(1, TList::Class());
+ for (Int_t i = 0; i < knTrackCuts; i ++) {
+ fTrackCuts[i] = 0;
+ }
+}
+
+//________________________________________________________________________
+AliAnalysisTaskFirstPhysics::~AliAnalysisTaskFirstPhysics()
+{
+ // Destructor. Clean-up the output list, but not the histograms that are put inside
+ // (the list is owner and will clean-up these histograms). Protect in PROOF case.
+ if (fOutput && !AliAnalysisManager::GetAnalysisManager()->IsProofMode()) {
+ delete fOutput;
+ }
+ for (Int_t i = 0; i < knTrackCuts; i ++) {
+ delete fTrackCuts[i];
+ fTrackCuts[i] = 0;
+ }
+ if (fTrigger) {
+ delete fTrigger;
+ }
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskFirstPhysics::PrepareOutputList()
+{
+ if (fOutput) {
+ AliError("fOutput already initialised.");
+ return;
+ }
+ fOutput = new TList();
+ fOutput->SetOwner();
+ TH1::SetDefaultSumw2(kTRUE);
+ if (fTrigger) {
+ AliError("fTrigger is already initialised.");
+ return;
+ }
+ fTrigger = new AliTriggerAnalysis;
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskFirstPhysics::PrepareDefaultTrackCuts()
+{
+ // quality cut on ITS+TPC tracks
+ fTrackCuts[kTrackCutQGlo] = new AliESDtrackCuts();
+ // TPC
+ fTrackCuts[kTrackCutQGlo]->SetMinNClustersTPC(70);
+ fTrackCuts[kTrackCutQGlo]->SetMaxChi2PerClusterTPC(4);
+ fTrackCuts[kTrackCutQGlo]->SetAcceptKinkDaughters(kFALSE);
+ fTrackCuts[kTrackCutQGlo]->SetRequireTPCRefit(kTRUE);
+ // ITS
+ fTrackCuts[kTrackCutQGlo]->SetRequireITSRefit(kTRUE);
+ fTrackCuts[kTrackCutQGlo]->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kOff);
+ fTrackCuts[kTrackCutQGlo]->SetEtaRange(-fCutEta, fCutEta);
+ fTrackCuts[kTrackCutQGlo]->SetPtRange(fCutTrackPtMin, fCutTrackPtMax);
+ // quality cut on ITS_SA tracks (complementary to ITS+TPC)
+ fTrackCuts[kTrackCutQITS] = new AliESDtrackCuts();
+ fTrackCuts[kTrackCutQITS]->SetRequireITSRefit(kTRUE);
+ fTrackCuts[kTrackCutQITS]->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kOff);
+ fTrackCuts[kTrackCutQITS]->SetEtaRange(-fCutEta, fCutEta);
+ // primary selection for tracks with SPD hits
+ fTrackCuts[kTrackCutDCAwSPD] = new AliESDtrackCuts();
+ fTrackCuts[kTrackCutDCAwSPD]->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kAny);
+ fTrackCuts[kTrackCutDCAwSPD]->SetMaxDCAToVertexXYPtDep("0.0182+0.0350/pt^1.01");
+ fTrackCuts[kTrackCutDCAwSPD]->SetMaxDCAToVertexZ(0.5);
+ fTrackCuts[kTrackCutDCAwSPD]->SetEtaRange(-fCutEta, fCutEta);
+ // primary selection for tracks w/o SPD hits
+ fTrackCuts[kTrackCutDCAwoSPD] = new AliESDtrackCuts();
+ fTrackCuts[kTrackCutDCAwoSPD]->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kNone);
+ fTrackCuts[kTrackCutDCAwoSPD]->SetMaxDCAToVertexXYPtDep("1.5*(0.0182+0.0350/pt^1.01)");
+ fTrackCuts[kTrackCutDCAwoSPD]->SetMaxDCAToVertexZ(0.5);
+ fTrackCuts[kTrackCutDCAwoSPD]->SetEtaRange(-fCutEta, fCutEta);
+
+ // tracks without SPD hits
+ fTrackCuts[kTrackCutNoSPD] = new AliESDtrackCuts();
+ fTrackCuts[kTrackCutNoSPD]->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kNone);
+ // tracks from TPC SA
+ fTrackCuts[kTrackCutTPConly] = new AliESDtrackCuts();
+ fTrackCuts[kTrackCutTPConly]->SetRequireTPCStandAlone(kTRUE);
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskFirstPhysics::UserCreateOutputObjects()
+{
+ PrepareOutputList();
+ // Define cuts
+ PrepareDefaultTrackCuts();
+
+ // create more histograms here using UserHisto1d and UserHisto2d
+
+ PostData(1, fOutput); // Post data for ALL output slots >0 here, to get at least an empty histogram
+}
+
+//________________________________________________________________________
+bool AliAnalysisTaskFirstPhysics::GetESDEvent()
+{
+ fESD = 0;
+ // Get a pointer to the reconstructed event
+ AliVEvent *event = InputEvent();
+ if (!event) {
+ AliError("ERROR: Could not retrieve event.");
+ return false;
+ }
+ // try to access the ESD information
+ AliESDEvent* esd = dynamic_cast<AliESDEvent*>(event);
+ if (!esd) {
+ AliError("InputEvent() is not AliESDEvent.");
+ return false;
+ }
+ fESD = esd;
+ return true;
+}
+
+//________________________________________________________________________
+bool AliAnalysisTaskFirstPhysics::CheckVertex()
+{
+ // check for good reconstructed vertex
+ if (!(fESD->GetPrimaryVertex()->GetStatus()) ||
+ !(fESD->GetPrimaryVertexSPD()->GetStatus())) {
+ return false;
+ }
+ // if vertex is from spd vertexZ, require more stringent cut
+ if (fESD->GetPrimaryVertex()->IsFromVertexerZ() &&
+ (fESD->GetPrimaryVertex()->GetDispersion() > 0.02 ||
+ fESD->GetPrimaryVertex()->GetZRes() > 0.25 )) {
+ return false;
+ }
+ if (TMath::Abs(fESD->GetPrimaryVertex()->GetZ()) > fCutVertexZ) {
+ return false;
+ }
+ return true;
+}
+
+//________________________________________________________________________
+bool AliAnalysisTaskFirstPhysics::CheckVertexMC() {
+ if (!fbReadMC) {
+ return false;
+ }
+ if (TMath::Abs(fMCEvent->GetPrimaryVertex()->GetZ()) > fCutVertexZ) {
+ return false;
+ }
+ return true;
+}
+
+//________________________________________________________________________
+bool AliAnalysisTaskFirstPhysics::PrepareMCInfo()
+{
+ fbReadMC = true;
+ fMCEvent = MCEvent();
+ if (!fMCEvent) {
+ fbReadMC = false;
+ }
+ if (fbReadMC) {
+ AliDebug(4, TString::Format("MC particles: %d", fMCEvent->GetNumberOfTracks()));
+ AliDebug(4, TString::Format("number of particles in the stack: %d", fMCEvent->Stack()->GetNtrack()));
+ AliGenPythiaEventHeader* pythiaGenHeader = 0;
+ AliGenDPMjetEventHeader* dpmHeader = 0;
+ pythiaGenHeader = dynamic_cast<AliGenPythiaEventHeader*>(fMCEvent->GenEventHeader());
+ dpmHeader = dynamic_cast<AliGenDPMjetEventHeader*>(fMCEvent->GenEventHeader());
+ // MC event classification
+ Int_t iProcessType = 0;
+ Int_t iSD1flag = 0, iSD2flag = 0, iDDflag = 0,
+ iCDflag = 0, iELflag = 0, iNDflag = 0;
+ if (pythiaGenHeader) {
+ iProcessType = pythiaGenHeader->ProcessType();
+ iSD1flag = 92;
+ iSD2flag = 93;
+ iDDflag = 94;
+ iELflag = 91;
+ iCDflag = -2;
+ iNDflag = -1;
+ AliDebug(5, TString::Format("Pythia event, %d type", iProcessType));
+ } else if (dpmHeader) {
+ iProcessType = dpmHeader->ProcessType();
+ iSD1flag = 5;
+ iSD2flag = 6;
+ iDDflag = 7;
+ iELflag = 2;
+ iCDflag = 4;
+ iNDflag = 1;
+ AliDebug(5, TString::Format("Phojet event, %d type", iProcessType));
+ } else {
+ AliError("neither pythia nor phojet event");
+ }
+ if (iProcessType == iSD1flag) {
+ fMCProcessType = kProcSD1;
+ } else if (iProcessType == iSD2flag) {
+ fMCProcessType = kProcSD2;
+ } else if (iProcessType == iDDflag) {
+ fMCProcessType = kProcDD;
+ } else if (iProcessType == iELflag) {
+ fMCProcessType = kProcEL;
+ } else if (iProcessType == iCDflag) {
+ fMCProcessType = kProcCD;
+ } else if (iProcessType == iNDflag) {
+ fMCProcessType = kProcND;
+ } else {
+ fMCProcessType = kProcIndef;
+ }
+ }
+ return fbReadMC;
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskFirstPhysics::UserExec(Option_t *)
+{
+ if (!GetESDEvent()) {
+ AliError("Unable to read the ESD");
+ return;
+ }
+ if (!CheckVertex()) {
+ return;
+ }
+
+ // custom code comes here
+
+ PostData(1, fOutput);
+}
+
+//________________________________________________________________________
+TH1D* AliAnalysisTaskFirstPhysics::UserHisto1d(const char *name, const char *title, const char *xlabel, Int_t nbinsx, Double_t xlow, Double_t xup)
+{
+ TH1D *hist = new TH1D(name, title, nbinsx, xlow, xup);
+ hist->GetXaxis()->SetTitle(xlabel);
+ fOutput->Add(hist);
+ return hist;
+}
+
+//________________________________________________________________________
+TH2D* AliAnalysisTaskFirstPhysics::UserHisto2d(const char *name, const char *title, const char *xlabel, Int_t nbinsx, Double_t xlow, Double_t xup, const char *ylabel, Int_t nbinsy, Double_t ylow, Double_t yup)
+{
+ TH2D *hist = new TH2D(name, title, nbinsx, xlow, xup, nbinsy, ylow, yup);
+ hist->GetXaxis()->SetTitle(xlabel);
+ hist->GetYaxis()->SetTitle(ylabel);
+ fOutput->Add(hist);
+ return hist;
+}
+
+//________________________________________________________________________
+bool AliAnalysisTaskFirstPhysics::GetHisto1FromOutput(const char *name, TH1D *&h) const
+{
+ h = dynamic_cast<TH1D*> (fOutput->FindObject(name));
+ if (!h) {
+ AliError(TString::Format("Unable to load histogram from output: %s", name));
+ return false;
+ } else {
+ return true;
+ }
+}
+
+//________________________________________________________________________
+bool AliAnalysisTaskFirstPhysics::GetHisto2FromOutput(const char *name, TH2D *&h) const
+{
+ h = dynamic_cast<TH2D*> (fOutput->FindObject(name));
+ if (!h) {
+ AliError(TString::Format("Unable to load histogram from output: %s", name));
+ return false;
+ } else {
+ return true;
+ }
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskFirstPhysics::Terminate(Option_t *)
+{
+ fOutput = dynamic_cast<TList*> (GetOutputData(1));
+ if(!fOutput) {
+ AliError("Could not retrieve TList fOutput.");
+ return;
+ }
+}
--- /dev/null
+// This class contains common elements for the analysis in the First Physics Group.
+// based on the code by Arvinder Palaha
+// written by Andras Agocs and Anton Alkin
+
+#ifndef ALIANALYSISTASKFIRSTPHYSICS_H
+#define ALIANALYSISTASKFIRSTPHYSICS_H
+
+class TH1D;
+class TH2D;
+class TList;
+class AliESDtrackCuts;
+class AliESDEvent;
+
+#include "AliAnalysisTaskSE.h"
+#include "AliTriggerAnalysis.h"
+
+#include <string>
+
+class AliAnalysisTaskFirstPhysics : public AliAnalysisTaskSE {
+ public:
+ // indexing various track cuts
+ enum {
+ kTrackCutQGlo,
+ kTrackCutQITS,
+ kTrackCutDCAwSPD,
+ kTrackCutDCAwoSPD,
+ kTrackCutNoSPD,
+ kTrackCutTPConly,
+ knTrackCuts}; // this must always the last
+
+ // recognised MC process types
+ enum ProcessType {
+ kProcSD1, // single diffractive AB->XB
+ kProcSD2, // single diffractive AB->AX
+ kProcDD, // double diffractive
+ kProcEL, // elastic
+ kProcCD, // central diffractive
+ kProcND, // non-diffractive
+ kProcIndef};
+
+ AliAnalysisTaskFirstPhysics(const char *name = "You should have given a name to this analysis");
+ virtual ~AliAnalysisTaskFirstPhysics();
+
+ virtual void UserCreateOutputObjects();
+ virtual void UserExec(Option_t *option);
+ virtual void Terminate(Option_t *);
+
+ void SetCutTrackPt(Double_t min, Double_t max) {fCutTrackPtMin = min; fCutTrackPtMax = max;}
+ Double_t GetCutTrackPtMin() const {return fCutTrackPtMin;}
+ Double_t GetCutTrackPtMax() const {return fCutTrackPtMax;}
+ void SetCutEta(Double_t x) {fCutEta = x;}
+ Double_t GetCutEta() const {return fCutEta;}
+ void SetCutVertexZ(Double_t x) {fCutVertexZ = x;}
+ Double_t GetCutVertexZ() const {return fCutVertexZ;}
+
+ protected:
+ void PrepareOutputList(); // create fOutput
+ void PrepareDefaultTrackCuts(); // create cut objects
+ bool PrepareMCInfo(); // check whether MC info is available and read process type
+ bool GetESDEvent(); // sets fESD to the current ESD
+ bool CheckVertex(); // checks for an appropriate vertex
+ bool CheckVertexMC(); // checks for an appropriate vertex in the MC truth
+
+ TH1D* UserHisto1d(const char *name, const char *title, const char *xlabel, Int_t nbinsx, Double_t xlow, Double_t xup);
+ TH2D* UserHisto2d(const char *name, const char *title, const char *xlabel, Int_t nbinsx, Double_t xlow, Double_t xup, const char *ylabel, Int_t nbinsy, Double_t ylow, Double_t yup);
+ bool GetHisto1FromOutput(const char *name, TH1D *&h) const; // read a histogram from fOutput; use this in Terminate()
+ bool GetHisto2FromOutput(const char *name, TH2D *&h) const; // read a 2d histogram from fOutput
+
+ AliESDEvent *fESD; //! the ESD information of the event
+ AliMCEvent *fMCEvent; //! the MC information is available
+ TList *fOutput; // Output list
+ bool fbReadMC; //! indicates if MC information could be read; see PrepareMCInfo()
+ ProcessType fMCProcessType; //! indicates the process type used in MC
+ AliESDtrackCuts *fTrackCuts[knTrackCuts]; // Track cuts
+ AliTriggerAnalysis* fTrigger; //!
+
+ private:
+ // simplest cut parameters
+ Double_t fCutTrackPtMin;
+ Double_t fCutTrackPtMax;
+ Double_t fCutEta;
+ Double_t fCutVertexZ;
+
+ AliAnalysisTaskFirstPhysics(const AliAnalysisTaskFirstPhysics&); // not implemented
+ AliAnalysisTaskFirstPhysics& operator=(const AliAnalysisTaskFirstPhysics&); // not implemented
+
+ ClassDef(AliAnalysisTaskFirstPhysics, 1);
+};
+
+#endif
+
--- /dev/null
+
+class AliAnalysisGrid;
+
+//______________________________________________________________________________
+void runFPexample(
+ const char* runtype = "grid", // local, proof or grid
+ const bool useRealData = true, // run the proof with data or MC
+ const char *gridMode = "full", // Set the run mode (can be "full", "test", "offline", "submit" or "terminate"). Full & Test work for proof
+ const char *taskname = "give_task_name_for_grid_analysis", // the unique name of our task *must be a valid c identifier*
+ const Int_t gridRun = -1, // the run to analyse *must be set for grid mode*
+ const char *gridDirData = "/alice/data/2010/LHC10d", // the location of the data for grid analysis
+ const char *gridDirMC = "/alice/sim/LHC10f6a", // the location of the MC for grid analysis
+ const Long64_t proofNentries = 2000000, // for local and proof mode, ignored in grid mode. Set to 1234567890 for all events.
+ const Long64_t proofFirstEntry = 0, // for local and proof mode, ignored in grid mode
+ )
+{
+ // check run type
+ if(runtype != "local" && runtype != "proof" && runtype != "grid"){
+ Printf("\n\tIncorrect run option, check first argument of run macro");
+ Printf("\tint runtype = local, proof or grid\n");
+ return;
+ }
+ Printf("%s analysis chosen", runtype);
+
+ const bool bMCtruth = !useRealData;
+ bool bMCphyssel = false;
+
+ const char *proofRealDataSet = "/default/kimb/LHC10d_000126405";
+ const char *proofMCDataSet = "/alice/sim/LHC11b1a_000118558";
+
+ char *proofdataset;
+ if (useRealData) {
+ proofdataset = proofRealDataSet;
+ bMCphyssel = false;
+ Printf("Using REAL DATA (TM) for analysis");
+ } else {
+ proofdataset = proofMCDataSet;
+ bMCphyssel = true;
+ Printf("Using MC for analysis");
+ }
+ const char *proofcluster = "alice-caf.cern.ch"; // which proof cluster to use in proof mode
+
+ // load libraries
+ gSystem->Load("libCore.so");
+ gSystem->Load("libGeom.so");
+ gSystem->Load("libVMC.so");
+ gSystem->Load("libPhysics.so");
+ gSystem->Load("libTree.so");
+ gSystem->Load("libSTEERBase.so");
+ gSystem->Load("libESD.so");
+ gSystem->Load("libAOD.so");
+ gSystem->Load("libANALYSIS.so");
+ gSystem->Load("libANALYSISalice.so");
+
+ // add aliroot indlude path
+ gROOT->ProcessLine(TString::Format(".include %s/include", gSystem->ExpandPathName("$ALICE_ROOT")));
+ gROOT->SetStyle("Plain");
+
+ // analysis manager
+ AliAnalysisManager* mgr = new AliAnalysisManager(taskname);
+
+ // create the alien handler and attach it to the manager
+ AliAnalysisAlien *plugin = new AliAnalysisAlien();
+ mgr->SetGridHandler(plugin);
+
+ AliVEventHandler* esdH = new AliESDInputHandler();
+ mgr->SetInputEventHandler(esdH);
+
+ // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
+ plugin->SetRunMode(gridMode);
+
+ gROOT->LoadMacro("AddTaskFPexample.C");
+ AddTaskFPexample(mgr, plugin, runtype, useRealData, taskname, gridRun);
+
+ // Define alien work directory where all files will be copied. Relative to alien $HOME.
+ plugin->SetGridWorkingDir(TString::Format("%s/%d/%s", taskname, gridRun, useRealData ? "data" : "sim").Data());
+
+ // Declare alien output directory. Relative to working directory.
+ plugin->SetGridOutputDir("output");
+
+ // Declare the analysis source files names separated by blancs. To be compiled runtime
+ // using ACLiC on the worker nodes.
+ // the upload order matters on PROOF! if A.cxx depends on B.h then put B.cxx first (my experience)
+ plugin->SetAnalysisSource("AliAnalysisTaskFirstPhysics.cxx AliAnalysisHistosVertex.cxx AliAnalysisTaskFPexample.cxx");
+
+ // Declare all libraries (other than the default ones for the framework. These will be
+ // loaded by the generated analysis macro. Add all extra files (task .cxx/.h) here.
+ plugin->SetAdditionalLibs("AliAnalysisTaskFirstPhysics.h AliAnalysisTaskFirstPhysics.cxx AliAnalysisHistosVertex.h AliAnalysisHistosVertex.cxx AliAnalysisTaskFPexample.h AliAnalysisTaskFPexample.cxx");
+
+ // Set versions of used packages
+ plugin->SetAPIVersion("V1.1x");
+ plugin->SetROOTVersion("v5-28-00c");
+ plugin->SetAliROOTVersion("v4-21-22-AN");
+
+ // Declare input data to be processed.
+
+ // Method 1: Create automatically XML collections using alien 'find' command.
+ // Define production directory LFN
+ if (useRealData) {
+ plugin->SetGridDataDir(gridDirData);
+ } else {
+ plugin->SetGridDataDir(gridDirMC);
+ }
+
+ // Set data search pattern
+ if (useRealData) {
+ plugin->SetDataPattern("*ESDs/pass2/*ESDs.root"); // CHECK LATEST PASS OF DATA SET IN ALIENSH
+ plugin->SetRunPrefix("000"); // real data
+ } else {
+ plugin->SetDataPattern("*ESDs.root"); // THIS CHOOSES ALL PASSES
+ }
+ // ...then add run numbers to be considered
+ plugin->AddRunNumber(gridRun);
+ //plugin->SetNrunsPerMaster(1);
+ plugin->SetOutputToRunNo();
+ // comment out the next line when using the "terminate" option, unless
+ // you want separate merged files for each run
+ plugin->SetMergeViaJDL();
+
+ // Method 2: Declare existing data files (raw collections, xml collections, root file)
+ // If no path mentioned data is supposed to be in the work directory (see SetGridWorkingDir())
+ // XML collections added via this method can be combined with the first method if
+ // the content is compatible (using or not tags)
+ // plugin->AddDataFile("tag.xml");
+ // plugin->AddDataFile("/alice/data/2008/LHC08c/000057657/raw/Run57657.Merged.RAW.tag.root");
+
+
+ // Declare the output file names separated by blancs.
+ // (can be like: file.root or file.root@ALICE::Niham::File)
+ // To only save certain files, use SetDefaultOutputs(kFALSE), and then
+ // SetOutputFiles("list.root other.filename") to choose which files to save
+ plugin->SetDefaultOutputs(kFALSE);
+
+ // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
+ plugin->SetAnalysisMacro(TString::Format("%s_%d.C", taskname, gridRun).Data());
+
+ // Optionally set maximum number of input files/subjob (default 100, put 0 to ignore)
+ if (useRealData) {
+ plugin->SetSplitMaxInputFileNumber(100);
+ } else {
+ plugin->SetSplitMaxInputFileNumber(300);
+ }
+
+ // Optionally modify the executable name (default analysis.sh)
+ plugin->SetExecutable(TString::Format("%s_%d.sh", taskname, gridRun).Data());
+
+ // set number of test files to use in "test" mode
+ plugin->SetNtestFiles(10);
+
+ // Optionally resubmit threshold.
+ plugin->SetMasterResubmitThreshold(90);
+
+ // Optionally set time to live (default 30000 sec)
+ plugin->SetTTL(30000);
+
+ // Optionally set input format (default xml-single)
+ plugin->SetInputFormat("xml-single");
+
+ // Optionally modify the name of the generated JDL (default analysis.jdl)
+ plugin->SetJDLName(TString::Format("%s_%d.jdl", taskname, gridRun).Data());
+
+ // Optionally modify job price (default 1)
+ plugin->SetPrice(1);
+
+ // Optionally modify split mode (default 'se')
+ plugin->SetSplitMode("se");
+
+ // Proof cluster
+ plugin->SetProofCluster(proofcluster);
+ // Dataset to be used
+ plugin->SetProofDataSet(proofdataset);
+ // May need to reset proof. Supported modes: 0-no reset, 1-soft, 2-hard
+ plugin->SetProofReset(0);
+ // May limit number of workers
+ plugin->SetNproofWorkers(0);
+ // May limit the number of workers per slave
+ // plugin->SetNproofWorkersPerSlave(1);
+ // May use a specific version of root installed in proof
+ plugin->SetRootVersionForProof("current");
+ // May set the aliroot mode. Check http://aaf.cern.ch/node/83
+ plugin->SetAliRootMode("default"); // Loads AF libs by default
+ // May request ClearPackages (individual ClearPackage not supported)
+ plugin->SetClearPackages(kFALSE);
+ // Plugin test mode works only providing a file containing test file locations, used in "local" mode also
+ plugin->SetFileForTestMode("files.txt"); // file should contain path name to a local directory containg *ESDs.root etc
+ // Request connection to alien upon connection to grid
+ plugin->SetProofConnectGrid(kFALSE);
+
+ // mc event handler
+ if (bMCtruth) {
+ AliMCEventHandler* mchandler = new AliMCEventHandler();
+ // Not reading track references
+ mchandler->SetReadTR(kFALSE);
+ mgr->SetMCtruthEventHandler(mchandler);
+ }
+
+ // === Physics Selection Task ===
+ //
+ // In SelectCollisionCandidate(), default is kMB, so the task UserExec()
+ // function is only called for these events.
+ // Options are:
+ // kMB Minimum Bias trigger
+ // kMBNoTRD Minimum bias trigger where the TRD is not read out
+ // kMUON Muon trigger
+ // kHighMult High-Multiplicity Trigger
+ // kUserDefined For manually defined trigger selection
+ //
+ // Multiple options possible with the standard AND/OR operators && and ||
+ // These all have the usual offline SPD or V0 selections performed.
+ //
+ // With a pointer to the physics selection object using physSelTask->GetPhysicsSelection(),
+ // one can manually set the selected and background classes using:
+ // AddCollisionTriggerClass("+CINT1B-ABCE-NOPF-ALL")
+ // AddBGTriggerClass("+CINT1A-ABCE-NOPF-ALL");
+ //
+ // One can also specify multiple classes at once, or require a class to NOT
+ // trigger, for e.g.
+ // AddBGTriggerClass("+CSMBA-ABCE-NOPF-ALL -CSMBB-ABCE-NOPF-ALL");
+ //
+ // NOTE that manually setting the physics selection overrides the standard
+ // selection, so it must be done in completeness.
+ //
+ // ALTERNATIVELY, one can make the physics selection inside the task
+ // UserExec().
+ // For this case, comment out the task->SelectCol.... line,
+ // and see AliBasicTask.cxx UserExec() function for details on this.
+
+ gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");
+ AliPhysicsSelectionTask *physSelTask = AddTaskPhysicsSelection(bMCphyssel);
+ if (!physSelTask) {
+ Printf("no physSelTask");
+ return;
+ }
+ //AliPhysicsSelection *physSel = physSelTask->GetPhysicsSelection();
+ //physSel->AddCollisionTriggerClass("+CINT1B-ABCE-NOPF-ALL");// #3119 #769");
+
+ // enable debug printouts
+ mgr->SetDebugLevel(2);
+ if (!mgr->InitAnalysis()) return;
+ mgr->PrintStatus();
+
+ // start analysis
+ Printf("Starting Analysis....");
+ mgr->StartAnalysis(runtype, proofNentries, proofFirstEntry);
+}
--- /dev/null
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class AliAnalysisTaskFirstPhysics+;
+#pragma link C++ class AliAnalysisTaskFPexample+;
+
+#endif