]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
First Physics Group analysis class.
authoraagocs <aagocs@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 6 May 2011 12:29:48 +0000 (12:29 +0000)
committeraagocs <aagocs@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 6 May 2011 12:29:48 +0000 (12:29 +0000)
An example how to use the class is also provided, including a macro.

PWG0/CMakelibPWG0FP.pkg [new file with mode: 0644]
PWG0/FirstPhysics/AddTaskFPexample.C [new file with mode: 0644]
PWG0/FirstPhysics/AliAnalysisTaskFPexample.cxx [new file with mode: 0644]
PWG0/FirstPhysics/AliAnalysisTaskFPexample.h [new file with mode: 0644]
PWG0/FirstPhysics/AliAnalysisTaskFirstPhysics.cxx [new file with mode: 0644]
PWG0/FirstPhysics/AliAnalysisTaskFirstPhysics.h [new file with mode: 0644]
PWG0/FirstPhysics/runFPexample.C [new file with mode: 0644]
PWG0/PWG0FPLinkDef.h [new file with mode: 0644]

diff --git a/PWG0/CMakelibPWG0FP.pkg b/PWG0/CMakelibPWG0FP.pkg
new file mode 100644 (file)
index 0000000..7647261
--- /dev/null
@@ -0,0 +1,41 @@
+#--------------------------------------------------------------------------------#
+# 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")
+
diff --git a/PWG0/FirstPhysics/AddTaskFPexample.C b/PWG0/FirstPhysics/AddTaskFPexample.C
new file mode 100644 (file)
index 0000000..979c783
--- /dev/null
@@ -0,0 +1,45 @@
+
+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);
+}
diff --git a/PWG0/FirstPhysics/AliAnalysisTaskFPexample.cxx b/PWG0/FirstPhysics/AliAnalysisTaskFPexample.cxx
new file mode 100644 (file)
index 0000000..53be85c
--- /dev/null
@@ -0,0 +1,280 @@
+
+#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("");
+}
diff --git a/PWG0/FirstPhysics/AliAnalysisTaskFPexample.h b/PWG0/FirstPhysics/AliAnalysisTaskFPexample.h
new file mode 100644 (file)
index 0000000..15d5d5f
--- /dev/null
@@ -0,0 +1,34 @@
+
+#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
+
diff --git a/PWG0/FirstPhysics/AliAnalysisTaskFirstPhysics.cxx b/PWG0/FirstPhysics/AliAnalysisTaskFirstPhysics.cxx
new file mode 100644 (file)
index 0000000..936c523
--- /dev/null
@@ -0,0 +1,308 @@
+
+#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;
+  }
+}
diff --git a/PWG0/FirstPhysics/AliAnalysisTaskFirstPhysics.h b/PWG0/FirstPhysics/AliAnalysisTaskFirstPhysics.h
new file mode 100644 (file)
index 0000000..89911de
--- /dev/null
@@ -0,0 +1,91 @@
+// 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
+
diff --git a/PWG0/FirstPhysics/runFPexample.C b/PWG0/FirstPhysics/runFPexample.C
new file mode 100644 (file)
index 0000000..c074ab1
--- /dev/null
@@ -0,0 +1,245 @@
+
+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);
+}
diff --git a/PWG0/PWG0FPLinkDef.h b/PWG0/PWG0FPLinkDef.h
new file mode 100644 (file)
index 0000000..8296043
--- /dev/null
@@ -0,0 +1,10 @@
+#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