Add new version of macros for RSN analysis
authorpulvir <pulvir@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 6 Apr 2011 12:42:25 +0000 (12:42 +0000)
committerpulvir <pulvir@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 6 Apr 2011 12:42:25 +0000 (12:42 +0000)
18 files changed:
PWG2/RESONANCES/macros/train/AddAnalysisTaskRsn.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/AddRsnInputHandler.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/AddRsnInputHandlerNew.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/AddTenderSupplies.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/AnalysisSetup.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/PluginByRunProof.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigEvent.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigKStarTPC.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigMonitorTPC.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigPhiAll.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigPhiITS.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigPhiKaonTest.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigPhiTPC.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigPhiTest.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/RsnConfigTest.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/Tender.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/runLocal.C [new file with mode: 0644]
PWG2/RESONANCES/macros/train/runPluginProof.C [new file with mode: 0644]

diff --git a/PWG2/RESONANCES/macros/train/AddAnalysisTaskRsn.C b/PWG2/RESONANCES/macros/train/AddAnalysisTaskRsn.C
new file mode 100644 (file)
index 0000000..e233635
--- /dev/null
@@ -0,0 +1,117 @@
+//
+// General macro to configure the RSN analysis task.
+// It calls all configs desired by the user, by means
+// of the boolean switches defined in the first lines.
+// ---
+// Inputs:
+//  1) flag to know if running on MC or data
+//  2) path where all configs are stored
+// ---
+// Returns:
+//  kTRUE  --> initialization successful
+//  kFALSE --> initialization failed (some config gave errors)
+//
+
+Bool_t useEvent       = 1;
+Bool_t useTest        = 0;
+Bool_t useKaonMonitor = 1;
+Bool_t usePhiTPC      = 1;
+Bool_t useKStarTPC    = 0;
+
+Bool_t AddAnalysisTaskRsn
+(
+   Bool_t      isMC,
+   Bool_t      useCentrality,
+   Bool_t      checkPileUp,
+   const char *path = "$(HOME)/code/resonances/alice-rsn-package/PWG2resonances/RESONANCES/macros/test/pulvir"
+)
+{  
+   //
+   // -- INITIALIZATION ----------------------------------------------------------------------------
+   //
+   
+   // retrieve analysis manager
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+
+   // create the task and connect with physics selection
+   AliRsnAnalysisTask *task = new AliRsnAnalysisTask("RSN");
+   task->SelectCollisionCandidates();
+   mgr->AddTask(task);
+   
+   //
+   // -- EVENT CUTS (same for all configs) ---------------------------------------------------------
+   //
+   
+   // cut on primary vertex:
+   // - 2nd argument --> |Vz| range
+   // - 3rd argument --> minimum required number of contributors
+   // - 4th argument --> tells if TPC stand-alone vertexes must be accepted
+   AliRsnCutPrimaryVertex *cutVertex = new AliRsnCutPrimaryVertex("cutVertex", 10.0, 0, kFALSE);
+   
+   // set the check for pileup
+   ::Info("AddAnalysisTaskRsn", "Check of pile-up from SPD is %s", (checkPileUp ? "active" : "disabled"));
+   cutVertex->SetCheckPileUp(checkPileUp);
+      
+   // define and fill cut set
+   AliRsnCutSet *eventCuts = new AliRsnCutSet("eventCuts", AliRsnTarget::kEvent);
+   eventCuts->AddCut(cutVertex);
+   eventCuts->SetCutScheme(cutVertex->GetName());
+   
+   //
+   // -- CONFIGS -----------------------------------------------------------------------------------
+   //
+   
+   // add configs and count how many are added
+   // will return kFALSE if none is added
+   
+   Int_t added = 0;
+   
+   if (useTest) {
+      // NOTE: this is a test and will had its own definition of event cuts
+      // ----> will not use those defined above
+      gROOT->LoadMacro(Form("%s/RsnConfigTest.C", path));
+      if (!RsnConfigTest(task, isMC)) return kFALSE;
+      added++; 
+   }
+   
+   if (useEvent) {
+      gROOT->LoadMacro(Form("%s/RsnConfigEvent.C", path));
+      if (!RsnConfigEvent(task, isMC, useCentrality, eventCuts)) return kFALSE;
+      added++;
+   }
+   
+   if (useKaonMonitor) {
+      gROOT->LoadMacro(Form("%s/RsnConfigMonitorTPC.C", path));
+      if (!RsnConfigMonitorTPC(task, isMC, useCentrality, eventCuts)) return kFALSE;
+      added++;
+   }
+   
+   if (usePhiTPC) {
+      gROOT->LoadMacro(Form("%s/RsnConfigPhiTPC.C", path));
+      if (!RsnConfigPhiTPC(task, isMC, useCentrality, eventCuts)) return kFALSE;
+      added++;
+   }
+   
+   if (useKStarTPC) {
+      gROOT->LoadMacro(Form("%s/RsnConfigKStarTPC.C", path));
+      if (!RsnConfigKStarTPC(task, isMC, useCentrality, eventCuts)) return kFALSE;
+      added++;
+   }
+   
+   ::Info("AddAnalysisTaskRsn.C", "Added %d configs", added);
+   if (!added) {
+      ::Error("AddAnalysisTaskRsn.C", "Cannot process an empty task!");
+      return kFALSE;
+   }
+   
+   //
+   // -- CONTAINERS --------------------------------------------------------------------------------
+   //
+   
+   const char *file = AliAnalysisManager::GetCommonFileName();
+   AliAnalysisDataContainer *output = mgr->CreateContainer("RsnOut", TList::Class(), AliAnalysisManager::kOutputContainer, file);
+   mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
+   mgr->ConnectOutput(task, 1, output);
+
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/AddRsnInputHandler.C b/PWG2/RESONANCES/macros/train/AddRsnInputHandler.C
new file mode 100644 (file)
index 0000000..94194a7
--- /dev/null
@@ -0,0 +1,194 @@
+//
+// This macro adds the specific RSN input handler, with all single particle cuts
+//
+void AddRsnInputHandler(Bool_t isMC, AliMultiInputEventHandler *multi)
+{
+   void myError  (const char *msg) {::Error  ("AddRsnInputHandler", msg);}
+   void myWarning(const char *msg) {::Warning("AddRsnInputHandler", msg);}
+   void myInfo   (const char *msg) {::Info   ("AddRsnInputHandler", msg);}
+   
+   if (!multi) {
+      ::Error("AddRsnInputHandler", "Required a WELL INITIALIZED AliMultiInputEventHandler object");
+      return;
+   }
+   
+   //---------------------------------------------
+   //  Define single cuts
+   //---------------------------------------------
+
+   // Track quality for ITS standalone:
+   // this cut is used to select tracks of good quality, irrespective of the PID.
+   // When adding status flags, the second argument tells if each considered flag
+   // must be active or not in the track status, since the ITS-SA tracks need that
+   // some of them are OFF (e.g.: kTPCin)
+   AliRsnCutTrackQuality *cutQualityITS = new AliRsnCutTrackQuality("cutQualityITS");
+   cutQualityITS->AddStatusFlag(AliESDtrack::kITSin    , kTRUE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kTPCin    , kFALSE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kITSrefit , kTRUE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kTPCrefit , kFALSE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kITSpureSA, kFALSE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kITSpid   , kTRUE);
+   cutQualityITS->SetPtRange(0.15, 1E+20);
+   cutQualityITS->SetEtaRange(-0.8, 0.8);
+   cutQualityITS->SetDCARPtFormula("0.0595+0.0182/pt^1.55");
+   cutQualityITS->SetDCAZmax(2.0);
+   cutQualityITS->SetSPDminNClusters(1);
+   cutQualityITS->SetITSminNClusters(4);
+   cutQualityITS->SetITSmaxChi2(2.0);
+   cutQualityITS->SetTPCminNClusters(0);
+   cutQualityITS->SetTPCmaxChi2(1E+10);
+   cutQualityITS->SetRejectKinkDaughters();
+      
+   // Track quality for TPC+ITS:
+   // works exactly like the one above, but has settings for selecting TPC+ITS tracks
+   // in this case, the flags required are all necessary, so here the procedure is simpler
+   AliRsnCutTrackQuality *cutQualityTPC = new AliRsnCutTrackQuality("cutQualityTPC");
+   cutQualityTPC->AddStatusFlag(AliESDtrack::kTPCin   , kTRUE);
+   cutQualityTPC->AddStatusFlag(AliESDtrack::kTPCrefit, kTRUE);
+   cutQualityTPC->AddStatusFlag(AliESDtrack::kITSrefit, kTRUE);
+   cutQualityTPC->SetPtRange(0.15, 1E+20);
+   cutQualityTPC->SetEtaRange(-0.8, 0.8);
+   cutQualityTPC->SetDCARPtFormula("0.0182+0.0350/pt^1.01");
+   cutQualityTPC->SetDCAZmax(2.0);
+   cutQualityTPC->SetSPDminNClusters(1);
+   cutQualityTPC->SetITSminNClusters(0);
+   cutQualityTPC->SetITSmaxChi2(1E+20);
+   cutQualityTPC->SetTPCminNClusters(70);
+   cutQualityTPC->SetTPCmaxChi2(4.0);
+   cutQualityTPC->SetRejectKinkDaughters();
+   
+   // ITS PID
+   // -- pions: 3sigma dE/dx cut
+   // -- kaons: 3sigma dE/dx cut
+   //
+   // NOTE:
+   // --> need to know if running on MC or data (for initializing the BB)
+   AliRsnCutPIDITS *cutPIDITSpion = new AliRsnCutPIDITS("cutPIDITSpion", AliPID::kPion, -3.0, 3.0);
+   AliRsnCutPIDITS *cutPIDITSkaon = new AliRsnCutPIDITS("cutPIDITSkaon", AliPID::kKaon, -3.0, 3.0);
+   cutPIDITSpion->SetMC(isMC);
+   cutPIDITSkaon->SetMC(isMC);
+   
+   // TPC PID
+   // -- pions: 3sigma dE/dx cut
+   // -- kaons: 3(5)sigma dE/dx cut for p_TPC above(below) 350 MeV/c
+   //
+   // NOTE:
+   // --> The initialization of the BB is different between data and MC.
+   AliRsnCutPIDTPC *cutPIDTPCpion  = new AliRsnCutPIDTPC("cutPIDTPCpion" , AliPID::kPion, -3.0, 3.0);
+   AliRsnCutPIDTPC *cutPIDTPCkaonL = new AliRsnCutPIDTPC("cutPIDTPCkaonL", AliPID::kKaon, -5.0, 5.0);
+   AliRsnCutPIDTPC *cutPIDTPCkaonH = new AliRsnCutPIDTPC("cutPIDTPCkaonH", AliPID::kKaon, -3.0, 3.0);
+   
+   // assign the momentum range and tell to reject tracks outside it
+   cutPIDTPCkaonL->SetMomentumRange(0.00, 0.35);
+   cutPIDTPCkaonH->SetMomentumRange(0.35, 1E20);
+   cutPIDTPCkaonL->SetRejectOutside(kTRUE);
+   cutPIDTPCkaonH->SetRejectOutside(kTRUE);
+   
+   // BB parameterization depends on data sample (MC, data)
+   // the momentum range is passed and tracks outside it are rejected
+   Double_t bbPar[5];
+   if (isMC) {
+      bbPar[0] = 2.15898 / 50.0;
+      bbPar[1] = 1.75295E1;
+      bbPar[2] = 3.40030E-9;
+      bbPar[3] = 1.96178;
+      bbPar[4] = 3.91720;
+   } else {
+      bbPar[0] = 1.41543 / 50.0;
+      bbPar[1] = 2.63394E1;
+      bbPar[2] = 5.0411E-11;
+      bbPar[3] = 2.12543;
+      bbPar[4] = 4.88663;
+   }
+   cutPIDTPCpion ->SetBBParam(bbPar);
+   cutPIDTPCkaonL->SetBBParam(bbPar);
+   cutPIDTPCkaonH->SetBBParam(bbPar);
+   
+   // TOF PID
+   // -- pions: 3sigma cut
+   // -- kaons: 3sigma cut
+   //
+   // NOTE:
+   // --> since we use also TPC, unmatched tracks are accepted
+   AliRsnCutPIDTOF *cutPIDTOFpion = new AliRsnCutPIDTOF("cutPIDTOFpion", AliPID::kPion, -3.0, 3.0);
+   AliRsnCutPIDTOF *cutPIDTOFkaon = new AliRsnCutPIDTOF("cutPIDTOFkaon", AliPID::kKaon, -3.0, 3.0);
+   cutPIDTOFpion->SetRejectUnmatched(kFALSE);
+   cutPIDTOFkaon->SetRejectUnmatched(kFALSE);
+   
+   //---------------------------------------------
+   //  Combine cuts
+   //---------------------------------------------
+   
+   // make several combinations of cuts:
+   // ITS and TPC standard
+   AliRsnCutSet *cutsQualityITS = new AliRsnCutSet("qualityITS", AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsQualityTPC = new AliRsnCutSet("qualityTPC", AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsPionITS    = new AliRsnCutSet("pionITS"   , AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsPionTPC    = new AliRsnCutSet("pionTPC"   , AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsPionAll    = new AliRsnCutSet("pionAll"   , AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsKaonITS    = new AliRsnCutSet("kaonITS"   , AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsKaonTPC    = new AliRsnCutSet("kaonTPC"   , AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsKaonAll    = new AliRsnCutSet("kaonAll"   , AliRsnTarget::kDaughter);
+   
+   // ITS standalone: quality only
+   cutsQualityITS->AddCut(cutQualityITS);
+   cutsQualityITS->SetCutScheme(cutQualityITS->GetName());
+   
+   // TPC+ITS: quality only
+   cutsQualityTPC->AddCut(cutQualityTPC);
+   cutsQualityTPC->SetCutScheme(cutQualityTPC->GetName());
+   
+   // ITS standalone: quality and ITS PID (pions)
+   cutsPionITS->AddCut(cutQualityITS);
+   cutsPionITS->AddCut(cutPIDITSpion);
+   cutsPionITS->SetCutScheme(Form("%s&%s", cutQualityITS->GetName(), cutPIDITSpion->GetName()));
+   
+   // ITS standalone: quality and ITS PID (kaons)
+   cutsKaonITS->AddCut(cutQualityITS);
+   cutsKaonITS->AddCut(cutPIDITSkaon);
+   cutsKaonITS->SetCutScheme(Form("%s&%s", cutQualityITS->GetName(), cutPIDITSkaon->GetName()));
+   
+   // TPC standalone: quality and TPC + TOF PID (pions)
+   cutsPionTPC->AddCut(cutQualityTPC);
+   cutsPionTPC->AddCut(cutPIDTPCpion);
+   cutsPionTPC->AddCut(cutPIDTOFpion);
+   cutsPionTPC->SetCutScheme(Form("%s & %s & %s", cutQualityTPC->GetName(), cutPIDTPCpion->GetName(), cutPIDTOFpion->GetName()));
+   
+   // TPC standalone: quality and TPC + TOF PID (kaons)
+   cutsKaonTPC->AddCut(cutQualityTPC);
+   cutsKaonTPC->AddCut(cutPIDTPCkaonL);
+   cutsKaonTPC->AddCut(cutPIDTPCkaonH);
+   cutsKaonTPC->AddCut(cutPIDTOFkaon);
+   cutsKaonTPC->SetCutScheme(Form("%s & (%s|%s) & %s", cutQualityTPC->GetName(), cutPIDTPCkaonL->GetName(), cutPIDTPCkaonH->GetName(), cutPIDTOFkaon->GetName()));
+   
+   // all tracks: both qualities and PIDs (pion)
+   cutsPionAll->AddCut(cutQualityITS);
+   cutsPionAll->AddCut(cutQualityTPC);
+   cutsPionAll->AddCut(cutPIDITSpion);
+   cutsPionAll->AddCut(cutPIDTPCpion);
+   cutsPionAll->AddCut(cutPIDTOFpion);
+   cutsPionAll->SetCutScheme(Form("(%s)|(%s)", cutsKaonITS->GetCutScheme().Data(), cutsKaonTPC->GetCutScheme().Data()));
+   
+   // all tracks: both qualities and PIDs (kaon)
+   cutsKaonAll->AddCut(cutQualityITS);
+   cutsKaonAll->AddCut(cutQualityTPC);
+   cutsKaonAll->AddCut(cutPIDITSkaon);
+   cutsKaonAll->AddCut(cutPIDTPCkaonL);
+   cutsKaonAll->AddCut(cutPIDTPCkaonH);
+   cutsKaonAll->AddCut(cutPIDTOFkaon);
+   cutsKaonAll->SetCutScheme(Form("(%s)|(%s)", cutsKaonITS->GetCutScheme().Data(), cutsKaonTPC->GetCutScheme().Data()));
+   
+   // setup selector in the handler and add RSN input handler
+   AliRsnInputHandler *rsnIH = new AliRsnInputHandler();
+   AliRsnDaughterSelector *sel = rsnIH->GetSelector();
+// sel->Add(cutsQualityITS, kTRUE);
+   sel->Add(cutsQualityTPC, kTRUE);
+// sel->Add(cutsPionITS   , kTRUE);
+// sel->Add(cutsPionTPC   , kTRUE);
+// sel->Add(cutsPionAll   , kTRUE);
+// sel->Add(cutsKaonITS   , kTRUE);
+   sel->Add(cutsKaonTPC   , kTRUE);
+// sel->Add(cutsKaonAll   , kTRUE);
+   sel->Init();
+   multi->AddInputEventHandler(rsnIH);
+}
diff --git a/PWG2/RESONANCES/macros/train/AddRsnInputHandlerNew.C b/PWG2/RESONANCES/macros/train/AddRsnInputHandlerNew.C
new file mode 100644 (file)
index 0000000..5ff71a2
--- /dev/null
@@ -0,0 +1,147 @@
+//
+// This macro adds the specific RSN input handler, with all single particle cuts
+//
+void AddRsnInputHandler(Bool_t isMC, AliMultiInputEventHandler *multi)
+{
+   void myError  (const char *msg) {::Error  ("AddRsnInputHandler", msg);}
+   void myWarning(const char *msg) {::Warning("AddRsnInputHandler", msg);}
+   void myInfo   (const char *msg) {::Info   ("AddRsnInputHandler", msg);}
+   
+   if (!multi) {
+      ::Error("AddRsnInputHandler", "Required a WELL INITIALIZED AliMultiInputEventHandler object");
+      return;
+   }
+   
+   //---------------------------------------------
+   //  Define single cuts
+   //---------------------------------------------
+
+   // Track quality for ITS standalone:
+   // this cut is used to select tracks of good quality, irrespective of the PID.
+   // When adding status flags, the second argument tells if each considered flag
+   // must be active or not in the track status, since the ITS-SA tracks need that
+   // some of them are OFF (e.g.: kTPCin)
+   AliRsnCutTrackQuality *cutQualityITS = new AliRsnCutTrackQuality("cutQualityITS");
+   cutQualityITS->AddStatusFlag(AliESDtrack::kITSin    , kTRUE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kTPCin    , kFALSE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kITSrefit , kTRUE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kTPCrefit , kFALSE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kITSpureSA, kFALSE);
+   cutQualityITS->AddStatusFlag(AliESDtrack::kITSpid   , kTRUE);
+   cutQualityITS->SetPtRange(0.15, 1E+20);
+   cutQualityITS->SetEtaRange(-0.8, 0.8);
+   cutQualityITS->SetDCARPtFormula("0.0595+0.0182/pt^1.55");
+   cutQualityITS->SetDCAZmax(2.0);
+   cutQualityITS->SetSPDminNClusters(1);
+   cutQualityITS->SetITSminNClusters(4);
+   cutQualityITS->SetITSmaxChi2(2.0);
+   cutQualityITS->SetTPCminNClusters(0);
+   cutQualityITS->SetTPCmaxChi2(1E+10);
+   cutQualityITS->SetRejectKinkDaughters();
+      
+   // Track quality for TPC+ITS:
+   // works exactly like the one above, but has settings for selecting TPC+ITS tracks
+   // in this case, the flags required are all necessary, so here the procedure is simpler
+   AliRsnCutTrackQuality *cutQualityTPC = new AliRsnCutTrackQuality("cutQualityTPC");
+   cutQualityTPC->AddStatusFlag(AliESDtrack::kTPCin   , kTRUE);
+   cutQualityTPC->AddStatusFlag(AliESDtrack::kTPCrefit, kTRUE);
+   cutQualityTPC->AddStatusFlag(AliESDtrack::kITSrefit, kTRUE);
+   cutQualityTPC->SetPtRange(0.15, 1E+20);
+   cutQualityTPC->SetEtaRange(-0.8, 0.8);
+   cutQualityTPC->SetDCARPtFormula("0.0182+0.0350/pt^1.01");
+   cutQualityTPC->SetDCAZmax(2.0);
+   cutQualityTPC->SetSPDminNClusters(1);
+   cutQualityTPC->SetITSminNClusters(0);
+   cutQualityTPC->SetITSmaxChi2(1E+20);
+   cutQualityTPC->SetTPCminNClusters(70);
+   cutQualityTPC->SetTPCmaxChi2(4.0);
+   cutQualityTPC->SetRejectKinkDaughters();
+   
+   // PID cuts for all needed detectors:
+   // use new implementation based on AliPIDResponse and its related task
+   // requires that AliAnalysisTaskPIDResponse is added otherwise it will raise errors
+   AliRsnCutPIDNSigma *cutPIDITSpion   = new AliRsnCutPIDNSigma("cutPIDITSpion"  , AliPID::kPion, AliRsnCutPIDNSigma::kITS, 3.0);
+   AliRsnCutPIDNSigma *cutPIDTPCpion   = new AliRsnCutPIDNSigma("cutPIDTPCpion"  , AliPID::kPion, AliRsnCutPIDNSigma::kTPC, 3.0);
+   AliRsnCutPIDNSigma *cutPIDTOFpion   = new AliRsnCutPIDNSigma("cutPIDITSpion"  , AliPID::kPion, AliRsnCutPIDNSigma::kTOF, 3.0);
+   AliRsnCutPIDNSigma *cutPIDITSkaon   = new AliRsnCutPIDNSigma("cutPIDITSkaon"  , AliPID::kKaon, AliRsnCutPIDNSigma::kITS, 3.0);
+   AliRsnCutPIDNSigma *cutPIDTPCkaonLo = new AliRsnCutPIDNSigma("cutPIDTPCkaonLo", AliPID::kKaon, AliRsnCutPIDNSigma::kTPC, 5.0);
+   AliRsnCutPIDNSigma *cutPIDTPCkaonHi = new AliRsnCutPIDNSigma("cutPIDTPCkaonHi", AliPID::kKaon, AliRsnCutPIDNSigma::kTPC, 3.0);
+   AliRsnCutPIDNSigma *cutPIDTOFkaon   = new AliRsnCutPIDNSigma("cutPIDITSkaon"  , AliPID::kKaon, AliRsnCutPIDNSigma::kTOF, 3.0);
+   
+   // ITS PID:
+   // - reject unmatched tracks
+   cutPIDITSpion->SetRejectUnmatched();
+   cutPIDITSkaon->SetRejectUnmatched();
+   
+   // TPC PID:
+   // - pions               --> 3 sigma cut
+   // - kaons below 350 MeV --> 5 sigma cut
+   // - kaons above 350 MeV --> 3 sigma cut
+   // - reject unmatched tracks
+   cutPIDTPCkaonLo->SetMomentumRange(0.00, 0.35);
+   cutPIDTPCkaonHi->SetMomentumRange(0.35, 1E20);
+   cutPIDTPCkaonLo->SetRejectOutside();
+   cutPIDTPCkaonHi->SetRejectOutside();
+   cutPIDTPCpion  ->SetRejectUnmatched();
+   cutPIDTPCkaonLo->SetRejectUnmatched();
+   cutPIDTPCkaonHi->SetRejectUnmatched();
+   
+   // TOF PID:
+   // must specify that unmatched tracks must be accepted
+   cutPIDTOFpion->SetRejectUnmatched(kFALSE);
+   cutPIDTOFkaon->SetRejectUnmatched(kFALSE);
+   
+   //---------------------------------------------
+   //  Combine cuts
+   //---------------------------------------------
+   
+   // make several combinations of cuts:
+   // ITS and TPC standard
+   //AliRsnCutSet *cutsQualityITS = new AliRsnCutSet("qualityITS", AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsQualityTPC = new AliRsnCutSet("qualityTPC", AliRsnTarget::kDaughter);
+   //AliRsnCutSet *cutsPionITS    = new AliRsnCutSet("pionITS"   , AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsPionTPC    = new AliRsnCutSet("pionTPC"   , AliRsnTarget::kDaughter);
+   //AliRsnCutSet *cutsKaonITS    = new AliRsnCutSet("kaonITS"   , AliRsnTarget::kDaughter);
+   AliRsnCutSet *cutsKaonTPC    = new AliRsnCutSet("kaonTPC"   , AliRsnTarget::kDaughter);
+   
+   // ITS standalone: quality only
+   //cutsQualityITS->AddCut(cutQualityITS);
+   //cutsQualityITS->SetCutScheme(cutQualityITS->GetName());
+   
+   // TPC+ITS: quality only
+   cutsQualityTPC->AddCut(cutQualityTPC);
+   cutsQualityTPC->SetCutScheme(cutQualityTPC->GetName());
+   
+   // ITS standalone: quality and ITS PID
+   //cutsPionITS->AddCut(cutQualityITS);
+   //cutsPionITS->AddCut(cutPIDITSpion);
+   //cutsPionITS->SetCutScheme(Form("%s&%s", cutQualityITS->GetName(), cutPIDITSpion->GetName()));
+   //cutsKaonITS->AddCut(cutQualityITS);
+   //cutsKaonITS->AddCut(cutPIDITSkaon);
+   //cutsKaonITS->SetCutScheme(Form("%s&%s", cutQualityITS->GetName(), cutPIDITSkaon->GetName()));
+   
+   // TPC standalone: quality and TPC PID
+   cutsPionTPC->AddCut(cutQualityTPC);
+   cutsPionTPC->AddCut(cutPIDTPCpion);
+   cutsPionTPC->AddCut(cutPIDTOFpion);
+   cutsPionTPC->SetCutScheme(Form("%s&%s&%s", cutQualityTPC->GetName(), cutPIDTPCpion->GetName(), cutPIDTOFpion->GetName()));
+   
+   cutsKaonTPC->AddCut(cutQualityTPC);
+   cutsKaonTPC->AddCut(cutPIDTPCkaonLo);
+   cutsKaonTPC->AddCut(cutPIDTPCkaonHi);
+   cutsKaonTPC->AddCut(cutPIDTOFkaon);
+   cutsKaonTPC->SetCutScheme(Form("%s&(%s|%s)&%s", cutQualityTPC->GetName(), cutPIDTPCkaonLo->GetName(), cutPIDTPCkaonHi->GetName(), cutPIDTOFkaon->GetName()));
+   
+   // setup selector in the handler and add RSN input handler
+   AliRsnInputHandler *rsnIH = new AliRsnInputHandler();
+   AliRsnDaughterSelector *sel = rsnIH->GetSelector();
+   //sel->Add(cutsQualityITS, kTRUE);
+   sel->Add(cutsQualityTPC, kTRUE);
+   //sel->Add(cutsPionITS, kTRUE);
+   sel->Add(cutsPionTPC, kTRUE);
+   //sel->Add(cutsKaonITS, kTRUE);
+   sel->Add(cutsKaonTPC, kTRUE);
+   //sel->Add(cutsKaonAll, kTRUE);
+   sel->Init();
+   multi->AddInputEventHandler(rsnIH);
+}
diff --git a/PWG2/RESONANCES/macros/train/AddTenderSupplies.C b/PWG2/RESONANCES/macros/train/AddTenderSupplies.C
new file mode 100644 (file)
index 0000000..733c805
--- /dev/null
@@ -0,0 +1,54 @@
+AliAnalysisTask *AddTenderSupplies
+(
+   Float_t tofres       = 80,
+   Bool_t  corrExpTimes = kFALSE,
+   Bool_t  applyT0      = kFALSE
+)
+{
+   // get the current analysis manager
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   if (!mgr) {
+      Error("AddTask_tender_Tender", "No analysis manager found.");
+      exit(0);
+      return 0;
+   }
+
+   //
+   // === Add tender to the ANALYSIS manager and set default storage =====
+   //
+   AliTender *tender = new AliTender("AnalysisTender");
+   tender->SetCheckEventSelection(kFALSE);
+   //tender->SetDefaultCDBStorage("raw://");
+   tender->SetDefaultCDBStorage("alien://folder=/alice/data/2010/OCDB");
+   mgr->AddTask(tender);
+
+   //
+   // === Attach VZERO supply ============================================
+   //
+   AliVZEROTenderSupply *VZEROtender = new AliVZEROTenderSupply("VZEROtender");
+   tender->AddSupply(VZEROtender);
+
+   //
+   // === Attach TPC supply ==============================================
+   //
+   AliTPCTenderSupply *TPCtender = new AliTPCTenderSupply("TPCtender");
+   tender->AddSupply(TPCtender);
+
+   //
+   // === Attach TOF supply ==============================================
+   //
+   AliTOFTenderSupply *TOFtender = new AliTOFTenderSupply("TOFtender");
+   TOFtender->SetTOFres(tofres);
+   TOFtender->SetApplyT0(applyT0);
+   TOFtender->SetCorrectExpTimes(corrExpTimes);
+   tender->AddSupply(TOFtender);
+
+   //
+   // === Define output containers, please use 'username'_'somename' =====
+   //
+   AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("tender_event", AliESDEvent::Class(), AliAnalysisManager::kExchangeContainer, "default_tender");
+   mgr->ConnectInput(tender,  0, mgr->GetCommonInputContainer());
+   mgr->ConnectOutput(tender,  1, coutput1);
+
+   return tender;
+}
diff --git a/PWG2/RESONANCES/macros/train/AnalysisSetup.C b/PWG2/RESONANCES/macros/train/AnalysisSetup.C
new file mode 100644 (file)
index 0000000..4e17e32
--- /dev/null
@@ -0,0 +1,172 @@
+//
+// This macro sets all the aspects of configuration of an Analysis Train run
+// which are always the same for all kinds of analysis (local, PROOF, AliEn)
+//
+// Inputs:
+//
+//   - taskList       = a string containin all the 'add-task' macros to be used
+//   - options        = a set of keywords which drive some configurations
+//   - outputFileName = name of file produced by train
+//   - configPath     = a path where all required config macros are stored
+//
+// Notes:
+//
+//   - in case the source is an ESD, and if inputs are a MC production
+//     the MC input handler is created by default
+//
+Bool_t AnalysisSetup
+(
+   Bool_t      isMC,
+   Int_t       nmix,
+   const char *options,
+   const char *outputFileName,
+   const char *configPath
+)
+{
+   //
+   // === EXAMINE OPTIONS ==========================================================================
+   //
+
+   // this is done using the utility 'RsnOptions.C'
+   // which provides a unique way to interpret them
+   
+   TString opt(options);
+   opt.ToUpper();
+   opt.ReplaceAll(" ", "");
+   
+   Bool_t isMix      = (nmix > 0);
+   Bool_t isESD      = opt.Contains("ESD");
+   Bool_t isAOD      = opt.Contains("AOD");
+   Bool_t useTender  = opt.Contains("TENDER");
+   Bool_t usePhysSel = opt.Contains("PHYS");
+   Bool_t noV0       = opt.Contains("NOV0");
+   Bool_t useCent    = opt.Contains("CENT");
+   
+   //
+   // === LOAD LIBRARIES ===========================================================================
+   //
+
+   gSystem->Load("libVMC.so");
+   gSystem->Load("libTree.so");
+   gSystem->Load("libPhysics.so");
+   gSystem->Load("libMatrix.so");
+   gSystem->Load("libMinuit.so");
+   gSystem->Load("libXMLParser.so");
+   gSystem->Load("libGui.so");
+   gSystem->Load("libSTEERBase.so");
+   gSystem->Load("libESD.so");
+   gSystem->Load("libAOD.so");
+   gSystem->Load("libANALYSIS.so");
+   gSystem->Load("libANALYSISalice.so");
+   gSystem->Load("libEventMixing.so");
+   gSystem->Load("libCORRFW.so");
+   
+   if (useTender) {
+      ::Info("AnalysisSetup", "Loading tender libraries");
+      gSystem->Load("libTENDER.so");
+      gSystem->Load("libTENDERSupplies.so");
+   }
+   
+   if (!AliAnalysisAlien::SetupPar("PWG2resonances.par")) return kFALSE;
+
+   //
+   // === ANALYSIS MANAGER CONFIGURATION ===========================================================
+   //
+
+   // create analysis manager
+   AliAnalysisManager *mgr = new AliAnalysisManager("RsnAnalysisManager");
+   mgr->SetCommonFileName(outputFileName);
+   ::Info("AnalysisSetup", "Common file name: %s", outputFileName);
+
+   //
+   // === INPUT / OUTPUT HANDLER CONFIGURATION =====================================================
+   //
+
+   ::Info("AnalysisSetup", "Using Multi Handler");
+   // create multi input event handler
+   AliMultiInputEventHandler *multiHandler = new AliMultiInputEventHandler();
+
+   // since there is an exit point above if the job
+   // isn't either ESD or AOD, here we don't recheck that
+   if (isESD) {
+      ::Info("AnalysisSetup", "Creating ESD handler");
+      AliESDInputHandler *esdHandler = new AliESDInputHandler();
+      multiHandler->AddInputEventHandler(esdHandler);
+
+      // if possible, create also MC handler
+      if (isMC) {
+         ::Info("AnalysisSetup", "Creating MC handler");
+         AliMCEventHandler *mcHandler  = new AliMCEventHandler();
+         multiHandler->AddInputEventHandler(mcHandler);
+      }
+   } else {
+      ::Info("AnalysisSetup", "Creating AOD handler");
+      AliAODInputHandler *aodHandler = new AliAODInputHandler();
+      multiHandler->AddInputEventHandler(aodHandler);
+   }
+
+   // add RSN input handler
+   ::Info("AnalysisSetup", "Adding RSN input handler");
+   gROOT->LoadMacro(Form("%s/AddRsnInputHandler.C", configPath));
+   AddRsnInputHandler(isMC, multiHandler);
+   
+   // set the input event handler for manager
+   mgr->SetInputEventHandler(multiHandler);
+   
+   // set event mixing properties, if required
+   if (isMix) {
+      ::Info("AnalysisSetup", "Setting mixing to n = %d", nmix);
+      // define mixing handler
+      AliMixInputEventHandler *mixHandler = new AliMixInputEventHandler(1, nmix);
+      mixHandler->SetInputHandlerForMixing(multiHandler);
+
+      // define binnings
+      AliMixEventPool   *evPool  = new AliMixEventPool();
+      AliMixEventCutObj *multip  = new AliMixEventCutObj(AliMixEventCutObj::kMultiplicity, 1., 10000., 1000.);
+      AliMixEventCutObj *zvertex = new AliMixEventCutObj(AliMixEventCutObj::kZVertex, -10., 10., 4.);
+      AliMixEventCutObj *cent    = new AliMixEventCutObj(AliMixEventCutObj::kCentrality, 0.0, 100.0, 10.0, "V0M");
+
+      // add cuts to handler and handler to manager
+      evPool->AddCut(zvertex);
+      if (useCent) evPool->AddCut(cent); else evPool->AddCut(multip);
+      mixHandler->SetEventPool(evPool);
+      multiHandler->AddInputEventHandler(mixHandler);
+   }
+
+   //
+   // === CONFIGURE AND INSERT PHYSICS SELECTION & TENDER SUPPLY ===================================
+   //
+
+   // add event selection for data if running ESD
+   if (isESD) {
+      // add tender supply for TOF
+      if (useTender) {
+         ::Info("AnalysisSetup", "options '%s' require to add tender", options);
+         gROOT->LoadMacro(Form("%s/AddTenderSupplies.C", configPath));
+         AddTenderSupplies(100.0, kTRUE, kFALSE);
+      }
+
+      // add event selection for data
+      // and swtich off VZERO if tender is not used
+      if (usePhysSel) {
+         ::Info("AnalysisSetup", "options '%s' require to add physics selection", options);
+         gROOT->LoadMacro("$(ALICE_ROOT)/ANALYSIS/macros/AddTaskPhysicsSelection.C");
+         AliPhysicsSelectionTask* physSelTask = AddTaskPhysicsSelection(isMC);
+         if (noV0) {
+            ::Info("AnalysisSetup", "options '%s' require to skip V0 info", options);
+            physSelTask->GetPhysicsSelection()->SetSkipV0(kTRUE);
+         }
+         if (multiHandler) {
+            AliESDInputHandler *esdHandler = dynamic_cast<AliESDInputHandler*>(multiHandler->GetFirstInputEventHandler());
+            esdHandler->SetEventSelection(multiHandler->GetEventSelection());
+         }
+      }
+   }
+   
+   // add PID response task
+   //gROOT->LoadMacro("$(ALICE_ROOT)/ANALYSIS/macros/AddTaskPIDResponse.C");
+   //AddTaskPIDResponse(isMC);
+   
+   ::Info("AnalysisSetup", "Setup successful");
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/PluginByRunProof.C b/PWG2/RESONANCES/macros/train/PluginByRunProof.C
new file mode 100644 (file)
index 0000000..77aadfe
--- /dev/null
@@ -0,0 +1,75 @@
+// ======================================
+// ===== ALIEN PLUGIN CONFIGURATION =====
+// ======================================
+//
+// This macro configures an AliEn plugin in order to launch a job
+// which runs a task from the resonance package on a list of runs
+// which are processed separately.
+//
+// All the possible configuration parameters are arguments
+// of the macro function, even if most of them have default
+// values which the user will rarely change.
+//
+// The macro tries to synchronize some output names, using
+// a unique name ('analysisName') to define all files that
+// describe the output, the analysis macros/executables/JDL.
+//
+// Since the run mode can be more variable than the config
+// it is not set here, but it is required in the run macro
+// which uses the plugin.
+//
+// Considered that the arguments are many, they are explained
+// inside the list of arguments in the macro definition.
+// In ALL cases where a list of strings must be provided, its
+// elements must be separated by a blank character.
+//
+AliAnalysisAlien* PluginByRunProof
+(
+   // all parameters which could often be customized
+   // are placed at the beginning of the macro, while
+   // all others can stay there with their default values:
+   // -- analysisName   --> common name used for naming all analysis related files
+   // -- dataset        --> dataset to be processed
+   // -- testFile       --> used for test mode only
+   // -- clusterName    --> PROOF cluster to be used
+   const char *dataSet,
+   const char *testFile,
+   const char *clusterName,
+   
+   // -- proofReset     --> require or not the PROOF reset
+   // -- alirootMode    --> the way AliROOT library are loaded
+   // -- clearPack      --> to clear or not the PAR libraries
+   Bool_t      proofReset  = kFALSE,
+   const char *alirootMode = "default",
+   Bool_t      clearPack   = kFALSE,
+
+   // standard package versions
+   const char *rootVersion    = "v5-28-00a",
+   const char *aliVersion     = "v4-21-17a-AN"
+)
+{
+   // create plugin object
+   // with specifications which apply to a run-by-run execution
+   // this creates by default also the job structure for merging
+   AliAnalysisAlien *plugin = new AliAnalysisAlien;
+
+   // package versions
+   plugin->SetROOTVersion(rootVersion);
+   plugin->SetAliROOTVersion(aliVersion);
+
+   // additional libraries/includes
+   //plugin->SetAdditionalLibs("libTENDER.so TENDERSupplies.par libEventMixing.so libPWG2resonances.so");
+   plugin->SetAdditionalLibs("libEventMixing.so PWG2resonances.par");
+   
+   // PROOF-specific settings
+   plugin->SetProofCluster(clusterName);
+   plugin->SetProofDataSet(dataSet);
+   plugin->SetProofReset(proofReset);
+   plugin->SetProofConnectGrid(kTRUE);
+   plugin->SetAliRootMode(alirootMode);
+   plugin->SetClearPackages(clearPack);
+   plugin->SetFileForTestMode(testFile);
+
+   // the end!
+   return plugin;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigEvent.C b/PWG2/RESONANCES/macros/train/RsnConfigEvent.C
new file mode 100644 (file)
index 0000000..b54fa6b
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Configuration script for monitor task with 2010 runs
+//
+// It contains a class definition where the cuts for each object
+// are defined separately, functions are initialized and so on.
+// This is used in the main function (named after the file name),
+// which is called by the 'AddTask' function.
+//
+
+Bool_t RsnConfigEvent
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC,
+   Bool_t              useCentrality,
+   AliRsnCutSet       *eventCuts
+)
+{
+   if (!task) myError("NULL task");
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- LOOP DEFINITION ---------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // loop on events
+   AliRsnLoopEvent *loop = new AliRsnLoopEvent("evtLoop");
+   
+   // add cuts to loop
+   loop->SetEventCuts(eventCuts);
+   
+   // add loop to task
+   task->Add(loop);
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- OUTPUTS DEFINITION ------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   Double_t mult[] = { 0.,  1.,  2.,  3.,  4.,  5.,   6.,   7.,   8.,   9.,  10., 11., 12., 13., 
+                      14., 15., 16., 17., 18., 19.,  20.,  21.,  22.,  23.,  24.,  25., 30., 35., 
+                      40., 50., 60., 70., 80., 90., 100., 120., 140., 160., 180., 200., 500.};
+   Int_t    nmult  = sizeof(mult) / sizeof(mult[0]);
+
+   // axes
+   AliRsnValueStd *axisMultESD  = new AliRsnValueStd("MESD", AliRsnValueStd::kEventMultESDCuts , nmult, mult);
+   AliRsnValueStd *axisMultSPD  = new AliRsnValueStd("MSPD", AliRsnValueStd::kEventMultSPD     , nmult, mult);
+   AliRsnValueStd *axisMultMC   = new AliRsnValueStd("MMC" , AliRsnValueStd::kEventMultMC      , nmult, mult);
+   AliRsnValueStd *axisMultTRK  = new AliRsnValueStd("MTRK", AliRsnValueStd::kEventMult        , nmult, mult);
+   AliRsnValueStd *axisCentV0   = new AliRsnValueStd("CNT" , AliRsnValueStd::kEventCentralityV0, 0.0  , 100.0, 1.0);
+   AliRsnValueStd *axisMultTest = new AliRsnValueStd("TEST", AliRsnValueStd::kEventMult        , 1, 1.0 , 1E10);
+   
+   // create output
+   AliRsnListOutput *out = new AliRsnListOutput("evtOut", AliRsnListOutput::kHistoDefault);
+   
+   // always add test axis, used to know how many events had at least one track
+   out->AddValue(axisMultTest);
+   
+   // add values to output:
+   // centrality only if this is requested, otherwise multiplicity
+   if (useCentrality) {
+      ::Info("RsnConfigEvent", "Adding centrality");
+      out->AddValue(axisCentV0);
+   } else {
+      ::Info("RsnConfigEvent", "Adding multiplicity");
+      //out->AddValue(axisMultESD);
+      //out->AddValue(axisMultSPD);
+      out->AddValue(axisMultTRK);
+      if (isMC) {
+         out->AddValue(axisMultMC);
+      }
+   }
+   
+   // add output to loop
+   loop->AddOutput(out);
+   
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigKStarTPC.C b/PWG2/RESONANCES/macros/train/RsnConfigKStarTPC.C
new file mode 100644 (file)
index 0000000..8cf14e4
--- /dev/null
@@ -0,0 +1,188 @@
+//
+// *** Configuration script for KStar->Kpi analysis with 2010 runs ***
+// 
+// A configuration script for RSN package needs to define the followings:
+//
+// (1) decay tree of each resonance to be studied, which is needed to select
+//     true pairs and to assign the right mass to all candidate daughters
+// (2) cuts at all levels: single daughters, tracks, events
+// (3) output objects: histograms or trees
+//
+Bool_t RsnConfigKStarTPC
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC,
+   Bool_t              useCentrality,
+   AliRsnCutSet       *eventCuts
+)
+{
+   if (!task) ::Error("RsnConfigKStarTPC", "NULL task");
+   
+   // we define here a suffix to differentiate names of different setups for the same resonance
+   // and we define also the name of the list of tracks we want to select for the analysis
+   // (if will fail if no lists with this name were added to the RsnInputHandler)
+   const char *suffix     = "tpc";
+   const char *listName1  = "kaonTPC";
+   const char *listName2  = "pionTPC";
+   Bool_t      useCharged = kTRUE;
+   Int_t       listID1    = -1;
+   Int_t       listID2    = -1;
+   
+   // find the index of the corresponding list in the RsnInputHandler
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   AliMultiInputEventHandler *multi = dynamic_cast<AliMultiInputEventHandler*>(mgr->GetInputEventHandler());
+   if (multi) {
+      TObjArray *array = multi->InputEventHandlers();
+      AliRsnInputHandler *rsn = (AliRsnInputHandler*)array->FindObject("rsnInputHandler");
+      if (rsn) {
+         AliRsnDaughterSelector *sel = rsn->GetSelector();
+         listID1 = sel->GetID(listName1, useCharged);
+         listID2 = sel->GetID(listName2, useCharged);
+      }
+   }
+   if (listID1 >= 0 && listID2 >= 0)
+      ::Info("RsnConfigKStarTPC.C", "Required lists '%s' and '%s' stay in positions %d and %d", listName1, listName2, listID1, listID2);
+   else {
+      ::Error("RsnConfigKStarTPC.C", "Required lists '%s' and '%s' absent in handler!", listName1, listName2);
+      return kFALSE;
+   }
+            
+   // ----------------------------------------------------------------------------------------------
+   // -- DEFINITIONS -------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // PAIR DEFINITIONS:
+   // this contains the definition of particle species and charge for both daughters of a resonance,
+   // which are used for the following purposes:
+   // --> species is used to assign the mass to the daughter (e.g. for building invariant mass)
+   // --> charge is used to select what tracks to use when doing the computation loops
+   // When a user wants to compute a like-sign background, he must define also a pair definition
+   // for each like-sign: in case of charged track decays, we need one for ++ and one for --
+   // Last two arguments are necessary only in some cases (but it is not bad to well initialize them):
+   // --> PDG code of resonance, which is used for selecting true pairs, when needed
+   // --> nominal resonance mass, which is used for computing quantities like Y or Mt
+   AliRsnPairDef *kstar_kaonP_pionM = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kPion, '-', 313, 0.896);
+   AliRsnPairDef *kstar_kaonM_pionP = new AliRsnPairDef(AliRsnDaughter::kKaon, '-', AliRsnDaughter::kPion, '+', 313, 0.896);
+   AliRsnPairDef *kstar_kaonP_pionP = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kPion, '+', 313, 0.896);
+   AliRsnPairDef *kstar_kaonM_pionM = new AliRsnPairDef(AliRsnDaughter::kKaon, '-', AliRsnDaughter::kPion, '-', 313, 0.896);
+
+   // PAIR LOOPS:
+   // these are the objects which drive the computations and fill the output histograms
+   // each one requires to be initialized with an AliRsnPairDef object, which provided masses,
+   // last argument tells if the pair is for mixing or not (this can be also set afterwards, anyway)
+   const Int_t     nPairs = 8;
+   Bool_t          addPair[nPairs] = {1, 1, 1, 1, 1, 1, 1, 1};
+   AliRsnLoopPair *kstarLoop[nPairs];
+   kstarLoop[0] = new AliRsnLoopPair(Form("%s_kstar_kaonP_pionM"     , suffix), kstar_kaonP_pionM, kFALSE);
+   kstarLoop[1] = new AliRsnLoopPair(Form("%s_kstar_kaonP_pionM_true", suffix), kstar_kaonP_pionM, kFALSE);
+   kstarLoop[2] = new AliRsnLoopPair(Form("%s_kstar_kaonP_pionM_mix" , suffix), kstar_kaonP_pionM, kTRUE );
+   kstarLoop[3] = new AliRsnLoopPair(Form("%s_kstar_kaonM_pionP"     , suffix), kstar_kaonM_pionP, kFALSE);
+   kstarLoop[4] = new AliRsnLoopPair(Form("%s_kstar_kaonM_pionP_true", suffix), kstar_kaonM_pionP, kFALSE);
+   kstarLoop[5] = new AliRsnLoopPair(Form("%s_kstar_kaonM_pionP_mix" , suffix), kstar_kaonM_pionP, kTRUE );
+   kstarLoop[6] = new AliRsnLoopPair(Form("%s_kstar_kaonP_pionP"     , suffix), kstar_kaonP_pionP, kFALSE);
+   kstarLoop[7] = new AliRsnLoopPair(Form("%s_kstar_kaonM_pionM"     , suffix), kstar_kaonM_pionM, kFALSE);
+
+   // set additional option for true pairs
+   // 1) we select only pairs coming from the same mother, which must have the right PDG code (from pairDef)
+   // 2) we select only pairs decaying according to the right channel (from pairDef species+charge definitions)
+   kstarLoop[1]->SetOnlyTrue(kTRUE);
+   kstarLoop[1]->SetCheckDecay(kTRUE);
+   kstarLoop[4]->SetOnlyTrue(kTRUE);
+   kstarLoop[4]->SetCheckDecay(kTRUE);
+   
+   // don't add true pairs if not MC
+   if (!isMC) addPair[1] = addPair[4] = 0;
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- PAIR CUTS ---------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // for pairs we define a rapidity windows, defined through a cut
+   // --> NOTE: it needs a support AliRsnPairDef from which it takes the mass
+   AliRsnValueStd *valRapidity = new AliRsnValueStd("valY", AliRsnValueStd::kPairY);
+   AliRsnCutValue *cutRapidity = new AliRsnCutValue("kstar_cutY", -0.5, 0.5, isMC);
+   valRapidity->SetSupportObject(kstar_kaonP_pionM);
+   cutRapidity->SetValueObj(valRapidity);
+   
+   // add the cut to a cut set (will be simple, there's only one)
+   AliRsnCutSet *pairCuts = new AliRsnCutSet("kstar_pairCuts", AliRsnTarget::kMother);
+   pairCuts->AddCut(cutRapidity);
+   pairCuts->SetCutScheme(cutRapidity->GetName());
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- COMPUTED VALUES & OUTPUTS -----------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // All values which should be computed are defined here and passed to the computation objects,
+   // since they define all that is computed bye each one, and, in case one output is a histogram
+   // they define the binning and range for that value
+   //
+   // NOTE:
+   // --> multiplicity bins have variable size
+   
+   Double_t mult[] = { 0.,  1.,  2.,  3.,  4.,  5.,   6.,   7.,   8.,   9.,  10., 11., 12., 13., 
+                      14., 15., 16., 17., 18., 19.,  20.,  21.,  22.,  23.,  24.,  25., 30., 35., 
+                      40., 50., 60., 70., 80., 90., 100., 120., 140., 160., 180., 200., 500.};
+   Int_t    nmult  = sizeof(mult) / sizeof(mult[0]);
+   
+   AliRsnValueStd *axisIM      = new AliRsnValueStd("kIM" , AliRsnValueStd::kPairInvMass       ,   0.5,   1.5, 0.0025);
+   AliRsnValueStd *axisRes     = new AliRsnValueStd("RES" , AliRsnValueStd::kPairInvMassRes    ,  -0.5,   0.5, 0.001);
+   AliRsnValueStd *axisPt      = new AliRsnValueStd("PT"  , AliRsnValueStd::kPairPt            ,   0.0,   5.0, 0.1  );
+   AliRsnValueStd *axisCentV0  = new AliRsnValueStd("CNT" , AliRsnValueStd::kEventCentralityV0 ,   0.0, 100.0, 5.0  );
+   AliRsnValueStd *axisMultESD = new AliRsnValueStd("MESD", AliRsnValueStd::kEventMultESDCuts  , nmult, mult);
+   AliRsnValueStd *axisMultSPD = new AliRsnValueStd("MSPD", AliRsnValueStd::kEventMultSPD      , nmult, mult);
+   AliRsnValueStd *axisMultTRK = new AliRsnValueStd("MTRK", AliRsnValueStd::kEventMult         , nmult, mult);
+   AliRsnValueStd *axisMultMC  = new AliRsnValueStd("MMC" , AliRsnValueStd::kEventMultMC       , nmult, mult);
+
+   // create outputs:
+   // we define one for true pairs, where we add resolution, and another without it, for all others
+   // it seems that it is much advantageous to use sparse histograms when adding more than 2 axes
+   AliRsnListOutput *out[2];
+   out[0] = new AliRsnListOutput("res"  , AliRsnListOutput::kHistoSparse);
+   out[1] = new AliRsnListOutput("nores", AliRsnListOutput::kHistoSparse);
+   
+   // add values to outputs:
+   // if centrality is required, we add it only, otherwise we add all multiplicities
+   // other axes (invmass, pt) are always added
+   for (Int_t i = 0; i < 2; i++) {
+      out[i]->AddValue(axisIM);
+      out[i]->AddValue(axisPt);
+      if (useCentrality) {
+         ::Info("RsnConfigKStarTPC.C", "Adding centrality axis");
+         out[i]->AddValue(axisCentV0);
+      } else {
+         ::Info("RsnConfigKStarTPC.C", "Adding multiplicity axes");
+         //out[i]->AddValue(axisMultESD);
+         //out[i]->AddValue(axisMultSPD);
+         out[i]->AddValue(axisMultTRK);
+         if (isMC) out[i]->AddValue(axisMultMC);
+      }
+   }
+   // resolution only in the first
+   out[0]->AddValue(axisRes);
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- ADD SETTINGS TO LOOPS AND LOOPS TO TASK ---------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   for (Int_t ip = 0; ip < nPairs; ip++) {
+      // skip pairs not to be added
+      if (!addPair[ip]) continue;
+      // assign list IDs
+      kstarLoop[ip]->SetListID(0, listID1);
+      kstarLoop[ip]->SetListID(1, listID2);
+      // assign event cuts
+      kstarLoop[ip]->SetEventCuts(eventCuts);
+      // assign pair cuts
+      kstarLoop[ip]->SetPairCuts(pairCuts);
+      // assign outputs
+      if (ip != 1)
+         kstarLoop[ip]->AddOutput(out[1]);
+      else
+         kstarLoop[ip]->AddOutput(out[0]);
+      // add to task
+      task->Add(kstarLoop[ip]);
+   }
+   
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigMonitorTPC.C b/PWG2/RESONANCES/macros/train/RsnConfigMonitorTPC.C
new file mode 100644 (file)
index 0000000..4dfe319
--- /dev/null
@@ -0,0 +1,108 @@
+//
+// *** Configuration script for phi->KK analysis with 2010 runs ***
+// 
+// A configuration script for RSN package needs to define the followings:
+//
+// (1) decay tree of each resonance to be studied, which is needed to select
+//     true pairs and to assign the right mass to all candidate daughters
+// (2) cuts at all levels: single daughters, tracks, events
+// (3) output objects: histograms or trees
+//
+Bool_t RsnConfigMonitorTPC
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC,
+   Bool_t              useCentrality,
+   AliRsnCutSet       *eventCuts
+)
+{
+   void myError  (const char *msg) {::Error  ("RsnConfigPhi", msg);}
+   void myWarning(const char *msg) {::Warning("RsnConfigPhi", msg);}
+   void myInfo   (const char *msg) {::Info   ("RsnConfigPhi", msg);}
+
+   if (!task) myError("NULL task");
+   
+   const char *suffix = "tpcstd";
+      
+   // ==================================================================================================================
+   // == DEFINITIONS ===================================================================================================
+   // ==================================================================================================================
+   
+   // daughter definitions
+   AliRsnDaughterDef *tracks = new AliRsnDaughterDef(AliRsnDaughter::kTrack, 0);
+
+   // computation objects:
+   // these are the objects which drive the computations, whatever it is (histos or tree filling)
+   // and all tracks passed to them will be given the mass according to the reference pair definition
+   // we create two unlike-sign pair computators, one for all pairs and another for true pairs (useful in MC)
+   AliRsnLoopDaughter *loop[3];
+   loop[0] = new AliRsnLoopDaughter(Form("%s_quality", suffix), 0, tracks);
+   loop[1] = new AliRsnLoopDaughter(Form("%s_pion"   , suffix), 0, tracks);
+   loop[2] = new AliRsnLoopDaughter(Form("%s_kaon"   , suffix), 0, tracks);
+
+   // assign the ID of the entry lists to be used by each pair to get selected daughters
+   // in our case, the AliRsnInputHandler contains only one list for selecting kaons
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   AliMultiInputEventHandler *multi = dynamic_cast<AliMultiInputEventHandler*>(mgr->GetInputEventHandler());
+   if (!multi) {
+      myError("Needed a multi input handler!");
+      return kFALSE;
+   }
+   TObjArray *array = multi->InputEventHandlers();
+   AliRsnInputHandler *rsn = (AliRsnInputHandler*)array->FindObject("rsnInputHandler");
+   if (!rsn) {
+      myError("Needed an RSN event handler");
+      return kFALSE;
+   }
+   AliRsnDaughterSelector *sel = rsn->GetSelector();
+   Int_t id[3];
+   id[0] = sel->GetID("qualityTPC", kTRUE);
+   id[1] = sel->GetID("pionTPC", kTRUE);
+   id[2] = sel->GetID("kaonTPC", kTRUE);
+   
+   // ==================================================================================================================
+   // == COMPUTED VALUES & OUTPUTS =====================================================================================
+   // ==================================================================================================================
+   
+   // axes
+   AliRsnValueStd *axisMomTPC = new AliRsnValueStd("pTPC", AliRsnValueStd::kTrackPtpc     , 0.0,   5.0, 0.01 );
+   AliRsnValueStd *axisSigTPC = new AliRsnValueStd("sTPC", AliRsnValueStd::kTrackTPCsignal, 0.0, 500.0, 2.0  );
+   AliRsnValueStd *axisMomTOF = new AliRsnValueStd("pTOF", AliRsnValueStd::kTrackP        , 0.0,   5.0, 0.01 );
+   AliRsnValuePID *axisSigTOF = new AliRsnValuePID("sTOF", AliRsnValuePID::kTOFnsigma     , AliPID::kKaon, -200.0, 200.0, 10.0);
+   
+   // create outputs
+   AliRsnListOutput *outTPC = new AliRsnListOutput("outTPC", AliRsnListOutput::kHistoDefault);
+   AliRsnListOutput *outTOF = new AliRsnListOutput("outTOF", AliRsnListOutput::kHistoDefault);
+   
+   // add values to outputs
+   outTPC->AddValue(axisMomTPC);
+   outTPC->AddValue(axisSigTPC);
+   outTOF->AddValue(axisMomTOF);
+   outTOF->AddValue(axisSigTOF);
+   
+   // ==================================================================================================================
+   // == CONCLUSION ====================================================================================================
+   // ==================================================================================================================
+   
+   for (Int_t i = 0; i < 3; i++) {
+      // list ID
+      if (id[i] < 0) {
+         myError(Form("Required entry list for loop #%d is not added in the selector", i));
+         return kFALSE;
+      }
+      myInfo(Form("Required entry list for loop #%d [%s] is %d", i, loop[i]->GetName(), id[i]));
+      loop[i]->SetListID(id[i]);
+      
+      // event cuts
+      loop[i]->SetEventCuts(eventCuts);
+      
+      // outputs
+      loop[i]->AddOutput(outTPC);
+      loop[i]->AddOutput(outTOF);
+      
+      // add to task
+      task->Add(loop[i]);
+   }
+   
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigPhiAll.C b/PWG2/RESONANCES/macros/train/RsnConfigPhiAll.C
new file mode 100644 (file)
index 0000000..2661e5b
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// *** Configuration script for phi->KK analysis with 2010 runs ***
+// 
+// A configuration script for RSN package needs to define the followings:
+//
+// (1) decay tree of each resonance to be studied, which is needed to select
+//     true pairs and to assign the right mass to all candidate daughters
+// (2) cuts at all levels: single daughters, tracks, events
+// (3) output objects: histograms or trees
+//
+Bool_t RsnConfigPhiAll
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC,
+   Bool_t              isMix,
+   Bool_t              useCentrality
+)
+{
+   void myError  (const char *msg) {::Error  ("RsnConfigPhi", msg);}
+   void myWarning(const char *msg) {::Warning("RsnConfigPhi", msg);}
+   void myInfo   (const char *msg) {::Info   ("RsnConfigPhi", msg);}
+
+   if (!task) myError("NULL task");
+   
+   const char *suffix = "allstd";
+      
+   // ==================================================================================================================
+   // == DEFINITIONS ===================================================================================================
+   // ==================================================================================================================
+   
+   // pair definitions --> decay channels:
+   // in our case, unlike-charged KK pairs for the signal, and like-charged ones for background
+   AliRsnPairDef *pairDef[3];
+   pairDef[0] = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kKaon, '-', 333, 1.019455); // unlike
+   pairDef[1] = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kKaon, '+', 333, 1.019455); // like ++
+   pairDef[2] = new AliRsnPairDef(AliRsnDaughter::kKaon, '-', AliRsnDaughter::kKaon, '-', 333, 1.019455); // like --
+
+   // computation objects:
+   // these are the objects which drive the computations, whatever it is (histos or tree filling)
+   // and all tracks passed to them will be given the mass according to the reference pair definition
+   // we create two unlike-sign pair computators, one for all pairs and another for true pairs (useful in MC)
+   AliRsnLoopPair *pair[4];
+   pair[0] = new AliRsnLoopPair(Form("%s_kaonP_kaonM_phi", suffix), 0, 0, pairDef[0]); // unlike - true
+   pair[1] = new AliRsnLoopPair(Form("%s_kaonP_kaonM_all", suffix), 0, 0, pairDef[0]); // unlike - all
+   pair[2] = new AliRsnLoopPair(Form("%s_kaonP_kaonP_all", suffix), 0, 0, pairDef[1]); // like ++
+   pair[3] = new AliRsnLoopPair(Form("%s_kaonM_kaonM_all", suffix), 0, 0, pairDef[2]); // like --
+
+   // set additional option for true pairs (slot [0])
+   pair[0]->SetOnlyTrue(kTRUE);
+   pair[0]->SetCheckDecay(kTRUE);
+   
+   // assign the ID of the entry lists to be used by each pair to get selected daughters
+   // in our case, the AliRsnInputHandler contains only one list for selecting kaons
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   AliMultiInputEventHandler *multi = dynamic_cast<AliMultiInputEventHandler*>(mgr->GetInputEventHandler());
+   if (!multi) {
+      myError("Needed a multi input handler!");
+      return kFALSE;
+   }
+   TObjArray *array = multi->InputEventHandlers();
+   AliRsnInputHandler *rsn = (AliRsnInputHandler*)array->FindObject("rsnInputHandler");
+   if (!rsn) {
+      myError("Needed an RSN event handler");
+      return kFALSE;
+   }
+   AliRsnDaughterSelector *sel = rsn->GetSelector();
+   Int_t id = sel->GetID("kaonTPC", kTRUE);
+   if (id < 0) {
+      myError("Kaons are not added in the selector");
+      return kFALSE;
+   }
+   myInfo(Form("Selected list is in position #%d", id));
+   for (Int_t i = 0; i < 4; i++) {
+      pair[i]->SetListID(0, id);
+      pair[i]->SetListID(1, id);
+   }
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- EVENT CUTS --------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // in the function for events, we don't cut on centrality or multiplicity, 
+   // since it becomes an axis of the output histogram
+
+   // primary vertex:
+   // - 2nd argument --> |Vz| range
+   // - 3rd argument --> minimum required number of contributors
+   // - 4th argument --> tells if TPC stand-alone vertexes must be accepted
+   // we switch on the check for pileup
+   AliRsnCutPrimaryVertex *cutVertex = new AliRsnCutPrimaryVertex("cutVertex", 10.0, 0, kFALSE);
+   cutVertex->SetCheckPileUp(kTRUE);
+      
+   // primary vertex is always used
+   AliRsnCutSet *eventCuts = new AliRsnCutSet("eventCuts", AliRsnTarget::kEvent);
+   eventCuts->AddCut(cutVertex);
+   eventCuts->SetCutScheme(cutVertex->GetName());
+   
+   // set cuts for each loop
+   for (Int_t i = 0; i < 4; i++) {
+      pair[i]->SetEventCuts(eventCuts);
+   }
+   
+   // ==================================================================================================================
+   // == PAIR CUTS =====================================================================================================
+   // ==================================================================================================================
+   
+   // Rapidity cut
+   // Only thing to consider is that it needs a support object to define mass
+   AliRsnCutValue *cutRapidity = new AliRsnCutValue("cutY", AliRsnValue::kPairY, -0.5, 0.5);
+   cutRapidity->GetValueObj()->SetSupportObject(pairDef[0]);
+
+   // in this case, we add the cut to the specific cut sets of all pairs
+   // and we must then loop over all pairs, to add cuts to the related sets
+   for (Int_t ipair = 0; ipair < 4; ipair++) {
+      pair[ipair]->GetPairCuts()->AddCut(cutRapidity);
+      pair[ipair]->GetPairCuts()->SetCutScheme(cutRapidity->GetName());
+   }
+   
+   // ==================================================================================================================
+   // == COMPUTED VALUES & OUTPUTS =====================================================================================
+   // ==================================================================================================================
+   
+   // All values which should be computed are defined here and passed to the computation objects,
+   // since they define all that is computed bye each one, and, in case one output is a histogram
+   // they define the binning and range for that value
+   //
+   // NOTE:
+   // --> multiplicity bins have variable size
+   
+   Double_t mult[] = { 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13.,  14.,  15.,  16.,  17.,  18.,  19., 
+                      20., 21., 22., 23., 24., 25., 30., 35., 40., 50., 60., 70., 80., 90., 100., 120., 140., 160., 180., 200., 500.};
+   Int_t    nmult  = sizeof(mult) / sizeof(mult[0]);
+   
+   AliRsnValue *axisIM      = new AliRsnValue("IM"  , AliRsnValue::kPairInvMass   ,  0.9, 1.4, 0.001);
+   AliRsnValue *axisRes     = new AliRsnValue("RES" , AliRsnValue::kPairInvMassRes, -0.5, 0.5, 0.001);
+   AliRsnValue *axisPt      = new AliRsnValue("PT"  , AliRsnValue::kPairPt        ,  0.0, 5.0, 0.1  );
+   AliRsnValue *axisMultESD = new AliRsnValue("MESD", AliRsnValue::kEventMultESDCuts, nmult, mult);
+   AliRsnValue *axisMultSPD = new AliRsnValue("MSPD", AliRsnValue::kEventMultSPD    , nmult, mult);
+   AliRsnValue *axisMultMC  = new AliRsnValue("MMC" , AliRsnValue::kEventMultMC     , nmult, mult);
+   AliRsnValue *axisCentV0  = new AliRsnValue("CNT" , AliRsnValue::kEventCentralityV0 , 0.0, 100.0, 10.0);
+
+   // create outputs
+   AliRsnListOutput *out[2];
+   AliRsnListOutput *out[0] = new AliRsnListOutput("phi", AliRsnListOutput::kHistoSparse);
+   AliRsnListOutput *out[1] = new AliRsnListOutput("all", AliRsnListOutput::kHistoSparse);
+   
+   // add values to outputs
+   out[0]->AddValue(axisRes);
+   for (Int_t i = 0; i < 2; i++) {
+      out[i]->AddValue(axisIM);
+      out[i]->AddValue(axisPt);
+      if (useCentrality) {
+         out[i]->AddValue(axisCentV0);
+      } else {
+         out[i]->AddValue(axisMultESD);
+         out[i]->AddValue(axisMultSPD);
+         if (isMC) out[i]->AddValue(axisMultMC);
+      }
+   }
+   
+   // add outputs to pairs
+   pair[0]->AddOutput(out[0]);
+   for (Int_t ipair = 1; ipair < 4; ipair++) {
+      pair[ipair]->AddOutput(out[1]);
+   }
+   
+   // ==================================================================================================================
+   // == CONCLUSION ====================================================================================================
+   // ==================================================================================================================
+   
+   if (isMC && !isMix) task->Add(pair[0]);
+   task->Add(pair[1]);
+   if (!isMix) {
+      task->Add(pair[2]);
+      task->Add(pair[3]);
+   }
+   
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigPhiITS.C b/PWG2/RESONANCES/macros/train/RsnConfigPhiITS.C
new file mode 100644 (file)
index 0000000..0f5f903
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// *** Configuration script for phi->KK analysis with 2010 runs ***
+// 
+// A configuration script for RSN package needs to define the followings:
+//
+// (1) decay tree of each resonance to be studied, which is needed to select
+//     true pairs and to assign the right mass to all candidate daughters
+// (2) cuts at all levels: single daughters, tracks, events
+// (3) output objects: histograms or trees
+//
+Bool_t RsnConfigPhiITS
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC,
+   Bool_t              isMix,
+   Bool_t              useCentrality
+)
+{
+   void myError  (const char *msg) {::Error  ("RsnConfigPhiITS", msg);}
+   void myWarning(const char *msg) {::Warning("RsnConfigPhiITS", msg);}
+   void myInfo   (const char *msg) {::Info   ("RsnConfigPhiITS", msg);}
+
+   if (!task) myError("NULL task");
+   
+   const char *suffix = "itsstd";
+      
+   // ==================================================================================================================
+   // == DEFINITIONS ===================================================================================================
+   // ==================================================================================================================
+   
+   // pair definitions --> decay channels:
+   // in our case, unlike-charged KK pairs for the signal, and like-charged ones for background
+   AliRsnPairDef *pairDef[3];
+   pairDef[0] = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kKaon, '-', 333, 1.019455); // unlike
+   pairDef[1] = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kKaon, '+', 333, 1.019455); // like ++
+   pairDef[2] = new AliRsnPairDef(AliRsnDaughter::kKaon, '-', AliRsnDaughter::kKaon, '-', 333, 1.019455); // like --
+
+   // computation objects:
+   // these are the objects which drive the computations, whatever it is (histos or tree filling)
+   // and all tracks passed to them will be given the mass according to the reference pair definition
+   // we create two unlike-sign pair computators, one for all pairs and another for true pairs (useful in MC)
+   AliRsnLoopPair *pair[4];
+   pair[0] = new AliRsnLoopPair(Form("%s_kaonP_kaonM_phi", suffix), 0, 0, pairDef[0]); // unlike - true
+   pair[1] = new AliRsnLoopPair(Form("%s_kaonP_kaonM_all", suffix), 0, 0, pairDef[0]); // unlike - all
+   pair[2] = new AliRsnLoopPair(Form("%s_kaonP_kaonP_all", suffix), 0, 0, pairDef[1]); // like ++
+   pair[3] = new AliRsnLoopPair(Form("%s_kaonM_kaonM_all", suffix), 0, 0, pairDef[2]); // like --
+
+   // set additional option for true pairs (slot [0])
+   pair[0]->SetOnlyTrue(kTRUE);
+   pair[0]->SetCheckDecay(kTRUE);
+   
+   // assign the ID of the entry lists to be used by each pair to get selected daughters
+   // in our case, the AliRsnInputHandler contains only one list for selecting kaons
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   AliMultiInputEventHandler *multi = dynamic_cast<AliMultiInputEventHandler*>(mgr->GetInputEventHandler());
+   if (!multi) {
+      myError("Needed a multi input handler!");
+      return kFALSE;
+   }
+   TObjArray *array = multi->InputEventHandlers();
+   AliRsnInputHandler *rsn = (AliRsnInputHandler*)array->FindObject("rsnInputHandler");
+   if (!rsn) {
+      myError("Needed an RSN event handler");
+      return kFALSE;
+   }
+   AliRsnDaughterSelector *sel = rsn->GetSelector();
+   Int_t id = sel->GetID("kaonTPC", kTRUE);
+   if (id < 0) {
+      myError("Kaons are not added in the selector");
+      return kFALSE;
+   }
+   myInfo(Form("Selected list is in position #%d", id));
+   for (Int_t i = 0; i < 4; i++) {
+      pair[i]->SetListID(0, id);
+      pair[i]->SetListID(1, id);
+   }
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- EVENT CUTS --------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // in the function for events, we don't cut on centrality or multiplicity, 
+   // since it becomes an axis of the output histogram
+
+   // primary vertex:
+   // - 2nd argument --> |Vz| range
+   // - 3rd argument --> minimum required number of contributors
+   // - 4th argument --> tells if TPC stand-alone vertexes must be accepted
+   // we switch on the check for pileup
+   AliRsnCutPrimaryVertex *cutVertex = new AliRsnCutPrimaryVertex("cutVertex", 10.0, 0, kFALSE);
+   cutVertex->SetCheckPileUp(kTRUE);
+      
+   // primary vertex is always used
+   AliRsnCutSet *eventCuts = new AliRsnCutSet("eventCuts", AliRsnTarget::kEvent);
+   eventCuts->AddCut(cutVertex);
+   eventCuts->SetCutScheme(cutVertex->GetName());
+   
+   // set cuts for each loop
+   for (Int_t i = 0; i < 4; i++) {
+      pair[i]->SetEventCuts(eventCuts);
+   }
+   
+   // ==================================================================================================================
+   // == PAIR CUTS =====================================================================================================
+   // ==================================================================================================================
+   
+   // Rapidity cut
+   // Only thing to consider is that it needs a support object to define mass
+   AliRsnCutValue *cutRapidity = new AliRsnCutValue("cutY", AliRsnValue::kPairY, -0.5, 0.5);
+   cutRapidity->GetValueObj()->SetSupportObject(pairDef[0]);
+
+   // in this case, we add the cut to the specific cut sets of all pairs
+   // and we must then loop over all pairs, to add cuts to the related sets
+   for (Int_t ipair = 0; ipair < 4; ipair++) {
+      pair[ipair]->GetPairCuts()->AddCut(cutRapidity);
+      pair[ipair]->GetPairCuts()->SetCutScheme(cutRapidity->GetName());
+   }
+   
+   // ==================================================================================================================
+   // == COMPUTED VALUES & OUTPUTS =====================================================================================
+   // ==================================================================================================================
+   
+   // All values which should be computed are defined here and passed to the computation objects,
+   // since they define all that is computed bye each one, and, in case one output is a histogram
+   // they define the binning and range for that value
+   //
+   // NOTE:
+   // --> multiplicity bins have variable size
+   
+   Double_t mult[] = { 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13.,  14.,  15.,  16.,  17.,  18.,  19., 
+                      20., 21., 22., 23., 24., 25., 30., 35., 40., 50., 60., 70., 80., 90., 100., 120., 140., 160., 180., 200., 500.};
+   Int_t    nmult  = sizeof(mult) / sizeof(mult[0]);
+   
+   AliRsnValue *axisIM      = new AliRsnValue("IM"  , AliRsnValue::kPairInvMass   ,  0.9, 1.4, 0.001);
+   AliRsnValue *axisRes     = new AliRsnValue("RES" , AliRsnValue::kPairInvMassRes, -0.5, 0.5, 0.001);
+   AliRsnValue *axisPt      = new AliRsnValue("PT"  , AliRsnValue::kPairPt        ,  0.0, 5.0, 0.1  );
+   AliRsnValue *axisMultESD = new AliRsnValue("MESD", AliRsnValue::kEventMultESDCuts, nmult, mult);
+   AliRsnValue *axisMultSPD = new AliRsnValue("MSPD", AliRsnValue::kEventMultSPD    , nmult, mult);
+   AliRsnValue *axisMultMC  = new AliRsnValue("MMC" , AliRsnValue::kEventMultMC     , nmult, mult);
+   AliRsnValue *axisCentV0  = new AliRsnValue("CNT" , AliRsnValue::kEventCentralityV0 , 0.0, 100.0, 10.0);
+
+   // create outputs
+   AliRsnListOutput *out[2];
+   AliRsnListOutput *out[0] = new AliRsnListOutput("phi", AliRsnListOutput::kHistoSparse);
+   AliRsnListOutput *out[1] = new AliRsnListOutput("all", AliRsnListOutput::kHistoSparse);
+   
+   // add values to outputs
+   out[0]->AddValue(axisRes);
+   for (Int_t i = 0; i < 2; i++) {
+      out[i]->AddValue(axisIM);
+      out[i]->AddValue(axisPt);
+      if (useCentrality) {
+         out[i]->AddValue(axisCentV0);
+      } else {
+         out[i]->AddValue(axisMultESD);
+         out[i]->AddValue(axisMultSPD);
+         if (isMC) out[i]->AddValue(axisMultMC);
+      }
+   }
+   
+   // add outputs to pairs
+   pair[0]->AddOutput(out[0]);
+   for (Int_t ipair = 1; ipair < 4; ipair++) {
+      pair[ipair]->AddOutput(out[1]);
+   }
+   
+   // ==================================================================================================================
+   // == CONCLUSION ====================================================================================================
+   // ==================================================================================================================
+   
+   if (isMC && !isMix) task->Add(pair[0]);
+   task->Add(pair[1]);
+   if (!isMix) {
+      task->Add(pair[2]);
+      task->Add(pair[3]);
+   }
+   
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigPhiKaonTest.C b/PWG2/RESONANCES/macros/train/RsnConfigPhiKaonTest.C
new file mode 100644 (file)
index 0000000..0adee79
--- /dev/null
@@ -0,0 +1,182 @@
+//
+// Test config macro for RSN package.
+// It configures:
+// 1) a monitor for all tracks passing quality cuts
+// 2) a monitor for all tracks passing quality + PID cuts
+// 3) an unlike-sign invariant-mass + pt distribution for K+K- pairs
+//
+Bool_t RsnConfigPhiKaonTest
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC
+)
+{
+   if (!task) {
+      ::Error("RsnConfigPhiKaonTest.C", "NULL task");
+      return kFALSE;
+   }
+   
+   const char *suffix = "test";
+      
+   // ----------------------------------------------------------------------------------------------
+   // -- DEFINITIONS -------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // daughter definition for monitor loops
+   // since it is intended to loop over all 'track' like objects (in the sense that we exclude V0s and cascades),
+   // we initialize it using the constructor that requires an AliRsnDaughter::EType and a charge, but since
+   // we want to loop over both charges, we set it to anything which is not '+' '-' or '0', which are tokens for
+   // selecting only positive, only negative or only neutral
+   AliRsnDaughterDef *tracks = new AliRsnDaughterDef(AliRsnDaughter::kTrack, 0);
+   
+   // definition of pair decay tree for phi resonance
+   // here we *must* specify a particle species and a charge, in order to check the decay tree
+   // last arguments are the PDG code and nominal mass of the resonance, which are needed when
+   // one wants to select true pairs only and/or he wants to compute rapidity or Mt 
+   AliRsnPairDef *pairDef = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kKaon, '-', 333, 1.019455);
+   
+   // definition of loop objects:
+   // (a) 1 monitor for all tracks passing quality cuts
+   // (b) 1 monitor for all tracks passing quality+PID cuts
+   // (c) 1 pair filled with all tracks passing same cuts as (b)
+   // (d) 1 pair like (c) but for mixing
+   // (e) 1 pair like (c) but with true pairs only
+   // NOTE: (c) and (d) are instantiated with same settings, they will be made
+   //       different after some settings done in second moment
+   AliRsnLoopDaughter *loopQuality = new AliRsnLoopDaughter(Form("%s_mon_quality", suffix), 0, tracks);
+   AliRsnLoopDaughter *loopPID     = new AliRsnLoopDaughter(Form("%s_mon_pid"    , suffix), 0, tracks);
+   AliRsnLoopPair     *loopPhi     = new AliRsnLoopPair    (Form("%s_unlike"     , suffix), pairDef);
+   AliRsnLoopPair     *loopPhiMix  = new AliRsnLoopPair    (Form("%s_unlike"     , suffix), pairDef);
+   AliRsnLoopPair     *loopPhiTrue = new AliRsnLoopPair    (Form("%s_trues"      , suffix), pairDef);
+   
+   // set additional option for true pairs (slot [0])
+   loopPhiTrue->SetOnlyTrue(kTRUE);
+   loopPhiTrue->SetCheckDecay(kTRUE);
+   
+   // set mixing options
+   loopPhi    ->SetMixed(kFALSE);
+   loopPhiMix ->SetMixed(kTRUE);
+   loopPhiTrue->SetMixed(kFALSE);
+   
+   // assign the ID of the entry lists to be used by each pair to get selected daughters
+   // in our case, the AliRsnInputHandler contains only one list for selecting kaons
+   Int_t idQuality, idPID;
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   AliMultiInputEventHandler *multi = dynamic_cast<AliMultiInputEventHandler*>(mgr->GetInputEventHandler());
+   if (!multi) {
+      myError("Needed a multi input handler!");
+      return kFALSE;
+   }
+   TObjArray *array = multi->InputEventHandlers();
+   AliRsnInputHandler *rsn = (AliRsnInputHandler*)array->FindObject("rsnInputHandler");
+   if (!rsn) {
+      myError("Needed an RSN event handler");
+      return kFALSE;
+   }
+   AliRsnDaughterSelector *sel = rsn->GetSelector();
+   idQuality = sel->GetID("qualityTPC", kTRUE);
+   idPID = sel->GetID("kaonTPC", kTRUE);
+   if (idQuality < 0 || idPID < 0) {
+      myError("List problems");
+      return kFALSE;
+   }
+   loopQuality->SetListID(idQuality);
+   loopPID    ->SetListID(idPID);
+   loopPhi    ->SetListID(0, idPID);
+   loopPhi    ->SetListID(1, idPID);
+   loopPhiMix ->SetListID(0, idPID);
+   loopPhiMix ->SetListID(1, idPID);
+   loopPhiTrue->SetListID(0, idPID);
+   loopPhiTrue->SetListID(1, idPID);
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- EVENT CUTS --------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+
+   // primary vertex:
+   // - 2nd argument --> |Vz| range
+   // - 3rd argument --> minimum required number of contributors
+   // - 4th argument --> tells if TPC stand-alone vertexes must be accepted
+   // we switch on the check for pileup
+   AliRsnCutPrimaryVertex *cutVertex = new AliRsnCutPrimaryVertex("cutVertex", 10.0, 0, kFALSE);
+   cutVertex->SetCheckPileUp(kTRUE);
+      
+   // primary vertex is always used
+   AliRsnCutSet *eventCuts = new AliRsnCutSet("eventCuts", AliRsnTarget::kEvent);
+   eventCuts->AddCut(cutVertex);
+   eventCuts->SetCutScheme(cutVertex->GetName());
+   
+   // add the event cuts to all loops
+   loopQuality->SetEventCuts(eventCuts);
+   loopPID    ->SetEventCuts(eventCuts);
+   loopPhi    ->SetEventCuts(eventCuts);
+   loopPhi    ->SetEventCuts(eventCuts);
+   loopPhiMix ->SetEventCuts(eventCuts);
+   loopPhiMix ->SetEventCuts(eventCuts);
+   loopPhiTrue->SetEventCuts(eventCuts);
+   loopPhiTrue->SetEventCuts(eventCuts);
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- PAIR CUTS ---------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // for pairs we define a rapidity windows, defined through a cut
+   // --> NOTE: it needs a support AliRsnPairDef from which it takes the mass
+   AliRsnValueStd *valRapidity = new AliRsnValueStd("valY", AliRsnValueStd::kPairY);
+   AliRsnCutValue *cutRapidity = new AliRsnCutValue("cutY", -0.5, 0.5, isMC);
+   valRapidity->SetSupportObject(pairDef);
+   cutRapidity->SetValueObj(valRapidity);
+   
+   // cut set
+   AliRsnCutSet *pairCuts = new AliRsnCutSet("pairCuts", AliRsnTarget::kMother);
+   pairCuts->AddCut(cutRapidity);
+   pairCuts->SetCutScheme(cutRapidity->GetName());
+   
+   // add cut to pair loops only
+   loopPhi    ->SetPairCuts(pairCuts);
+   loopPhi    ->SetPairCuts(pairCuts);
+   loopPhiMix ->SetPairCuts(pairCuts);
+   loopPhiMix ->SetPairCuts(pairCuts);
+   loopPhiTrue->SetPairCuts(pairCuts);
+   loopPhiTrue->SetPairCuts(pairCuts);
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- COMPUTED VALUES & OUTPUTS -----------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   AliRsnValueStd *axisIM     = new AliRsnValueStd("IM"  , AliRsnValueStd::kPairInvMass   , 0.9,   1.4, 0.001);
+   AliRsnValueStd *axisPt     = new AliRsnValueStd("PT"  , AliRsnValueStd::kPairPt        , 0.0,   5.0, 0.1  );
+   AliRsnValueStd *axisMomTPC = new AliRsnValueStd("pTPC", AliRsnValueStd::kTrackPtpc     , 0.0,   5.0, 0.01 );
+   AliRsnValueStd *axisSigTPC = new AliRsnValueStd("sTPC", AliRsnValueStd::kTrackTPCsignal, 0.0, 500.0, 2.0  );
+   
+   // output for monitors:
+   // 2D histogram with TPC signal vs TPC momentum
+   AliRsnListOutput *outMonitor = new AliRsnListOutput("mon", AliRsnListOutput::kHistoDefault);
+   outMonitor->AddValue(axisMomTPC);
+   outMonitor->AddValue(axisSigTPC);
+   
+   // output for pairs:
+   // 2D histogram with inv.mass vs pt
+   AliRsnListOutput *outPair = new AliRsnListOutput("pair", AliRsnListOutput::kHistoDefault);
+   outPair->AddValue(axisIM);
+   outPair->AddValue(axisPt);
+   
+   // add outputs to loops
+   loopQuality->AddOutput(outMonitor);
+   loopPID    ->AddOutput(outMonitor);
+   loopPhi    ->AddOutput(outPair);
+   loopPhiMix ->AddOutput(outPair);
+   loopPhiTrue->AddOutput(outPair);
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- CONCLUSION --------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   task->Add(loopQuality);
+   task->Add(loopPID    );
+   task->Add(loopPhi    );
+   task->Add(loopPhiMix );
+   task->Add(loopPhiTrue);
+   
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigPhiTPC.C b/PWG2/RESONANCES/macros/train/RsnConfigPhiTPC.C
new file mode 100644 (file)
index 0000000..343d53e
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// *** Configuration script for phi->KK analysis with 2010 runs ***
+// 
+// A configuration script for RSN package needs to define the followings:
+//
+// (1) decay tree of each resonance to be studied, which is needed to select
+//     true pairs and to assign the right mass to all candidate daughters
+// (2) cuts at all levels: single daughters, tracks, events
+// (3) output objects: histograms or trees
+//
+Bool_t RsnConfigPhiTPC
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC,
+   Bool_t              useCentrality,
+   AliRsnCutSet       *eventCuts
+)
+{
+   if (!task) ::Error("RsnConfigPhiTPC", "NULL task");
+   
+   // we define here a suffix to differentiate names of different setups for the same resonance
+   // and we define also the name of the list of tracks we want to select for the analysis
+   // (if will fail if no lists with this name were added to the RsnInputHandler)
+   const char *suffix     = "tpc";
+   const char *listName   = "kaonTPC";
+   Bool_t      useCharged = kTRUE;
+   Int_t       listID     = -1;
+   
+   // find the index of the corresponding list in the RsnInputHandler
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   AliMultiInputEventHandler *multi = dynamic_cast<AliMultiInputEventHandler*>(mgr->GetInputEventHandler());
+   if (multi) {
+      TObjArray *array = multi->InputEventHandlers();
+      AliRsnInputHandler *rsn = (AliRsnInputHandler*)array->FindObject("rsnInputHandler");
+      if (rsn) {
+         AliRsnDaughterSelector *sel = rsn->GetSelector();
+         listID = sel->GetID(listName, useCharged);
+      }
+   }
+   if (listID >= 0)
+      ::Info("RsnConfigPhiTPC.C", "Required list '%s' stays in position %d", listName, listID);
+   else {
+      ::Error("RsnConfigPhiTPC.C", "Required list '%s' absent in handler!", listName);
+      return kFALSE;
+   }
+            
+   // ----------------------------------------------------------------------------------------------
+   // -- DEFINITIONS -------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // PAIR DEFINITIONS:
+   // this contains the definition of particle species and charge for both daughters of a resonance,
+   // which are used for the following purposes:
+   // --> species is used to assign the mass to the daughter (e.g. for building invariant mass)
+   // --> charge is used to select what tracks to use when doing the computation loops
+   // When a user wants to compute a like-sign background, he must define also a pair definition
+   // for each like-sign: in case of charged track decays, we need one for ++ and one for --
+   // Last two arguments are necessary only in some cases (but it is not bad to well initialize them):
+   // --> PDG code of resonance, which is used for selecting true pairs, when needed
+   // --> nominal resonance mass, which is used for computing quantities like Y or Mt
+   AliRsnPairDef *phi_kaonP_kaonM = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kKaon, '-', 333, 1.019455);
+   AliRsnPairDef *phi_kaonP_kaonP = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kKaon, '+', 333, 1.019455);
+   AliRsnPairDef *phi_kaonM_kaonM = new AliRsnPairDef(AliRsnDaughter::kKaon, '-', AliRsnDaughter::kKaon, '-', 333, 1.019455);
+
+   // PAIR LOOPS:
+   // these are the objects which drive the computations and fill the output histograms
+   // each one requires to be initialized with an AliRsnPairDef object, which provided masses,
+   // last argument tells if the pair is for mixing or not (this can be also set afterwards, anyway)
+   const Int_t     nPairs = 5;
+   Bool_t          addPair[nPairs] = {1, 1, 1, 1, 1};
+   AliRsnLoopPair *phiLoop[nPairs];
+   phiLoop[0] = new AliRsnLoopPair(Form("%s_phi_kaonP_kaonM"     , suffix), phi_kaonP_kaonM, kFALSE);
+   phiLoop[1] = new AliRsnLoopPair(Form("%s_phi_kaonP_kaonM_true", suffix), phi_kaonP_kaonM, kFALSE);
+   phiLoop[2] = new AliRsnLoopPair(Form("%s_phi_kaonP_kaonM_mix" , suffix), phi_kaonP_kaonM, kTRUE );
+   phiLoop[3] = new AliRsnLoopPair(Form("%s_phi_kaonP_kaonP"     , suffix), phi_kaonP_kaonP, kFALSE);
+   phiLoop[4] = new AliRsnLoopPair(Form("%s_phi_kaonM_kaonM"     , suffix), phi_kaonM_kaonM, kFALSE);
+
+   // set additional option for true pairs
+   // 1) we select only pairs coming from the same mother, which must have the right PDG code (from pairDef)
+   // 2) we select only pairs decaying according to the right channel (from pairDef species+charge definitions)
+   phiLoop[1]->SetOnlyTrue(kTRUE);
+   phiLoop[1]->SetCheckDecay(kTRUE);
+   
+   // don't add true pairs if not MC
+   if (!isMC) addPair[1] = 0;
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- PAIR CUTS ---------------------------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // for pairs we define a rapidity windows, defined through a cut
+   // --> NOTE: it needs a support AliRsnPairDef from which it takes the mass
+   AliRsnValueStd *valRapidity = new AliRsnValueStd("valY", AliRsnValueStd::kPairY);
+   AliRsnCutValue *cutRapidity = new AliRsnCutValue("phi_cutY", -0.5, 0.5, isMC);
+   valRapidity->SetSupportObject(phi_kaonP_kaonM);
+   cutRapidity->SetValueObj(valRapidity);
+   
+   // add the cut to a cut set (will be simple, there's only one)
+   AliRsnCutSet *pairCuts = new AliRsnCutSet("phi_pairCuts", AliRsnTarget::kMother);
+   pairCuts->AddCut(cutRapidity);
+   pairCuts->SetCutScheme(cutRapidity->GetName());
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- COMPUTED VALUES & OUTPUTS -----------------------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   // All values which should be computed are defined here and passed to the computation objects,
+   // since they define all that is computed bye each one, and, in case one output is a histogram
+   // they define the binning and range for that value
+   //
+   // NOTE:
+   // --> multiplicity bins have variable size
+   
+   Double_t mult[] = { 0.,  1.,  2.,  3.,  4.,  5.,   6.,   7.,   8.,   9.,  10., 11., 12., 13., 
+                      14., 15., 16., 17., 18., 19.,  20.,  21.,  22.,  23.,  24.,  25., 30., 35., 
+                      40., 50., 60., 70., 80., 90., 100., 120., 140., 160., 180., 200., 500.};
+   Int_t    nmult  = sizeof(mult) / sizeof(mult[0]);
+   
+   AliRsnValueStd *axisIM      = new AliRsnValueStd("pIM"  , AliRsnValueStd::kPairInvMass       ,   0.9,   1.4, 0.001);
+   AliRsnValueStd *axisRes     = new AliRsnValueStd("RES"  , AliRsnValueStd::kPairInvMassRes    ,  -0.5,   0.5, 0.001);
+   AliRsnValueStd *axisPt      = new AliRsnValueStd("PT"   , AliRsnValueStd::kPairPt            ,   0.0,   5.0, 0.1  );
+   AliRsnValueStd *axisCentV0  = new AliRsnValueStd("CNT"  , AliRsnValueStd::kEventCentralityV0 ,   0.0, 100.0, 5.0  );
+   AliRsnValueStd *axisMultESD = new AliRsnValueStd("MESD" , AliRsnValueStd::kEventMultESDCuts  , nmult, mult);
+   AliRsnValueStd *axisMultSPD = new AliRsnValueStd("MSPD" , AliRsnValueStd::kEventMultSPD      , nmult, mult);
+   AliRsnValueStd *axisMultTRK = new AliRsnValueStd("MTRK" , AliRsnValueStd::kEventMult         , nmult, mult);
+   AliRsnValueStd *axisMultMC  = new AliRsnValueStd("MMC"  , AliRsnValueStd::kEventMultMC       , nmult, mult);
+
+   // create outputs:
+   // we define one for true pairs, where we add resolution, and another without it, for all others
+   // it seems that it is much advantageous to use sparse histograms when adding more than 2 axes
+   AliRsnListOutput *out[2];
+   out[0] = new AliRsnListOutput("res"  , AliRsnListOutput::kHistoSparse);
+   out[1] = new AliRsnListOutput("nores", AliRsnListOutput::kHistoSparse);
+   
+   // add values to outputs:
+   // if centrality is required, we add it only, otherwise we add all multiplicities
+   // other axes (invmass, pt) are always added
+   for (Int_t i = 0; i < 2; i++) {
+      out[i]->AddValue(axisIM);
+      out[i]->AddValue(axisPt);
+      if (useCentrality) {
+         ::Info("RsnConfigPhiTPC.C", "Adding centrality axis");
+         out[i]->AddValue(axisCentV0);
+      } else {
+         ::Info("RsnConfigPhiTPC.C", "Adding multiplicity axes");
+         //out[i]->AddValue(axisMultESD);
+         //out[i]->AddValue(axisMultSPD);
+         out[i]->AddValue(axisMultTRK);
+         if (isMC) out[i]->AddValue(axisMultMC);
+      }
+   }
+   // resolution only in the first
+   out[0]->AddValue(axisRes);
+   
+   // ----------------------------------------------------------------------------------------------
+   // -- ADD SETTINGS TO LOOPS AND LOOPS TO TASK ---------------------------------------------------
+   // ----------------------------------------------------------------------------------------------
+   
+   for (Int_t ip = 0; ip < nPairs; ip++) {
+      // skip pairs not to be added
+      if (!addPair[ip]) continue;
+      // assign list IDs
+      phiLoop[ip]->SetListID(0, listID);
+      phiLoop[ip]->SetListID(1, listID);
+      // assign event cuts
+      phiLoop[ip]->SetEventCuts(eventCuts);
+      // assign pair cuts
+      phiLoop[ip]->SetPairCuts(pairCuts);
+      // assign outputs
+      if (ip != 1)
+         phiLoop[ip]->AddOutput(out[1]);
+      else
+         phiLoop[ip]->AddOutput(out[0]);
+      // add to task
+      task->Add(phiLoop[ip]);
+   }
+   
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigPhiTest.C b/PWG2/RESONANCES/macros/train/RsnConfigPhiTest.C
new file mode 100644 (file)
index 0000000..18a3591
--- /dev/null
@@ -0,0 +1,188 @@
+//
+// *** Configuration script for phi->KK analysis with 2010 runs ***
+// 
+// A configuration script for RSN package needs to define the followings:
+//
+// (1) decay tree of each resonance to be studied, which is needed to select
+//     true pairs and to assign the right mass to all candidate daughters
+// (2) cuts at all levels: single daughters, tracks, events
+// (3) output objects: histograms or trees
+//
+Bool_t RsnConfigPhi
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC,
+   Bool_t              isMix,
+   const char         *options
+)
+{
+   void myError  (const char *msg) {::Error  ("RsnConfigPhi", msg);}
+   void myWarning(const char *msg) {::Warning("RsnConfigPhi", msg);}
+   void myInfo   (const char *msg) {::Info   ("RsnConfigPhi", msg);}
+
+   if (!task) myError("NULL task");
+   
+   // ==================================================================================================================
+   // == OPTIONS =======================================================================================================
+   // ==================================================================================================================
+   
+   // Instead or getting confused with plenty of arguments in the macro (with default values),
+   // we use a unique string of options with a set of conventional strings to set up the job:
+   // -- "MC"/"DATA" --> what kind of sample
+   // -- "ITS"/"TPC" --> what tracks to use (ITS standalone and/or TPC+ITS)
+   // -- "xxxPID"    --> add the PID cuts for the detector xxx.
+   // -- "MULT"      --> add axes for multiplicity
+   //
+   // In this point, these options are converted into boolean variables.
+   
+   TString opt(options);
+   opt.ToUpper();
+   opt.ReplaceAll(" ", "");
+   
+   Bool_t addITS  = opt.Contains("ITS");
+   Bool_t addTPC  = opt.Contains("TPC");
+   Bool_t useITS  = opt.Contains("ITSPID");
+   Bool_t useTPC  = opt.Contains("TPCPID");
+   Bool_t useTOF  = opt.Contains("TOFPID");
+   Bool_t useMult = opt.Contains("MULT");
+   
+   // correct options when needed
+   if (!addITS) useITS = kFALSE;
+   if (!addTPC) useTPC = useTOF = kFALSE;
+   
+   // ==================================================================================================================
+   // == DEFINITIONS ===================================================================================================
+   // ==================================================================================================================
+   
+   // daughter definitions
+   AliRsnDaughterDef *defKaonP = new AliRsnDaughterDef(AliRsnDaughter::kKaon, '+');
+   AliRsnDaughterDef *defKaonM = new AliRsnDaughterDef(AliRsnDaughter::kKaon, '-');
+   
+   // pair definitions --> decay channels:
+   // in our case, unlike-charged KK pairs for the signal, and like-charged ones for background
+   AliRsnPairDef *pairDef[3];
+   pairDef[0] = new AliRsnPairDef(defKaonP, defKaonM, 333, 1.019455); // unlike
+   pairDef[1] = new AliRsnPairDef(defKaonP, defKaonP, 333, 1.019455); // like ++
+   pairDef[2] = new AliRsnPairDef(defKaonM, defKaonM, 333, 1.019455); // like --
+
+   // computation objects:
+   // these are the objects which drive the computations, whatever it is (histos or tree filling)
+   // and all tracks passed to them will be given the mass according to the reference pair definition
+   // we create two unlike-sign pair computators, one for all pairs and another for true pairs (useful in MC)
+   AliRsnLoopPair *pair[4];
+   pair[0] = new AliRsnLoopPair(Form("%s_kaonP_kaonM_phi", opt.Data()), 0, 0, pairDef[0]); // unlike - true
+   pair[1] = new AliRsnLoopPair(Form("%s_kaonP_kaonM_all", opt.Data()), 0, 0, pairDef[0]); // unlike - all
+   pair[2] = new AliRsnLoopPair(Form("%s_kaonP_kaonP_all", opt.Data()), 0, 0, pairDef[1]); // like ++
+   pair[3] = new AliRsnLoopPair(Form("%s_kaonM_kaonM_all", opt.Data()), 0, 0, pairDef[2]); // like --
+   
+   // loop on events
+   AliRsnLoopEvent *event = new AliRsnLoopEvent(Form("%s_evt", opt.Data()));
+
+   // set additional option for true pairs (slot [0])
+   pair[0]->SetOnlyTrue(kTRUE);
+   pair[0]->SetCheckDecay(kTRUE);
+   
+   // assign the ID of the entry lists to be used by each pair to get selected daughters
+   // in our case, the AliRsnInputHandler contains only one list for selecting kaons
+   for (Int_t i = 0; i < 4; i++) pair[i]->SetListID(0, 0);
+   
+   // ==================================================================================================================
+   // == COMPUTED VALUES ===============================================================================================
+   // ==================================================================================================================
+   
+   // All values which should be computed are defined here and passed to the computation objects,
+   // since they define all that is computed bye each one, and, in case one output is a histogram
+   // they define the binning and range for that value
+   //
+   // NOTE:
+   // --> multiplicity bins have variable size
+   
+   Double_t mult[] = { 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13.,  14.,  15.,  16.,  17.,  18.,  19., 
+                      20., 21., 22., 23., 24., 25., 30., 35., 40., 50., 60., 70., 80., 90., 100., 120., 140., 160., 180., 200., 500.};
+   Int_t    nmult  = sizeof(mult) / sizeof(mult[0]);
+   
+   AliRsnValue *axisIM      = new AliRsnValue("IM"  , AliRsnValue::kPairInvMass   ,  0.9, 1.4, 0.001);
+   AliRsnValue *axisRes     = new AliRsnValue("RES" , AliRsnValue::kPairInvMassRes, -0.5, 0.5, 0.001);
+   AliRsnValue *axisPt      = new AliRsnValue("PT"  , AliRsnValue::kPairPt        ,  0.0, 5.0, 0.1  );
+   AliRsnValue *axisY       = new AliRsnValue("Y"   , AliRsnValue::kPairY         , -1.1, 1.1, 0.1  );
+   AliRsnValue *axisMultESD = new AliRsnValue("MESD", AliRsnValue::kEventMultESDCuts, nmult, mult);
+   AliRsnValue *axisMultSPD = new AliRsnValue("MSPD", AliRsnValue::kEventMultSPD    , nmult, mult);
+   AliRsnValue *axisMultMC  = new AliRsnValue("MMC" , AliRsnValue::kEventMultMC     , nmult, mult);
+
+   // add values to pairs
+   // NOTE: in previous package version, they were added to functions
+   for (Int_t i = 0; i < 4; i++) {
+      if (i == 0) pair[i]->AddValue(axisRes);
+      pair[i]->AddValue(axisIM);
+      pair[i]->AddValue(axisPt);
+      pair[i]->AddValue(axisY);
+      if (useMult) {
+         ::Info("RsnConfigPhi", "Adding multiplicity computations");
+         pair[i]->AddValue(axisMultESD);
+         pair[i]->AddValue(axisMultSPD);
+         if (isMC) pair[i]->AddValue(axisMultMC);
+         event->AddValue(axisMultESD);
+         event->AddValue(axisMultSPD);
+         if (isMC) event->AddValue(axisMultMC);
+      }
+   }
+      
+   // ==================================================================================================================
+   // == PAIR CUTS =====================================================================================================
+   // ==================================================================================================================
+   
+   // Rapidity cut
+   // Only thing to consider is that it needs a support object to define mass
+   AliRsnCutValue *cutRapidity = new AliRsnCutValue("cutY", AliRsnValue::kPairY, -0.5, 0.5);
+   cutRapidity->GetValueObj()->SetSupportObject(pairDef[0]);
+
+   // in this case, we add the cut to the specific cut sets of all pairs
+   // and we must then loop over all pairs, to add cuts to the related sets
+   for (Int_t ipair = 0; ipair < 4; ipair++) {
+      pair[ipair]->GetPairCuts()->AddCut(cutRapidity);
+      pair[ipair]->GetPairCuts()->SetCutScheme(cutRapidity->GetName());
+      ::Info("RsnConfigPhi", "Scheme for pair cuts: %s", pair[ipair]->GetPairCuts()->GetCutScheme().Data());
+   }
+   
+   // ==================================================================================================================
+   // == OUTPUTS =======================================================================================================
+   // ==================================================================================================================
+   
+   // now we define the outputs
+   // in the new version of package, we use same syntax as TNtuple:
+   // for each output object we define a name, and a list of variables
+   // which must contain a combination of names of the axes added to the pair
+   // and third argument is an enum to decide what kind of output we want
+
+   AliRsnOutput *ntpMult = new AliRsnOutput("ntp1", "MSPD:MESD", AliRsnOutput::kNtuple);
+   AliRsnOutput *ntpIMPt = new AliRsnOutput("ntp2", "IM:PT"    , AliRsnOutput::kNtuple);
+   AliRsnOutput *fcnIMPt = new AliRsnOutput("out1", "IM:PT"    , AliRsnOutput::kHistoDefault);
+   AliRsnOutput *fcnIM   = new AliRsnOutput("out2", "IM"       , AliRsnOutput::kHistoDefault);
+   AliRsnOutput *fcnPt   = new AliRsnOutput("out3", "PT"       , AliRsnOutput::kHistoDefault);
+   AliRsnOutput *fcnRes  = new AliRsnOutput("out4", "IM:PT:RES", AliRsnOutput::kHistoSparse);
+   
+   // add outputs to pairs
+   for (Int_t ipair = 0; ipair < 4; ipair++) {
+      if (!ipair) pair[ipair]->AddOutput(fcnRes);
+      pair[ipair]->AddOutput(ntpIMPt);
+      //pair[ipair]->AddOutput(fcnIMPt);
+      //pair[ipair]->AddOutput(fcnIM);
+      //pair[ipair]->AddOutput(fcnPt);
+   }
+   if (useMult) event->AddOutput(ntpMult);
+   
+   // ==================================================================================================================
+   // == CONCLUSION ====================================================================================================
+   // ==================================================================================================================
+   
+   // add all created objects to the task
+   for (Int_t i = 0; i < 4; i++) {
+      if (i == 0 && !isMC) continue;
+      if (isMix && i != 1) continue;
+      pair[i]->SetMixed(isMix);
+      task->Add(pair[i]);
+   }
+   if (useMult) task->Add(event);
+   
+   return kTRUE;
+}
diff --git a/PWG2/RESONANCES/macros/train/RsnConfigTest.C b/PWG2/RESONANCES/macros/train/RsnConfigTest.C
new file mode 100644 (file)
index 0000000..6724c62
--- /dev/null
@@ -0,0 +1,164 @@
+Bool_t RsnConfigTest
+(
+   AliRsnAnalysisTask *task,
+   Bool_t              isMC
+)
+{
+   // find the index of the corresponding list in the RsnInputHandler
+   const char *listNameQuality = "qualityTPC";
+   const char *listNamePID     = "kaonTPC";
+   Int_t       qualityID       = -1;
+   Int_t       pidID           = -1;
+   AliAnalysisManager        *mgr   = AliAnalysisManager::GetAnalysisManager();
+   AliMultiInputEventHandler *multi = dynamic_cast<AliMultiInputEventHandler*>(mgr->GetInputEventHandler());
+   if (multi) {
+      TObjArray *array = multi->InputEventHandlers();
+      TObjArrayIter next(array);
+      TObject *obj;
+      while ( (obj = next()) ) {
+         if (obj->InheritsFrom(AliRsnInputHandler::Class())) {
+            AliRsnInputHandler *rsn = (AliRsnInputHandler*)obj;
+            AliRsnDaughterSelector *sel = rsn->GetSelector();
+            qualityID = sel->GetID(listNameQuality, kTRUE);
+            pidID = sel->GetID(listNamePID, kTRUE);
+         }
+      }
+   }
+   if (qualityID < 0) {
+      ::Error("RsnConfigTest", "Selector does not contain list for quality only");
+      return kFALSE;
+   }
+   if (pidID < 0) {
+      ::Error("RsnConfigTest", "Selector does not contain list for quality+PID");
+      return kFALSE;
+   }
+   ::Info("RsnConfigTest", "ID for cut set named '%10s' = %d", listNameQuality, qualityID);
+   ::Info("RsnConfigTest", "ID for cut set named '%10s' = %d", listNamePID, pidID);
+   
+   // add pair computation
+   //AddPairLoop(task, isMC, pidID, pidID, "test");
+   
+   // add monitor computation
+   AddMonitorLoop(task, isMC, qualityID, pidID, "test");
+   return kTRUE;
+}
+
+AliRsnCutSet* EventCuts() 
+{
+   // primary vertex:
+   // - 2nd argument --> |Vz| range
+   // - 3rd argument --> minimum required number of contributors
+   // - 4th argument --> tells if TPC stand-alone vertexes must be accepted
+   // we switch on the check for pileup
+   AliRsnCutPrimaryVertex *cutVertex = new AliRsnCutPrimaryVertex("cutVertex", 10.0, 0, kFALSE);
+   cutVertex->SetCheckPileUp(kTRUE);
+      
+   // primary vertex is always used
+   AliRsnCutSet *eventCuts = new AliRsnCutSet("eventCuts", AliRsnTarget::kEvent);
+   eventCuts->AddCut(cutVertex);
+   eventCuts->SetCutScheme(cutVertex->GetName());
+   
+   return eventCuts;
+}
+
+AliRsnCutSet* PairCuts(AliRsnPairDef *support)
+{
+   // for pairs we define a rapidity windows, defined through a cut
+   // --> NOTE: it needs a support AliRsnPairDef from which it takes the mass
+   AliRsnValueStd *valRapidity = new AliRsnValueStd("valY", AliRsnValueStd::kPairY);
+   AliRsnCutValue *cutRapidity = new AliRsnCutValue("cutY", -0.5, 0.5, kFALSE);
+   valRapidity->SetSupportObject(support);
+   cutRapidity->SetValueObj(valRapidity);
+   
+   // cut set
+   AliRsnCutSet *pairCuts = new AliRsnCutSet("pairCuts", AliRsnTarget::kMother);
+   pairCuts->AddCut(cutRapidity);
+   pairCuts->SetCutScheme(cutRapidity->GetName());
+}
+
+void AddPairOutput(AliRsnLoopPair *pair)
+{
+   // axes
+   AliRsnValueStd *axisIM = new AliRsnValueStd("IM", AliRsnValueStd::kPairInvMass, 0.9, 1.4, 0.001);
+   AliRsnValueStd *axisPt = new AliRsnValueStd("PT", AliRsnValueStd::kPairPt     , 0.0, 5.0, 0.1  );
+     
+   // output: 2D histogram of inv. mass vs. pt
+   AliRsnListOutput *outPair = new AliRsnListOutput("pair", AliRsnListOutput::kHistoDefault);
+   outPair->AddValue(axisIM);
+   outPair->AddValue(axisPt);
+   
+   // add outputs to loop
+   pair->AddOutput(outPair);
+}
+
+void AddMonitorOutput(AliRsnLoopDaughter *mon)
+{
+   // axes
+   AliRsnValueStd *axisMomTPC = new AliRsnValueStd("pTPC", AliRsnValueStd::kTrackPtpc     , 0.0,   5.0, 0.01 );
+   AliRsnValueStd *axisSigTPC = new AliRsnValueStd("sTPC", AliRsnValueStd::kTrackTPCsignal, 0.0, 500.0, 2.0  );
+   
+   // output: 2D histogram of TPC signal vs. TPC momentum
+   AliRsnListOutput *outMonitor = new AliRsnListOutput("mon", AliRsnListOutput::kHistoDefault);
+   outMonitor->AddValue(axisMomTPC);
+   outMonitor->AddValue(axisSigTPC);
+   
+   // add outputs to loop
+   mon->AddOutput(outMonitor);
+}
+
+void AddPairLoop(AliRsnAnalysisTask *task, Bool_t isMC, Int_t listID1, Int_t listID2, const char *suffix = "")
+{
+   // pair definition
+   AliRsnPairDef  *pairDef    = new AliRsnPairDef(AliRsnDaughter::kKaon, '+', AliRsnDaughter::kKaon, '-', 333, 1.019455);
+   
+   // loop object creation
+   AliRsnLoopPair *loopPhi    = new AliRsnLoopPair(Form("%s_unlike", suffix), pairDef, kFALSE);
+   AliRsnLoopPair *loopPhiMix = new AliRsnLoopPair(Form("%s_unlike", suffix), pairDef, kTRUE );
+   
+   // assign ID of selector lists to be used (KK --> the same)
+   loopPhi->SetListID(0, listID1);
+   loopPhi->SetListID(1, listID2);
+   loopPhiMix->SetListID(0, listID1);
+   loopPhiMix->SetListID(1, listID2);
+   
+   // assign cuts for events
+   AliRsnCutSet *eventCuts = EventCuts();
+   loopPhi->SetEventCuts(eventCuts);
+   loopPhiMix->SetEventCuts(eventCuts);
+   
+   // assign cuts for pairs
+   AliRsnCutSet *pairCuts = PairCuts(pairDef);
+   loopPhi->SetPairCuts(eventCuts);
+   loopPhiMix->SetPairCuts(eventCuts);
+   
+   // add outputs
+   AddPairOutput(loopPhi);
+   AddPairOutput(loopPhiMix);
+   
+   // add loops to task
+   task->Add(loopPhi);
+   task->Add(loopPhiMix);
+}
+
+void AddMonitorLoop(AliRsnAnalysisTask *task, Bool_t isMC, Int_t listID1, Int_t listID2, const char *suffix = "")
+{
+   // monitor definition
+   AliRsnDaughterDef *tracks = new AliRsnDaughterDef(AliRsnDaughter::kTrack /*'+' or '-'*/);
+   
+   // loop object
+   AliRsnLoopDaughter *loopMon1 = new AliRsnLoopDaughter(Form("%s_mon1", suffix), listID1, tracks);
+   AliRsnLoopDaughter *loopMon2 = new AliRsnLoopDaughter(Form("%s_mon2", suffix), listID2, tracks);
+   
+   // add cuts on events
+   AliRsnCutSet *eventCuts = EventCuts();
+   loopMon1->SetEventCuts(eventCuts);
+   loopMon2->SetEventCuts(eventCuts);
+   
+   // add monitors
+   AddMonitorOutput(loopMon1);
+   AddMonitorOutput(loopMon2);
+   
+   // add loop to task
+   task->Add(loopMon1);
+   task->Add(loopMon2);
+}
diff --git a/PWG2/RESONANCES/macros/train/Tender.C b/PWG2/RESONANCES/macros/train/Tender.C
new file mode 100644 (file)
index 0000000..07cdd96
--- /dev/null
@@ -0,0 +1,117 @@
+typedef enum AliESDpid::EStartTimeType_t TOFtimeType;
+
+TString     rsnTenderStorage         ("alien://folder=/alice/data/2010/OCDB");
+TString     rsnTenderOptions         ("VZERO+TPC+TOF");
+TOFtimeType rsnTenderTOFtime         = AliESDpid::kTOF_T0;
+Double_t    rsnTenderTOFres          = 80.0; 
+Bool_t      rsnTenderTOFcorrExpTimes = kFALSE;
+Bool_t      rsnTenderTOFapplyT0      = kFALSE;
+
+//__________________________________________________________________________________________________
+//
+// Special function to add tender when no multi handler is used
+//
+void AddTender()
+{
+   Info("Setup", "Adding tender directly to manager");
+   
+   AliTender *tender = new AliTender("AnalysisTender");
+   tender->SetCheckEventSelection(rsnTenderOptions.Contains("SEL"));
+   tender->SetDefaultCDBStorage(rsnTenderStorage.Data());
+   AddTenderSupplies(tender);
+   
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   mgr->AddTask(tender);
+}
+
+//__________________________________________________________________________________________________
+//
+// Special function to add tender handler when multi handler is used
+//
+void AddTenderHandler(AliMultiInputEventHandler *multiInputHandler)
+{
+   Info("Setup", "Adding tender handler");
+   if (!multiInputHandler) return;
+   
+   // works only with ESDs
+   AliESDInputHandler*esdIH = dynamic_cast<AliESDInputHandler*>(multiInputHandler->GetFirstInputEventHandler());
+   if (!esdIH) {
+      Error("Setup", "No ESD handler found");
+      return;
+   }   
+   
+   // add tender handler and configure tender inside
+   AliTenderInputEventHandler *tenderIH = new AliTenderInputEventHandler();
+   AliTender *tender = tenderIH->GetTender();
+   AddTenderSupplies(tender);
+   
+   // add handler to event handler
+   multiInputHandler->AddInputEventHandler(tenderIH);
+}
+
+//__________________________________________________________________________________________________
+//
+// Special function to add tender supplies
+//
+void AddTenderSupplies(AliTender *tender)
+{
+   if (!tender) return;
+   
+   Bool_t useV0  = rsnTenderOptions.Contains("V0");
+   Bool_t useTPC = rsnTenderOptions.Contains("TPC");
+   Bool_t useTOF = rsnTenderOptions.Contains("TOF");
+   Bool_t useTRD = rsnTenderOptions.Contains("TRD");
+   Bool_t usePID = rsnTenderOptions.Contains("PID");
+   Bool_t useVTX = rsnTenderOptions.Contains("PrimVtx");
+   Bool_t evSel  = rsnTenderOptions.Contains("SEL");
+   
+   tender->SetCheckEventSelection(evSel);
+   tender->SetDefaultCDBStorage("raw://");
+
+   // VZERO
+   if (useV0) {
+      Info("Setup", "Adding tender supply for VZERO");
+      AliVZEROTenderSupply *vzeroSupply = new AliVZEROTenderSupply("VZEROtender");
+      vzeroSupply->SetDebug(kFALSE);
+      tender->AddSupply(vzeroSupply);
+   }
+   
+   // TPC
+   if (useTPC) {
+      Info("Setup", "Adding tender supply for TPC");
+      AliTPCTenderSupply *tpcSupply = new AliTPCTenderSupply("TPCtender");
+      tpcSupply->SetDebugLevel(2);
+      //tpcSupply->SetMip(50.);
+      tender->AddSupply(tpcSupply);
+   }
+   
+   // TOF
+   if (useTOF) {
+      Info("Setup", "Adding tender supply for TOF");
+      AliTOFTenderSupply *tofTender = new AliTOFTenderSupply("TOFtender");
+      tofTender->SetTimeZeroType(rsnTenderTOFtime);
+      tofTender->SetTOFres(rsnTenderTOFres);
+      tofTender->SetApplyT0(rsnTenderTOFapplyT0);
+      tofTender->SetCorrectExpTimes(rsnTenderTOFcorrExpTimes);
+      tender->AddSupply(tofTender);
+   }
+   
+   // TRD
+   if (useTRD) {
+      Info("Setup", "Adding tender supply for TRD");
+      AliTRDTenderSupply *trdSupply = new AliTRDTenderSupply("TRDtender");
+      tender->AddSupply(trdSupply);
+   }
+   
+   // PID
+   if (usePID) {
+      Info("Setup", "Adding tender supply for PID");
+      tender->AddSupply(new AliPIDTenderSupply("PIDtender"));
+   }
+   
+   // Primary Vertex
+   if (useVTX) {
+      Info("Setup", "Adding tender supply for Primary Vertex");
+      tender->AddSupply(new AliVtxTenderSupply("PriVtxtender"));
+   }
+}
diff --git a/PWG2/RESONANCES/macros/train/runLocal.C b/PWG2/RESONANCES/macros/train/runLocal.C
new file mode 100644 (file)
index 0000000..efdb150
--- /dev/null
@@ -0,0 +1,221 @@
+//
+// This is an example steering macro for running RSN analysis task
+// locally with a collection of files specified in a text file:
+//
+// Inputs:
+//   - nReadFiles  = number of files to process from the list
+//   - nSkipFiles  = how many lines to be skipped when reading the list
+//   - addTaskName = name of the macro to add the RSN analysis task
+//                   (assumed to have inside it a function named like the file)
+//   - inputSource = name of the file containing all the inputs
+//                   ---> to run on a local collection, the collection file
+//                        must contain on each line the full path
+//                        of one input file and it must have the ".txt" extension
+//                   ---> to run on an AliEn collection, the collection file must be an XML
+//                        file collection like those built from the "find -x" method in aliensh.
+//   - options     = a label which is used to know what kind of data are being read
+//                   (it is propagated to the 'addTask' macro for eventual setting up of something
+//   - outName     = name for the file with RSN package outputs (without ROOT extension)
+//
+// Notes:
+//   - in case the source is an ESD, and if inputs are a MC production
+//     the MC input handler is created by default
+//
+//
+// In principle, the user should never modify this macro.
+//
+void runLocal
+(
+   Int_t       nReadFiles      = 0,
+   Int_t       nSkipFiles      = 0,
+   Int_t       nmix            = 0,
+   const char *inputSource     = "pbpb_data.txt",
+   const char *runOptions      = "esd_data_phys_cent",
+   const char *analysisOptions = "tpcpid_tofpid_mult",
+   const char *outName         = "test.root",
+   const char *taskList        = "AddRsnAnalysisTask.C",
+   //const char *taskPath        = "$(ALICE_ROOT)/PWG2/RESONANCES/macros/train"
+   const char *taskPath        = "$(HOME)/code/resonances/alice-rsn-package/PWG2resonances/RESONANCES/macros/test/pulvir"
+)
+{
+   //
+   // === PREPARATION ==============================================================================
+   //
+   
+   // this option is not needed when using plugin
+   // gEnv->SetValue("XSec.GSI.DelegProxy","2");
+   
+   // stopwatch
+   TStopwatch timer;
+   timer.Start();
+   
+   // some options
+   TString opt(runOptions);
+   opt.ToUpper();
+   Bool_t useTender = opt.Contains("TENDER");
+   Bool_t isMC      = opt.Contains("MC") || (!opt.Contains("DATA"));
+   Bool_t isESD     = opt.Contains("ESD");
+   ::Info("runPlugin.C", "useTender = %d", useTender);
+   ::Info("runPlugin.C", "isMC      = %d", isMC     );
+   ::Info("runPlugin.C", "runOpts   = %s", runOptions);
+   ::Info("runPlugin.C", "anaOpts   = %s", analysisOptions);
+   
+   // basic configurations
+   gROOT->LoadMacro(Form("%s/AnalysisSetup.C", taskPath));
+   AnalysisSetup(isMC, nmix, runOptions, outName, taskPath);
+   
+   // define tree name
+   Char_t treeName[200];
+   if (isESD) sprintf(treeName, "esdTree"); else sprintf(treeName, "aodTree");
+   
+   //
+   // === BUILD INPUT LIST =========================================================================
+   //
+
+   // check extension of input to distinguish between XML and TXT
+   TString sInput(inputSource);
+   sInput.ToLower();
+   Bool_t isTXT = (!strcmp(sInput(sInput.Length() - 3, 3).Data(), "txt"));
+   cout << "Input = " << (isTXT ? "TXT" : "XML") << endl;
+
+   // if input is XML, connect to AliEn
+   if (!isTXT) TGrid::Connect("alien://");
+
+   // create TChain of input events
+   TChain *analysisChain = 0x0;
+   if (isTXT) analysisChain = CreateChainFromText(inputSource, treeName, nReadFiles, nSkipFiles);
+   else       analysisChain = CreateChainFromXML (inputSource, treeName, nReadFiles, nSkipFiles);
+   if (!analysisChain) {
+      Error("runLocal", "Analysis chain not properly initialized");
+      return;
+   }
+   
+   //
+   // === CONFIGURATION ============================================================================
+   //
+
+   //AliLog::SetGlobalDebugLevel(AliLog::kDebug + 3);
+   //AliLog::SetClassDebugLevel("AliRsnCutESD2010", AliLog::kDebug+3);
+   //AliLog::SetClassDebugLevel("AliRsnCutValue", AliLog::kDebug+3);
+   //AliLog::SetClassDebugLevel("AliRsnCutESDCutMultiplicity", AliLog::kDebug+3);
+   //AliLog::SetClassDebugLevel("AliRsnValue", AliLog::kDebug+3);
+   //AliLog::SetClassDebugLevel("AliRsnCutTrackQuality", AliLog::kDebug+3);
+   //AliLog::SetGlobalDebugLevel(AliLog::kDebug+3);
+   
+   //
+   // === ANALYSIS TASK CREATION AND INCLUSION =====================================================
+   //
+   
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   if (!mgr) return;
+   
+   gROOT->LoadMacro(Form("%s/AddRsnAnalysisTask.C", taskPath));
+   AddRsnAnalysisTask(isMC, (nmix > 0), runOptions, analysisOptions);
+
+   // initialize and start analysis
+   if (!mgr->InitAnalysis()) {
+      ::Error("runPlugin.C", "Failed to init analysis");
+      return;
+   }
+   mgr->PrintStatus();
+   if (isTXT) mgr->StartAnalysis("local", analysisChain);
+   else       mgr->StartAnalysis("alien", analysisChain);
+   
+   // final operation
+   // gObjectTable->Print();
+   timer.Stop();
+   timer.Print();
+}
+
+//_________________________________________________________________________________________________
+TChain* CreateChainFromXML
+(const char *xmlFileName, const char *treeName, Int_t nread, Int_t nskip)
+{
+//
+// Create a TChain with all required files listed into an XML collection.
+// Necessary to run analysis in AliEn jobs.
+// ---
+// Arguments:
+//  - xmlFileName = input list
+//  - treeName    = "esdTree" or "aodTree"
+//  - nread       = how many files to read (0 = all)
+//  - nskip       = how many files to skip from beginning
+//
+
+   // if nread argument is 0, it is disabled
+   if (nread == 0) nread = 1000000000;
+
+   // initialize output object
+   TChain *chain = new TChain(treeName);
+
+   // initialize the AliEn collection
+   TAlienCollection *myCollection = TAlienCollection::Open(xmlFileName);
+   if (!myCollection) {
+      Error("CreateChainFromXML", "Cannot create an AliEn collection from %s", xmlFileName);
+      return 0x0;
+   }
+
+   // loop on collection
+   myCollection->Reset();
+   while (myCollection->Next()) {
+      // skip until reached required number of offset
+      if (nskip > 0) {--nskip; continue;}
+
+      // stop if required number of read files is reached
+      // otherwise update the counter
+      if (nread <= 0) break;
+      nread--;
+
+      // recovery file and add it
+      Info("CreateChainFromXML", Form("Adding: %s", myCollection->GetTURL("")));
+      chain->Add(myCollection->GetTURL(""));
+   }
+
+   return chain;
+}
+
+//_________________________________________________________________________________________________
+TChain* CreateChainFromText(const char *fileName, const char *treeName, Int_t nread, Int_t nskip)
+{
+//
+// Create a TChain with all required files listed into a text file.
+// Necessary to run analysis in local jobs.
+// ---
+// Arguments:
+//  - xmlFileName = input file list
+//  - treeName    = "esdTree" or "aodTree"
+//  - nread       = how many files to read (0 = all)
+//  - nskip       = how many files to skip from beginning
+//
+
+   // if third argument is 0, it is interpreted
+   // as "read all lines"
+   Bool_t readAll = (nread <= 0);
+
+   // initialize output object
+   TChain* target = new TChain(treeName);
+
+   // open text file
+   ifstream fileIn(fileName);
+
+   // loop on collection
+   TString line;
+   while (fileIn.good()) {
+      fileIn >> line;
+      if (line.IsNull()) continue;
+
+      // skip until reached required number of offset
+      if (nskip > 0) {--nskip; continue;}
+
+      // stop if required number of read files is reached
+      // otherwise update the counter
+      if (!readAll && nread <= 0) break;
+      nread--;
+
+      // add file
+      Info("CreateChainFromText", "Adding '%s'", line.Data());
+      target->Add(line.Data());
+   }
+
+   return target;
+}
diff --git a/PWG2/RESONANCES/macros/train/runPluginProof.C b/PWG2/RESONANCES/macros/train/runPluginProof.C
new file mode 100644 (file)
index 0000000..d0c7c5b
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// This is an example steering macro for running RSN analysis task
+// with the AliEn plugin on PROOF.
+//
+// Inputs:
+//
+//   - runMode     = AliEn plugin run mode
+//   - suffix      = eventual suffix which is attached to the automatic name created for outputs
+//   - partname    = a string which defines the resonance name (used for output)
+//   - runList     = configuration file whith gives list of runs, pattern, prefix, options and AliEn path
+//   - split       = corresponding JDL value
+//   - nmerge      = number of outputs to be merged per stage
+//
+//   - taskList    = a string containin all the 'add-task' macros to be used
+//   - taskPath    = the uniqu pathe where all 'add-task' macros (and all their needs) are stored
+//
+//   - workDirBase = path of the working directory (starting from AliEn home)
+//   - outDir      = path of the output directory (w.r. to workDir)
+//
+// Notes:
+//
+//   - in case the source is an ESD, and if inputs are a MC production
+//     the MC input handler is created by default
+//
+//
+// In principle, the user should never modify this macro.
+//
+void runPluginProof
+(
+   const char *runMode         = "full",
+   Int_t       nmix            = 0,
+   const char *dataSet         = "/alice/data/LHC10h_000137162#esdTree",
+   const char *clusterName     = "alice-caf.cern.ch",
+   const char *testFile        = "pbpb_data.txt",
+   const char *runOptions      = "esd_data_phys_cent",
+   const char *analysisOptions = "tpcpid_tofpid",
+   const char *outName         = "test_proof.root",
+   const char *taskList        = "AddRsnAnalysisTask.C",
+   //const char *taskPath        = "$(ALICE_ROOT)/PWG2/RESONANCES/macros/train"
+   const char *taskPath        = "$(HOME)/code/resonances/alice-rsn-package/PWG2resonances/RESONANCES/macros/test/pulvir"
+)
+{
+   //
+   // === PREPARATION ==============================================================================
+   //
+   
+   // this option is not needed when using plugin
+   // gEnv->SetValue("XSec.GSI.DelegProxy","2");
+   
+   // some options
+   TString opt(runOptions);
+   opt.ToUpper();
+   Bool_t useTender = opt.Contains("TENDER");
+   Bool_t isMC      = opt.Contains("MC") || (!opt.Contains("DATA"));
+   ::Info("runPlugin.C", "useTender = %d", useTender);
+   ::Info("runPlugin.C", "isMC      = %d", isMC     );
+   ::Info("runPlugin.C", "runOpts   = %s", runOptions);
+   ::Info("runPlugin.C", "anaOpts   = %s", analysisOptions);
+   
+   // basic configurations
+   gROOT->LoadMacro(Form("%s/AnalysisSetup.C", taskPath));
+   AnalysisSetup(isMC, nmix, runOptions, outName, taskPath);
+
+   //
+   // === PLUGIN CONFIGURATION =====================================================================
+   //
+
+   // load and execute plugin configuration macro
+   // pass to the macro, as FIRST argument, the common name
+   // which is used for the output, since it must be equal
+   // to the one defined here for the common output (for merging)
+   gROOT->LoadMacro("PluginByRunProof.C");
+
+   // build the list of arguments (for them see the 'PluginByRun.C' code)
+   TString args("PluginByRunProof(");
+   args += Form("\"%s\", ", dataSet);
+   args += Form("\"%s\", ", testFile);
+   args += Form("\"%s\") ", clusterName);
+
+   // create the plugin
+   AliAnalysisAlien *plugin = (AliAnalysisAlien*)gROOT->ProcessLine(args.Data());
+
+   // set run mode
+   plugin->SetRunMode(runMode);
+   
+   // add to manager
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   if (!mgr) return;
+   mgr->SetGridHandler(plugin);
+   
+   //
+   // === ANALYSIS EXECUTION =======================================================================
+   //
+
+   gROOT->LoadMacro(Form("%s/AddRsnAnalysisTask.C", taskPath));
+   AddRsnAnalysisTask(isMC, kFALSE, runOptions, analysisOptions);
+   
+   // initialize and start analysis
+   if (!mgr->InitAnalysis()) {
+      ::Error("runPlugin.C", "Failed to init analysis");
+      return;
+   }
+   mgr->PrintStatus();
+   mgr->StartAnalysis("proof");
+}