]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
New class for selecting clean V0s with kinematic cuts
authormorsch <morsch@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 16 Mar 2011 17:26:56 +0000 (17:26 +0000)
committermorsch <morsch@f7af4fe6-9843-0410-8265-dc069ae4e863>
Wed, 16 Mar 2011 17:26:56 +0000 (17:26 +0000)
Matus Kalisky

ANALYSIS/ANALYSISaliceLinkDef.h
ANALYSIS/AliESDv0KineCuts.cxx [new file with mode: 0644]
ANALYSIS/AliESDv0KineCuts.h [new file with mode: 0644]
ANALYSIS/CMakelibANALYSISalice.pkg

index 59a6965b4132db8bdce77a9d387dbdc0d5fa6613..008ed1851ee28ab03dfae445aeb0300929bf7353 100644 (file)
@@ -13,6 +13,7 @@
 #pragma link C++ class  AliESDtrackCuts+;
 #pragma link C++ class  AliESDpidCuts+;
 #pragma link C++ class  AliESDv0Cuts+;
+#pragma link C++ class  AliESDv0KineCuts+;
 
 #pragma link C++ class  AliEventPoolOTF+;
 #pragma link C++ class  AliEventPoolLoop+;
diff --git a/ANALYSIS/AliESDv0KineCuts.cxx b/ANALYSIS/AliESDv0KineCuts.cxx
new file mode 100644 (file)
index 0000000..75fb10a
--- /dev/null
@@ -0,0 +1,1034 @@
+/**************************************************************************\r
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *\r
+ *                                                                        *\r
+ * Author: The ALICE Off-line Project.                                    *\r
+ * Contributors are mentioned in the code where appropriate.              *\r
+ *                                                                        *\r
+ * Permission to use, copy, modify and distribute this software and its   *\r
+ * documentation strictly for non-commercial purposes is hereby granted   *\r
+ * without fee, provided that the above copyright notice appears in all   *\r
+ * copies and that both the copyright notice and this permission notice   *\r
+ * appear in the supporting documentation. The authors make no claims     *\r
+ * about the suitability of this software for any purpose. It is          *\r
+ * provided "as is" without express or implied warranty.                  *\r
+ **************************************************************************/\r
+\r
+/*\r
+ * author: M.Kalisky@gsi.de\r
+ * 08/Dec/2010\r
+ *\r
+ * Description: This class allows with purely kinematical cuts\r
+ * to select clean samples of electrons, pions and protons from the\r
+ * V0 online finder ESD V0 candidates for PID and dectector resonse\r
+ * studies.\r
+ */\r
+\r
+#include <TVector3.h>\r
+#include <TDatabasePDG.h>\r
+\r
+#include "AliESDv0.h"\r
+#include "AliESDtrack.h"\r
+#include "AliESDEvent.h"\r
+#include "AliVEvent.h"\r
+#include "AliLog.h"\r
+#include "AliKFParticle.h"\r
+#include "AliVTrack.h"\r
+#include "AliKFVertex.h"\r
+\r
+#include "AliESDv0KineCuts.h"\r
+\r
+ClassImp(AliESDv0KineCuts)\r
+\r
+//____________________________________________________________________\r
+AliESDv0KineCuts::AliESDv0KineCuts() :\r
+  fEvent(0x0)\r
+  , fPrimaryVertex(0x0)\r
+  , fType(0)\r
+  , fMode(0)\r
+  , fTPCNcls(1)\r
+  , fTPCrefit(kTRUE)\r
+  , fTPCchi2perCls(4.0)\r
+  , fTPCclsRatio(0.6)\r
+  , fNoKinks(kTRUE)\r
+  , fGcutChi2NDF(10)\r
+  , fGcutInvMass(0.05)\r
+  , fK0cutChi2NDF(10)\r
+  , fLcutChi2NDF(10)\r
+{\r
+  //\r
+  // Default constructor\r
+  //\r
+\r
+  // default single track cuts\r
+  fTPCNcls = 1;                // minimal number of the TPC clusters\r
+  fTPCrefit = kTRUE;           // TPC refit\r
+  fTPCchi2perCls = 4.0;        // chi2 per TPC cluster\r
+  fTPCclsRatio = 0.6;          // minimal foun/findable TPC cluster ratio\r
+  fNoKinks = kTRUE;            // kinks - no [kTRUE] or do not care [kFalse]\r
+\r
+\r
+  // default gamma cuts values\r
+  fGcutChi2NDF = 10;           // Chi2NF cut value for the AliKFparticle gamma\r
+  fGcutCosPoint[0] = 0;        // cos of the pointing angle [min, max]\r
+  fGcutCosPoint[1] = 0.02;     // cos of the pointing angle [min, max]\r
+  fGcutDCA[0] = 0.;            // DCA between the daughter tracks [min, max]\r
+  fGcutDCA[1] = 0.25;          // DCA between the daughter tracks [min, max]\r
+  fGcutVertexR[0] = 3.;        // radius of the conversion point [min, max]\r
+  fGcutVertexR[1] = 90.;       // radius of the conversion point [min, max]\r
+  fGcutPsiPair[0] = 0.;        // value of the psi pair cut [min, max]\r
+  fGcutPsiPair[1] = 0.05;      // value of the psi pair cut [min, max]\r
+  fGcutInvMass = 0.05;         // upper value on the gamma invariant mass\r
+  // default K0 cuts\r
+  fK0cutChi2NDF = 10;          // Chi2NF cut value for the AliKFparticle K0\r
+  fK0cutCosPoint[0] = 0.;      // cos of the pointing angle [min, max]\r
+  fK0cutCosPoint[1] = 0.02;    // cos of the pointing angle [min, max]\r
+  fK0cutDCA[0] = 0.;           // DCA between the daughter tracks [min, max]\r
+  fK0cutDCA[1] = 0.2;          // DCA between the daughter tracks [min, max]\r
+  fK0cutVertexR[0] = 2.0;      // radius of the decay point [min, max]\r
+  fK0cutVertexR[1] = 30.0;     // radius of the decay point [min, max]\r
+  fK0cutInvMass[0] = 0.486;    // invariant mass window\r
+  fK0cutInvMass[1] = 0.508;    // invariant mass window\r
+  // Lambda & anti-Lambda cut values\r
+  fLcutChi2NDF = 10;           // Chi2NF cut value for the AliKFparticle K0\r
+  fLcutCosPoint[0] = 0.;       // cos of the pointing angle [min, max]\r
+  fLcutCosPoint[1] = 0.02;     // cos of the pointing angle [min, max]\r
+  fLcutDCA[0] = 0.;            // DCA between the daughter tracks [min, max]\r
+  fLcutDCA[1] = 0.2;           // DCA between the daughter tracks [min, max]\r
+  fLcutVertexR[0] = 2.0;       // radius of the decay point [min, max]\r
+  fLcutVertexR[1] = 40.0;      // radius of the decay point [min, max]\r
+  fLcutInvMass[0] = 1.11;      // invariant mass window\r
+  fLcutInvMass[1] = 1.12;      // invariant mass window\r
+    \r
+}\r
+//____________________________________________________________________\r
+AliESDv0KineCuts::~AliESDv0KineCuts(){\r
+  //\r
+  // Destructor\r
+  //\r
+\r
+\r
+}\r
+//____________________________________________________________________\r
+AliESDv0KineCuts::AliESDv0KineCuts(const AliESDv0KineCuts &ref):\r
+  TObject(ref)\r
+  , fEvent(0x0)\r
+  , fPrimaryVertex(0x0)\r
+  , fType(0)\r
+  , fMode(0)\r
+  , fTPCNcls(1)\r
+  , fTPCrefit(kTRUE)\r
+  , fTPCchi2perCls(4.0)\r
+  , fTPCclsRatio(0.6)\r
+  , fNoKinks(kTRUE)\r
+  , fGcutChi2NDF(10)\r
+  , fGcutInvMass(0.05)\r
+  , fK0cutChi2NDF(10)\r
+  , fLcutChi2NDF(10)\r
+{\r
+  //\r
+  // Copy operator\r
+  //\r
+\r
+  ref.Copy(*this);\r
+}\r
+//____________________________________________________________________\r
+AliESDv0KineCuts &AliESDv0KineCuts::operator=(const AliESDv0KineCuts &ref){\r
+  //\r
+  // assignment operator\r
+  //\r
+  if(this != &ref)\r
+    ref.Copy(*this);\r
+  return *this; \r
+}\r
+//____________________________________________________________________\r
+void AliESDv0KineCuts::Copy(TObject &ref) const {\r
+  //\r
+  // Performs the copying of the object\r
+  //\r
+\r
+  TObject::Copy(ref);\r
+\r
+  AliESDv0KineCuts &target = dynamic_cast<AliESDv0KineCuts &>(ref);\r
+\r
+  // default single track cuts\r
+  target.fTPCNcls = fTPCNcls;\r
+  target.fTPCrefit = fTPCrefit;\r
+  target.fTPCchi2perCls = fTPCchi2perCls;\r
+  target.fTPCclsRatio = fTPCclsRatio;\r
+  target.fNoKinks = fNoKinks;\r
+\r
+\r
+  // default gamma cuts values\r
+  target.fGcutChi2NDF = fGcutChi2NDF;\r
+  memcpy(target.fGcutCosPoint, fGcutCosPoint, sizeof(Float_t) * 2);\r
+  memcpy(target.fGcutDCA, fGcutDCA, sizeof(Float_t) * 2); \r
+  memcpy(target.fGcutVertexR, fGcutVertexR, sizeof(Float_t) * 2);\r
+  memcpy(target.fGcutPsiPair, fGcutPsiPair, sizeof(Float_t) * 2);\r
+  target.fGcutInvMass = fGcutInvMass;\r
+  // default K0 cuts\r
+  target.fK0cutChi2NDF = fK0cutChi2NDF;\r
+  memcpy(target.fK0cutCosPoint, fK0cutCosPoint, sizeof(Float_t) * 2);\r
+  memcpy(target.fK0cutDCA, fK0cutDCA, sizeof(Float_t) * 2);\r
+  memcpy(target.fK0cutVertexR, fK0cutVertexR, sizeof(Float_t) * 2);\r
+  memcpy(target.fK0cutInvMass, fK0cutInvMass, sizeof(Float_t) * 2);\r
+  // Lambda & anti-Lambda cut values\r
+  target.fLcutChi2NDF = fLcutChi2NDF;\r
+  memcpy(target.fLcutCosPoint, fLcutCosPoint, sizeof(Float_t) * 2);\r
+  memcpy(target.fLcutDCA, fLcutDCA, sizeof(Float_t) * 2);\r
+  memcpy(target.fLcutVertexR, fLcutVertexR, sizeof(Float_t) * 2);\r
+  memcpy(target.fLcutInvMass, fLcutInvMass, sizeof(Float_t) * 2);\r
+  \r
+}\r
+//____________________________________________________________________\r
+Bool_t const AliESDv0KineCuts::ProcessV0(AliESDv0* const v0, Int_t &pdgV0, Int_t &pdgP, Int_t &pdgN){\r
+  //\r
+  // main user function\r
+  //\r
+\r
+  if(!v0) return kFALSE;\r
+  if(!fEvent){\r
+    AliErrorClass("No valid Event pointer available, provide it first");\r
+    return kFALSE;\r
+  }\r
+\r
+  if(!V0CutsCommon(v0)) return kFALSE;\r
+\r
+  const Int_t id = PreselectV0(v0);\r
+\r
+  if(!SingleTrackCuts(v0)) return kFALSE;\r
+\r
+  switch(id){\r
+  case kUndef:\r
+    return kFALSE;\r
+  case kGamma:\r
+    return CaseGamma(v0, pdgV0, pdgP, pdgN);\r
+  case kK0:\r
+    return CaseK0(v0, pdgV0, pdgP, pdgN);\r
+  case kLambda:\r
+    return CaseLambda(v0, pdgV0, pdgP, pdgN, 0);\r
+  case kALambda:\r
+    return CaseLambda(v0, pdgV0, pdgP, pdgN, 1);\r
+  default:\r
+    return kFALSE; \r
+  }\r
+\r
+  return kFALSE;\r
+}\r
+//____________________________________________________________________\r
+Bool_t const AliESDv0KineCuts::ProcessV0(AliESDv0* const v0, Int_t &pdgP, Int_t &pdgN){\r
+  //\r
+  // main user function, simplified if the V0 identity is not necessary\r
+  //\r
+\r
+  if(!v0) return kFALSE;\r
+  if(!fEvent){\r
+    AliErrorClass("No valid Event pointer available, provide it first");\r
+    return kFALSE;\r
+  }\r
+\r
+  Int_t idV0 = -1;\r
+  return ProcessV0(v0, idV0, pdgP, pdgN);\r
+\r
+}\r
+//____________________________________________________________________\r
+Int_t  const AliESDv0KineCuts::PreselectV0(AliESDv0* const v0){\r
+  //\r
+  // Make a preselection (exclusive) of the V0 cadidates based on\r
+  // Armenteros plot\r
+  // the armenteros cut values are currently fixed and user is not able to set them via\r
+  // set funcions. The reason is that these cuts are optimized and furneter changes should \r
+  // not be necessary. To prove otherwise please study in detail before changing the values\r
+  //\r
\r
+  Float_t ap[2] = {-1., -1.};\r
+  Armenteros(v0, ap);\r
+  // for clarity\r
+  const Float_t alpha = ap[0];\r
+  const Float_t qt = ap[1];\r
+\r
+  // selection cuts \r
+  // - the reagions for different candidates must not overlap \r
+\r
+  // Gamma cuts\r
+  const Double_t cutAlphaG = 0.35; \r
+  const Double_t cutQTG = 0.05;\r
+  const Double_t cutAlphaG2[2] = {0.6, 0.8};\r
+  const Double_t cutQTG2 = 0.04;\r
+\r
+  // K0 cuts\r
+  const Float_t cutQTK0[2] = {0.1075, 0.215};\r
+  const Float_t cutAPK0[2] = {0.199, 0.8};   // parameters for curved QT cut\r
+  \r
+  // Lambda & A-Lambda cuts\r
+  const Float_t cutQTL = 0.03;\r
+  const Float_t cutAlphaL[2] = {0.35, 0.7};\r
+  const Float_t cutAlphaAL[2] = {-0.7,  -0.35};\r
+  const Float_t cutAPL[3] = {0.107, -0.69, 0.5};  // parameters fir curved QT cut\r
+\r
+\r
+  if(kPurity == fMode){\r
+  // Check for Gamma candidates\r
+    if(qt < cutQTG){\r
+      if( (TMath::Abs(alpha) < cutAlphaG) ) return kGamma;\r
+    }\r
+    // additional region - should help high pT gammas\r
+    if(qt < cutQTG2){\r
+      if( (TMath::Abs(alpha) > cutAlphaG2[0]) &&  (TMath::Abs(alpha) < cutAlphaG2[1]) ) return kGamma;\r
+    }\r
+  }\r
+  if(kEffGamma == fMode){\r
+    if(qt < cutQTG) return kGamma;\r
+  }\r
+\r
+  \r
+  // Check for K0 candidates\r
+  Float_t q = cutAPK0[0] * TMath::Sqrt(TMath::Abs(1 - alpha*alpha/(cutAPK0[1]*cutAPK0[1])));\r
+  if( (qt > cutQTK0[0]) && (qt < cutQTK0[1]) && (qt > q) ){\r
+    return kK0;\r
+  }\r
+\r
+  // Check for Lambda candidates\r
+  q = cutAPL[0] * TMath::Sqrt(TMath::Abs(1 - ( (alpha + cutAPL[1]) * (alpha + cutAPL[1]) ) / (cutAPL[2]*cutAPL[2]) ));\r
+  if( (alpha > cutAlphaL[0]) && (alpha < cutAlphaL[1]) && (qt > cutQTL) && (qt < q)  ){\r
+    return kLambda;\r
+  }\r
+\r
+  // Check for A-Lambda candidates\r
+  q = cutAPL[0] * TMath::Sqrt(TMath::Abs(1 - ( (alpha - cutAPL[1]) * (alpha - cutAPL[1]) ) / (cutAPL[2]*cutAPL[2]) ));\r
+  if( (alpha > cutAlphaAL[0]) && (alpha < cutAlphaAL[1]) && (qt > cutQTL) && (qt < q)  ){\r
+    return kALambda;\r
+  }\r
+  \r
+  return kUndef;\r
+}\r
+//____________________________________________________________________\r
+Bool_t const AliESDv0KineCuts::SingleTrackCuts(AliESDv0 * const v0){\r
+  //\r
+  // apply single track cuts\r
+  // correct sign not relevat here\r
+  //\r
+\r
+  if(!v0) return kFALSE;\r
+  \r
+  Int_t pIndex = 0, nIndex = 0;\r
+  pIndex = v0->GetPindex();\r
+  nIndex = v0->GetNindex();\r
+  AliESDtrack* d[2];\r
+  d[0] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(pIndex));\r
+  d[1] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(nIndex));\r
+  \r
+  for(Int_t i=0; i<2; ++i){\r
+    if(!d[i]) return kFALSE;\r
+    \r
+    // status word\r
+    ULong_t status = d[i]->GetStatus();\r
+\r
+    // No. of TPC clusters leave to the users\r
+    if(d[i]->GetTPCNcls() < 1) return kFALSE;\r
+\r
+    // TPC refit\r
+    if(!(status & AliESDtrack::kTPCrefit)) return kFALSE;\r
+  \r
+    // Chi2 per TPC cluster\r
+    Int_t nTPCclusters = d[i]->GetTPCNcls();\r
+    Float_t chi2perTPCcluster = d[i]->GetTPCchi2()/Float_t(nTPCclusters);\r
+    if(chi2perTPCcluster > 4) return kFALSE;\r
+\r
+    // TPC cluster ratio\r
+    Float_t cRatioTPC = d[i]->GetTPCNclsF() > 0. ? static_cast<Float_t>(d[i]->GetTPCNcls())/static_cast<Float_t> (d[i]->GetTPCNclsF()) : 1.;\r
+    if(cRatioTPC < 0.6) return kFALSE;\r
+    \r
+    // kinks\r
+    if(d[i]->GetKinkIndex(0) != 0) return kFALSE;\r
+    \r
+  }\r
+\r
+  return kTRUE;\r
+}\r
+//____________________________________________________________________\r
+Bool_t  const AliESDv0KineCuts::CaseGamma(AliESDv0* const v0, Int_t &pdgV0, Int_t &pdgP, Int_t &pdgN){\r
+  //\r
+  // process the gamma conversion candidate\r
+  //\r
+\r
+  if(!v0) return kFALSE;\r
+\r
+  AliVTrack* daughter[2];\r
+  Int_t pIndex = 0, nIndex = 0;\r
+\r
+  Bool_t sign = CheckSigns(v0);\r
+  if(sign){\r
+    pIndex = v0->GetPindex();\r
+    nIndex = v0->GetNindex();\r
+  }\r
+  else{\r
+    pIndex = v0->GetNindex();\r
+    nIndex = v0->GetPindex();    \r
+  }\r
+  daughter[0] = dynamic_cast<AliVTrack *>(fEvent->GetTrack(pIndex));\r
+  daughter[1] = dynamic_cast<AliVTrack *>(fEvent->GetTrack(nIndex));\r
+  if(!daughter[0] || !daughter[1]) return kFALSE;\r
+\r
+  AliKFParticle *kfMother = CreateMotherParticle(daughter[0], daughter[1], TMath::Abs(kElectron), TMath::Abs(kElectron));\r
+  if(!kfMother) return kFALSE;\r
+\r
+  AliESDtrack* d[2];\r
+  d[0] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(pIndex));\r
+  d[1] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(nIndex));\r
+\r
+  Float_t iMass = v0->GetEffMass(0, 0);\r
+\r
+  // cos pointing angle\r
+  Double_t cosPoint = v0->GetV0CosineOfPointingAngle();\r
+  cosPoint = TMath::ACos(cosPoint);\r
+\r
+  // DCA between daughters\r
+  Double_t dca = v0->GetDcaV0Daughters();\r
+\r
+  // Production vertex\r
+  Double_t x, y, z; \r
+  v0->GetXYZ(x,y,z);\r
+  Double_t r = TMath::Sqrt(x*x + y*y);\r
+\r
+  Double_t xy[2];\r
+  Double_t r2 = -1.;\r
+  if ( GetConvPosXY(d[0], d[1], xy) ){\r
+    r2 = TMath::Sqrt(xy[0]*xy[0] + xy[1]*xy[1]);\r
+  }\r
+\r
+  // psi pair \r
+  Double_t psiPair = PsiPair(v0);\r
+  \r
+  // V0 chi2/ndf\r
+  Double_t chi2ndf = kfMother->GetChi2()/kfMother->GetNDF();\r
+\r
+  if(kfMother) delete kfMother; \r
+  \r
+  // apply the cuts\r
+\r
+  if(iMass > fGcutInvMass) return kFALSE;\r
+\r
+  if(chi2ndf > fGcutChi2NDF) return kFALSE;\r
+\r
+  if(cosPoint < fGcutCosPoint[0] || cosPoint > fGcutCosPoint[1]) return kFALSE;\r
+\r
+  if(dca < fGcutDCA[0] || dca > fGcutDCA[1]) return kFALSE;\r
+\r
+  if(r < fGcutVertexR[0] || r > fGcutVertexR[1]) return kFALSE;\r
+\r
+  if(psiPair < fGcutPsiPair[0] || psiPair > fGcutPsiPair[1]) return kFALSE;\r
+  \r
+  // all cuts passed\r
+\r
+  pdgV0 = 22;\r
+  if(sign){\r
+    pdgP = -11;\r
+    pdgN = 11;\r
+  }\r
+  else{\r
+    pdgP = 11;\r
+    pdgN = -11;\r
+  }\r
+\r
+  return kTRUE;\r
+}\r
+//____________________________________________________________________\r
+Bool_t  const AliESDv0KineCuts::CaseK0(AliESDv0* const v0, Int_t &pdgV0, Int_t &pdgP, Int_t &pdgN){\r
+  //\r
+  // process the K0 candidate\r
+  //\r
+\r
+  if(!v0) return kFALSE;\r
+  \r
+  AliVTrack* daughter[2];\r
+  Int_t pIndex = 0, nIndex = 0;\r
+  Bool_t sign = CheckSigns(v0);\r
+  if(sign){\r
+    pIndex = v0->GetPindex();\r
+    nIndex = v0->GetNindex();\r
+  }\r
+  else{\r
+    pIndex = v0->GetNindex();\r
+    nIndex = v0->GetPindex();    \r
+  }\r
\r
+  daughter[0] = dynamic_cast<AliVTrack *>(fEvent->GetTrack(pIndex));\r
+  daughter[1] = dynamic_cast<AliVTrack *>(fEvent->GetTrack(nIndex));\r
+  if(!daughter[0] || !daughter[1]) return kFALSE;\r
+\r
+  AliKFParticle *kfMother = CreateMotherParticle(daughter[0], daughter[1], TMath::Abs(kPiPlus), TMath::Abs(kPiPlus));\r
+  if(!kfMother) return kFALSE;\r
+\r
+  AliESDtrack* d[2];\r
+  d[0] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(pIndex));\r
+  d[1] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(nIndex));\r
+\r
+  Float_t iMass = v0->GetEffMass(2, 2);\r
+\r
+  // cos pointing angle\r
+  Double_t cosPoint = v0->GetV0CosineOfPointingAngle();\r
+  cosPoint = TMath::ACos(cosPoint);\r
+\r
+  // DCA between daughters\r
+  Double_t dca = v0->GetDcaV0Daughters();\r
+\r
+  // Production vertex\r
+  Double_t x, y, z; \r
+  v0->GetXYZ(x,y,z);\r
+\r
+  Double_t r = TMath::Sqrt(x*x + y*y);  \r
+\r
+  // V0 chi2/ndf\r
+  Double_t chi2ndf = kfMother->GetChi2()/kfMother->GetNDF();\r
+  \r
+  if(kfMother) delete kfMother; \r
+\r
+  //\r
+  // apply the cuts\r
+  //\r
+  if(iMass < fK0cutInvMass[0] || iMass > fK0cutInvMass[1]) return kFALSE;\r
+\r
+  if(chi2ndf > fK0cutChi2NDF) return kFALSE;\r
+\r
+  if(cosPoint < fK0cutCosPoint[0] || cosPoint > fK0cutCosPoint[1]) return kFALSE;\r
+\r
+  if(dca < fK0cutDCA[0] || dca > fK0cutDCA[1]) return kFALSE;\r
+\r
+  if(r < fK0cutVertexR[0] || r > fK0cutVertexR[1]) return kFALSE;\r
+\r
+  // all cuts passed\r
+  pdgV0 = 310;\r
+  if(sign){\r
+    pdgP = 211;\r
+    pdgN = -211;\r
+  }\r
+  else{\r
+    pdgP = -211;\r
+    pdgN = 211;\r
+  }\r
+\r
+  return kTRUE;\r
+}\r
+//____________________________________________________________________\r
+Bool_t  const AliESDv0KineCuts::CaseLambda(AliESDv0* const v0, Int_t &pdgV0, Int_t &pdgP, Int_t &pdgN, Int_t id){\r
+  //\r
+  // process teh Lambda and Anti-Lambda candidate\r
+  //\r
+  \r
+  if(!v0) return kFALSE;\r
+\r
+    const Double_t cL0mass=TDatabasePDG::Instance()->GetParticle(kLambda0)->Mass();  // PDG lambda mass\r
+\r
+  AliVTrack* daughter[2];\r
+  Int_t pIndex = 0, nIndex = 0;\r
+  Float_t mMass[2] = {-1., -1.};\r
+  Bool_t sign = CheckSigns(v0);\r
+  if(sign){\r
+    pIndex = v0->GetPindex();\r
+    nIndex = v0->GetNindex();\r
+    mMass[0] = v0->GetEffMass(4, 2);\r
+    mMass[1] = v0->GetEffMass(2, 4);\r
+  }\r
+  else{\r
+    pIndex = v0->GetNindex();\r
+    nIndex = v0->GetPindex();    \r
+    mMass[0] = v0->GetEffMass(2, 4);\r
+    mMass[1] = v0->GetEffMass(4, 2);\r
+  }\r
\r
+  daughter[0] = dynamic_cast<AliVTrack *>(fEvent->GetTrack(pIndex));\r
+  daughter[1] = dynamic_cast<AliVTrack *>(fEvent->GetTrack(nIndex));\r
+  if(!daughter[0] || !daughter[1]) return kFALSE;\r
+\r
+  AliKFParticle *kfMother[2] = {0x0, 0x0};\r
+  // Lambda\r
+  kfMother[0] = CreateMotherParticle(daughter[0], daughter[1], TMath::Abs(kProton), TMath::Abs(kPiPlus));\r
+  if(!kfMother[0]) return kFALSE;\r
+  \r
+  // Anti-Lambda\r
+  kfMother[1] = CreateMotherParticle(daughter[0], daughter[1], TMath::Abs(kPiPlus), TMath::Abs(kProton));\r
+  if(!kfMother[1]) return kFALSE;\r
+\r
+  Float_t dMass[2] = {TMath::Abs(mMass[0] - cL0mass), TMath::Abs(mMass[1] - cL0mass)};\r
+  \r
+  AliESDtrack* d[2];\r
+  d[0] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(pIndex));\r
+  d[1] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(nIndex));\r
+  if(!d[0] || !d[1])    return kFALSE;\r
+  \r
+  Float_t p[2] = {d[0]->GetP(), d[1]->GetP()}; \r
+\r
+  // check the 3 lambda - antilambda variables\r
+  Int_t check[2] = {-1, -1};   // 0 : lambda, 1 : antilambda\r
+  // 1) momentum of the daughter particles - proton is expected to have higher momentum than pion\r
+  check[0] = (p[0] > p[1]) ? 0 : 1;\r
+  // 2) mass of the mother particle\r
+  check[1] = (dMass[0] < dMass[1]) ? 0 : 1;\r
\r
+  // require positive correlation of (1) and (2)\r
+  if(check[0] != check[1]){\r
+    if(kfMother[0]) delete kfMother[0]; \r
+    if(kfMother[1]) delete kfMother[1]; \r
+    return kFALSE;\r
+  }\r
+\r
+  // now that the check[0] == check[1]\r
+  const Int_t type = check[0];\r
+\r
+  // require that the input armenteros preselection agree:\r
+  if(type != id) return kFALSE;\r
+\r
+  Float_t iMass =0.;\r
+  if(sign){\r
+    iMass = (type == 0) ? v0->GetEffMass(4, 2) : v0->GetEffMass(2, 4);\r
+  }\r
+  else{\r
+    iMass = (type == 0) ? v0->GetEffMass(2, 4) : v0->GetEffMass(4, 2);\r
+  }\r
+\r
+  // cos pointing angle\r
+  Double_t cosPoint = v0->GetV0CosineOfPointingAngle();\r
+  cosPoint = TMath::ACos(cosPoint);\r
+\r
+  // DCA between daughters\r
+  Double_t dca = v0->GetDcaV0Daughters();\r
+  \r
+  // Production vertex\r
+  Double_t x, y, z; \r
+  v0->GetXYZ(x,y,z);\r
+  Double_t r = TMath::Sqrt(x*x + y*y);\r
+\r
+  // proton - pion indices\r
+  Int_t ix[2] = {0, 1};\r
+  if(1 == type){\r
+    ix[0] = 1;\r
+    ix[1] = 0;\r
+  }\r
+\r
+  // V0 chi2/ndf\r
+  Double_t chi2ndf = kfMother[type]->GetChi2()/kfMother[type]->GetNDF();\r
+\r
+  if(kfMother[0]) delete kfMother[0]; \r
+  if(kfMother[1]) delete kfMother[1]; \r
+\r
+  //\r
+  // apply the cuts\r
+  //\r
+\r
+  if(iMass < fLcutInvMass[0] || iMass > fLcutInvMass[1]) return kFALSE;\r
+\r
+  if(chi2ndf > fLcutChi2NDF) return kFALSE;\r
+\r
+  if(cosPoint < fLcutCosPoint[0] || cosPoint > fLcutCosPoint[1]) return kFALSE;\r
+\r
+  if(dca < fLcutDCA[0] || dca > fLcutDCA[1]) return kFALSE;\r
+\r
+  if(r < fLcutVertexR[0] || r > fLcutVertexR[1]) return kFALSE;\r
+\r
+  // all cuts passed\r
+\r
+  if(0 == type){\r
+    pdgV0 = 3122;\r
+    if(sign){\r
+      pdgP = 2212;\r
+      pdgN = -211;\r
+    }\r
+    else{\r
+      pdgP = -211;\r
+      pdgN = 2212;\r
+    }\r
+  }\r
+  else{\r
+    pdgV0 = -3122;\r
+    if(sign){\r
+      pdgP = 211;\r
+      pdgN = -2212;\r
+    }\r
+    else{\r
+      pdgP = -2212;\r
+      pdgN = 211;\r
+    }\r
+  }\r
+\r
+  return kTRUE;\r
+}\r
+//____________________________________________________________________\r
+Bool_t const AliESDv0KineCuts::V0CutsCommon(AliESDv0 * const v0){\r
+  //\r
+  // V0 cuts common to all V0s\r
+  //\r
+\r
+  AliESDtrack* dN, *dP; \r
\r
+  dP = dynamic_cast<AliESDtrack *>(fEvent->GetTrack(v0->GetPindex()));\r
+  dN = dynamic_cast<AliESDtrack *>(fEvent->GetTrack(v0->GetNindex())); \r
+  \r
+  if(!dN || !dP) return kFALSE;\r
+\r
+  Int_t qP = dP->Charge();\r
+  Int_t qN = dN->Charge();\r
+\r
+  if((qP*qN) != -1) return kFALSE;\r
+\r
+  return kTRUE;\r
+}\r
+//____________________________________________________________________\r
+void const AliESDv0KineCuts::Armenteros(AliESDv0* const v0, Float_t val[2]){\r
+  //\r
+  // computes the Armenteros variables for given V0\r
+  // fills the histogram\r
+  // returns the values via "val"\r
+  //\r
+  \r
+  Double_t mn[3] = {0,0,0};\r
+  Double_t mp[3] = {0,0,0};  \r
+  Double_t mm[3] = {0,0,0};  \r
+\r
+  if(CheckSigns(v0)){\r
+    v0->GetNPxPyPz(mn[0],mn[1],mn[2]); //reconstructed cartesian momentum components of negative daughter\r
+    v0->GetPPxPyPz(mp[0],mp[1],mp[2]); //reconstructed cartesian momentum components of positive daughter\r
+  }\r
+  else{\r
+    v0->GetPPxPyPz(mn[0],mn[1],mn[2]); //reconstructed cartesian momentum components of negative daughter\r
+    v0->GetNPxPyPz(mp[0],mp[1],mp[2]); //reconstructed cartesian momentum components of positive daughter\r
+  }\r
+  v0->GetPxPyPz(mm[0],mm[1],mm[2]); //reconstructed cartesian momentum components of mother\r
+\r
+  TVector3 vecN(mn[0],mn[1],mn[2]);\r
+  TVector3 vecP(mp[0],mp[1],mp[2]);\r
+  TVector3 vecM(mm[0],mm[1],mm[2]);\r
+  \r
+  Double_t thetaP = acos((vecP * vecM)/(vecP.Mag() * vecM.Mag()));\r
+  Double_t thetaN = acos((vecN * vecM)/(vecN.Mag() * vecM.Mag()));\r
+  \r
+  Double_t alfa = ((vecP.Mag())*cos(thetaP)-(vecN.Mag())*cos(thetaN))/\r
+    ((vecP.Mag())*cos(thetaP)+(vecN.Mag())*cos(thetaN)) ;\r
+  Double_t qt = vecP.Mag()*sin(thetaP);\r
+\r
+  val[0] = alfa;\r
+  val[1] = qt;\r
+}\r
+//____________________________________________________________________\r
+Bool_t const AliESDv0KineCuts::CheckSigns(AliESDv0* const v0){\r
+  //\r
+  // check wheter the sign was correctly applied to \r
+  // V0 daughter tracks\r
+  //\r
+  \r
+  Bool_t correct = kFALSE;\r
+\r
+  Int_t pIndex = 0, nIndex = 0;\r
+  pIndex = v0->GetPindex();\r
+  nIndex = v0->GetNindex();\r
+  \r
+  AliESDtrack* d[2];\r
+  d[0] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(pIndex));\r
+  d[1] = dynamic_cast<AliESDtrack*>(fEvent->GetTrack(nIndex));\r
+\r
+  Int_t sign[2];\r
+  sign[0] = (int)d[0]->GetSign();\r
+  sign[1] = (int)d[1]->GetSign();\r
+  \r
+  if(-1 == sign[0] && 1 == sign[1]){\r
+    correct = kFALSE;\r
+  }\r
+  else{\r
+    correct = kTRUE;\r
+  }\r
+  \r
+  return correct;\r
+}\r
+//________________________________________________________________\r
+Double_t const AliESDv0KineCuts::PsiPair(AliESDv0* const v0) {\r
+  //\r
+  // Angle between daughter momentum plane and plane \r
+  // \r
+\r
+  if(!fEvent) return -1.;\r
+\r
+  Float_t magField = fEvent->GetMagneticField();\r
+\r
+  Int_t pIndex = -1;\r
+  Int_t nIndex = -1;\r
+  if(CheckSigns(v0)){\r
+    pIndex = v0->GetPindex();\r
+    nIndex = v0->GetNindex();\r
+  }\r
+  else{\r
+    pIndex = v0->GetNindex();\r
+    nIndex = v0->GetPindex();    \r
+  }\r
\r
+\r
+  AliESDtrack* daughter[2];\r
+\r
+  daughter[0] = dynamic_cast<AliESDtrack *>(fEvent->GetTrack(pIndex));\r
+  daughter[1] = dynamic_cast<AliESDtrack *>(fEvent->GetTrack(nIndex));\r
+\r
+  Double_t x, y, z;\r
+  v0->GetXYZ(x,y,z);//Reconstructed coordinates of V0; to be replaced by Markus Rammler's method in case of conversions!\r
+  \r
+  Double_t mn[3] = {0,0,0};\r
+  Double_t mp[3] = {0,0,0};\r
+  \r
+\r
+  v0->GetNPxPyPz(mn[0],mn[1],mn[2]);//reconstructed cartesian momentum components of negative daughter;\r
+  v0->GetPPxPyPz(mp[0],mp[1],mp[2]);//reconstructed cartesian momentum components of positive daughter; \r
+\r
+\r
+  Double_t deltat = 1.;\r
+  deltat = TMath::ATan(mp[2]/(TMath::Sqrt(mp[0]*mp[0] + mp[1]*mp[1])+1.e-13)) -  TMath::ATan(mn[2]/(TMath::Sqrt(mn[0]*mn[0] + mn[1]*mn[1])+1.e-13));//difference of angles of the two daughter tracks with z-axis\r
+\r
+  Double_t radiussum = TMath::Sqrt(x*x + y*y) + 50;//radius to which tracks shall be propagated\r
+\r
+  Double_t momPosProp[3];\r
+  Double_t momNegProp[3];\r
+    \r
+  AliExternalTrackParam pt(*daughter[0]), nt(*daughter[1]);\r
+    \r
+  Double_t psiPair = 4.;\r
+\r
+  if(nt.PropagateTo(radiussum,magField) == 0)//propagate tracks to the outside\r
+    psiPair =  -5.;\r
+  if(pt.PropagateTo(radiussum,magField) == 0)\r
+    psiPair = -5.;\r
+  pt.GetPxPyPz(momPosProp);//Get momentum vectors of tracks after propagation\r
+  nt.GetPxPyPz(momNegProp);\r
+  \r
+  Double_t pEle =\r
+    TMath::Sqrt(momNegProp[0]*momNegProp[0]+momNegProp[1]*momNegProp[1]+momNegProp[2]*momNegProp[2]);//absolute momentum value of negative daughter\r
+  Double_t pPos =\r
+    TMath::Sqrt(momPosProp[0]*momPosProp[0]+momPosProp[1]*momPosProp[1]+momPosProp[2]*momPosProp[2]);//absolute momentum value of positive daughter\r
+    \r
+  Double_t scalarproduct =\r
+    momPosProp[0]*momNegProp[0]+momPosProp[1]*momNegProp[1]+momPosProp[2]*momNegProp[2];//scalar product of propagated positive and negative daughters' momenta\r
+    \r
+  Double_t chipair = TMath::ACos(scalarproduct/(pEle*pPos));//Angle between propagated daughter tracks\r
+\r
+  psiPair =  TMath::Abs(TMath::ASin(deltat/chipair));  \r
+\r
+  return psiPair; \r
+}\r
+//___________________________________________________________________\r
+Bool_t const AliESDv0KineCuts::GetConvPosXY(AliESDtrack * const ptrack, AliESDtrack * const ntrack, Double_t convpos[2]){\r
+  //\r
+  // recalculate the gamma conversion XY postition\r
+  //\r
+\r
+  const Double_t b = fEvent->GetMagneticField();\r
+\r
+  Double_t helixcenterpos[2];\r
+  GetHelixCenter(ptrack,b,ptrack->Charge(),helixcenterpos);\r
+\r
+  Double_t helixcenterneg[2];\r
+  GetHelixCenter(ntrack,b,ntrack->Charge(),helixcenterneg);\r
+\r
+  Double_t  poshelix[6];\r
+  ptrack->GetHelixParameters(poshelix,b);\r
+  Double_t posradius = TMath::Abs(1./poshelix[4]);\r
+\r
+  Double_t  neghelix[6];\r
+  ntrack->GetHelixParameters(neghelix,b);\r
+  Double_t negradius = TMath::Abs(1./neghelix[4]);\r
+\r
+  Double_t xpos = helixcenterpos[0];\r
+  Double_t ypos = helixcenterpos[1];\r
+  Double_t xneg = helixcenterneg[0];\r
+  Double_t yneg = helixcenterneg[1];\r
+\r
+  convpos[0] = (xpos*negradius + xneg*posradius)/(negradius+posradius);\r
+  convpos[1] = (ypos*negradius+  yneg*posradius)/(negradius+posradius);\r
+\r
+  return 1;\r
+}\r
+//___________________________________________________________________\r
+Bool_t const AliESDv0KineCuts::GetHelixCenter(AliESDtrack * const track, Double_t b,Int_t charge, Double_t center[2]){\r
+  //\r
+  // computes the center of the track helix\r
+  //\r
+  \r
+  Double_t pi = TMath::Pi();\r
+  \r
+  Double_t  helix[6];\r
+  track->GetHelixParameters(helix,b);\r
+  \r
+  Double_t xpos =  helix[5];\r
+  Double_t ypos =  helix[0];\r
+  Double_t radius = TMath::Abs(1./helix[4]);\r
+  Double_t phi = helix[2];\r
+\r
+  if(phi < 0){\r
+    phi = phi + 2*pi;\r
+  }\r
+\r
+  phi -= pi/2.;\r
+  Double_t xpoint =  radius * TMath::Cos(phi);\r
+  Double_t ypoint =  radius * TMath::Sin(phi);\r
+\r
+  if(b<0){\r
+    if(charge > 0){\r
+      xpoint = - xpoint;\r
+      ypoint = - ypoint;\r
+    }\r
+\r
+    if(charge < 0){\r
+      xpoint =  xpoint;\r
+      ypoint =  ypoint;\r
+    }\r
+  }\r
+  if(b>0){\r
+    if(charge > 0){\r
+      xpoint =  xpoint;\r
+      ypoint =  ypoint;\r
+    }\r
+\r
+    if(charge < 0){\r
+      xpoint = - xpoint;\r
+      ypoint = - ypoint;\r
+    }\r
+  }\r
+  center[0] =  xpos + xpoint;\r
+  center[1] =  ypos + ypoint;\r
+\r
+  return 1;\r
+}\r
+//___________________________________________________________________\r
+AliKFParticle *AliESDv0KineCuts::CreateMotherParticle(const AliVTrack* const pdaughter, const AliVTrack* const ndaughter, Int_t pspec, Int_t nspec){\r
+  //\r
+  // Creates a mother particle\r
+  //\r
+  AliKFParticle pkfdaughter(*pdaughter, pspec);\r
+  AliKFParticle nkfdaughter(*ndaughter, nspec);\r
+  \r
+  \r
+  // Create the mother particle \r
+  AliKFParticle *m = new AliKFParticle(pkfdaughter, nkfdaughter);\r
+  // DEBUG - testing\r
+  if(TMath::Abs(kElectron) == pspec && TMath::Abs(kElectron) == nspec) m->SetMassConstraint(0, 0.001);\r
+  else if(TMath::Abs(kPiPlus) == pspec && TMath::Abs(kPiPlus) == nspec) m->SetMassConstraint(TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(), 0.);\r
+  else if(TMath::Abs(kProton) == pspec && TMath::Abs(kPiPlus) == nspec) m->SetMassConstraint(TDatabasePDG::Instance()->GetParticle(kLambda0)->Mass(), 0.);\r
+  else if(TMath::Abs(kPiPlus) == pspec && TMath::Abs(kProton) == nspec) m->SetMassConstraint(TDatabasePDG::Instance()->GetParticle(kLambda0)->Mass(), 0.);\r
+  else{\r
+    AliErrorClass("Wrong daughter ID - mass constraint can not be set");\r
+  }\r
+\r
+  AliKFVertex improvedVertex = *fPrimaryVertex;\r
+  improvedVertex += *m;\r
+  m->SetProductionVertex(improvedVertex);\r
+  \r
+  // update 15/06/2010\r
+  // mother particle will not be added to primary vertex but only to its copy \r
+  // as this confilcts with calling\r
+  // m->SetPrimaryVertex() function and\r
+  // subsequently removing the mother particle afterwards\r
+  // Source: Sergey Gorbunov\r
+\r
+  return m;\r
+}\r
+//____________________________________________________________________\r
+void  AliESDv0KineCuts::SetEvent(AliESDEvent* const event){\r
+  //\r
+  // direct setter of ESD event\r
+  //\r
+  fEvent = event;\r
+  if(!fEvent){\r
+    AliErrorClass("Invalid input event pointer");\r
+    return;\r
+  }\r
+\r
+}\r
+//____________________________________________________________________\r
+void  AliESDv0KineCuts::SetEvent(AliVEvent* const event){\r
+  //\r
+  // direct setter of ESD event\r
+  //\r
+  if(event)\r
+    fEvent = static_cast<AliESDEvent*>(event);\r
+  if(!fEvent){\r
+    AliErrorClass("Invalid input event pointer");\r
+    return;\r
+  }\r
+\r
+}\r
+//________________________________________________________________\r
+void AliESDv0KineCuts::SetPrimaryVertex(AliKFVertex* const v){\r
+  //\r
+  // set the primary vertex of the event\r
+  //\r
+  fPrimaryVertex = v;\r
+  if(!fPrimaryVertex){\r
+    AliErrorClass("Failed to initialize the primary vertex");\r
+    return;\r
+  }\r
+}\r
+//___________________________________________________________________\r
+void AliESDv0KineCuts::SetMode(Int_t mode, Int_t type){\r
+  //\r
+  // this function allows the user to select (prior running the 'ProcessV0' function)\r
+  // to select different approaches to V0 selection - the 'mode'\r
+  // - and -\r
+  // different systems (pp, PbPb) - 'type' \r
+  //\r
+  // To see the cut values for different modes please refer to the\r
+  // function SetCuts()\r
+  //\r
+  // Important notice: based on the parameters particular sets of cuts will\r
+  // be activated for teh V0 selection. If some additional changes to single\r
+  // cuts are needed please us the SetXXXcut function (see the header file)\r
+  // \r
+\r
+  switch(mode){\r
+  case kPurity:\r
+    fMode = kPurity;  // used to obtain highest purity possible - the efficiency may be low\r
+  case kEffGamma:\r
+    fMode = kEffGamma; // used to obtain highes efficiency possible - the purity may be worse\r
+  default:\r
+    AliError("V0 selection mode not recognozed, setting 'kPurity'");\r
+    fMode = kPurity;\r
+  }\r
+\r
+  switch(type){\r
+  case kPP:\r
+    fType = kPP;  // cuts optimized for low multiplicity \r
+  case kPbPb:\r
+    fType = kPbPb;  // cuts optimized for high multiplicity\r
+  }\r
+  \r
+  // setup the cut values for selected mode & type\r
+  SetCuts();\r
+\r
+}\r
+//___________________________________________________________________\r
+void AliESDv0KineCuts::SetMode(Int_t mode, const char* type){\r
+  //\r
+  // overloaded function - please see above\r
+  // \r
+  \r
+  Int_t t = -1;\r
+\r
+  if(!strcmp("pp", type)) t = kPP;\r
+  else if(!(strcmp("PbPb", type))) t = kPbPb;\r
+  else{\r
+    AliError("data type not recognized, setting 'pp'");\r
+    t = kPP;    \r
+  }\r
+\r
+  SetMode(mode, t);\r
+\r
+}\r
+//___________________________________________________________________\r
+void AliESDv0KineCuts::SetCuts(){\r
+  //\r
+  // this funciton sets the default cut values based on the selected\r
+  // fMode and fType.\r
+  // please note that only the cuts that have different values than the default\r
+  // cuts are updated here\r
+  //\r
+  \r
+  // last update: 14/02/2011\r
+  // as a very preliminary  - the only change to default cuts is to apply\r
+  // less restricting gamma conversion selection in PreselectV0() function\r
+  \r
+\r
+  \r
+}\r
diff --git a/ANALYSIS/AliESDv0KineCuts.h b/ANALYSIS/AliESDv0KineCuts.h
new file mode 100644 (file)
index 0000000..e14d1e6
--- /dev/null
@@ -0,0 +1,191 @@
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *\r
+ * See cxx source for full Copyright notice                               */\r
+/*\r
+ * plesae see source file for more details\r
+ */\r
+#ifndef ALIESDV0KINECUTS_H\r
+#define ALIESDV0KINECUTS_H\r
+\r
+#include <TObject.h>\r
+\r
+class AliESDv0;\r
+class AliESDEvent;\r
+class AliVEvent;\r
+class AliESDtrack;\r
+class AliVTrack;\r
+class AliKFParticle;\r
+class AliKFVertex;\r
+\r
+class AliESDv0KineCuts : public TObject{\r
+ public:\r
+  enum{ // Reconstructed V0\r
+    kUndef = -1,\r
+      kGamma = 0,\r
+      kK0 = 1,\r
+      kLambda = 2,\r
+      kALambda = 3\r
+      };\r
+  enum{ // data types\r
+    kPP = 0,\r
+      kPbPb = 1,  // not yet implemented\r
+      };\r
+  enum{ // operation modes\r
+    kPurity = 0, // purely kinematical selection\r
+      kEffGamma = 1  // !!! involves TPC dEdx or nSimga cuts !!!\r
+      };\r
+  \r
+  AliESDv0KineCuts();\r
+  virtual ~AliESDv0KineCuts();\r
+\r
+  AliESDv0KineCuts(const AliESDv0KineCuts &ref);\r
+  AliESDv0KineCuts &operator=(const AliESDv0KineCuts &ref);\r
+\r
+  // main selection function - called once per V0 candidate\r
+  Bool_t const ProcessV0(AliESDv0* const v0, Int_t &pdgV0, Int_t &pdgP, Int_t &pdgN);\r
+  Bool_t const ProcessV0(AliESDv0* const v0, Int_t &pdgP, Int_t &pdgN);\r
+\r
+  // must be called by the user\r
+  void SetEvent(AliESDEvent* const event);\r
+  void SetEvent(AliVEvent* const event);\r
+  void SetPrimaryVertex(AliKFVertex* const v);\r
+\r
+  // user can select an operation modes [see .cxx for details]\r
+  void   SetMode(Int_t mode, Int_t type);\r
+  void   SetMode(Int_t mode, const char* type);\r
+\r
+  //\r
+  // setter functions for V0 cut values\r
+  // for default values see the constructor\r
+  // see the default contructor for comments\r
+  //\r
+\r
+  // single track cuts\r
+  void   SetNTPCclusters(Int_t n) { fTPCNcls = n; };\r
+  void   SetTPCrefit(Bool_t r = kTRUE) { fTPCrefit = r; };\r
+  void   SetTPCchi2perCls(Float_t chi2) { fTPCchi2perCls = chi2; };\r
+  void   SetTPCclusterratio(Float_t r) { fTPCclsRatio = r; };\r
+  void   SetNoKinks(Bool_t k = kTRUE) { fNoKinks = k; };\r
+\r
+  // gamma cuts\r
+  void   SetGammaCutChi2NDF(Float_t val)  { fGcutChi2NDF = val; };\r
+  void   SetGammaCutCosPoint(Float_t * const val) { \r
+    fGcutCosPoint[0] = val[0];\r
+    fGcutCosPoint[1] = val[1];\r
+  };\r
+  void   SetGammaCutDCA(Float_t * const val){\r
+    fGcutDCA[0] = val[0];\r
+    fGcutDCA[1] = val[1];\r
+  };\r
+  void   SetGammaCutVertexR(Float_t * const val){\r
+    fGcutVertexR[0] = val[0];\r
+    fGcutVertexR[1] = val[1];\r
+  };\r
+  void   SetGammaCutPsiPair(Float_t * const val){\r
+    fGcutPsiPair[0] = val[0];\r
+    fGcutPsiPair[1] = val[1];\r
+  };\r
+  void   SetGammaCutInvMass(Float_t val){\r
+    fGcutInvMass = val;\r
+  };\r
+  // K0 cuts\r
+  void   SetK0CutChi2NDF(Float_t val)  { fK0cutChi2NDF = val; };\r
+  void   SetK0CutCosPoint(Float_t * const val) { \r
+    fK0cutCosPoint[0] = val[0];\r
+    fK0cutCosPoint[1] = val[1];\r
+  };\r
+  void   SetK0CutDCA(Float_t * const val){\r
+    fK0cutDCA[0] = val[0];\r
+    fK0cutDCA[1] = val[1];\r
+  };\r
+  void   SetK0CutVertexR(Float_t * const val){\r
+    fK0cutVertexR[0] = val[0];\r
+    fK0cutVertexR[1] = val[1];\r
+  };\r
+  void   SetK0CutInvMass(Float_t * const val){\r
+    fK0cutInvMass[0] = val[0];\r
+    fK0cutInvMass[1] = val[1];\r
+  };\r
+  // lambda & anti-lambda cuts\r
+  void   SetLambdaCutChi2NDF(Float_t val)  { fLcutChi2NDF = val; };\r
+  void   SetLambdaCutCosPoint(Float_t * const val) { \r
+    fLcutCosPoint[0] = val[0];\r
+    fLcutCosPoint[1] = val[1];\r
+  };\r
+  void   SetLambdaCutDCA(Float_t * const val){\r
+    fLcutDCA[0] = val[0];\r
+    fLcutDCA[1] = val[1];\r
+  };\r
+  void   SetLambdaCutVertexR(Float_t * const val){\r
+    fLcutVertexR[0] = val[0];\r
+    fLcutVertexR[1] = val[1];\r
+  };\r
+  void   SetLambdaCutInvMass(Float_t * const val){\r
+    fLcutInvMass[0] = val[0];\r
+    fLcutInvMass[1] = val[1];\r
+  };\r
+  \r
+\r
+  Int_t  const PreselectV0(AliESDv0* const v0);\r
+\r
+  Bool_t const CaseGamma(AliESDv0* const v0, Int_t &pdgV0, Int_t &pdgP, Int_t &pdgN);\r
+  Bool_t const CaseK0(AliESDv0* const v0, Int_t &pdgV0, Int_t &pdgP, Int_t &pdgN);\r
+  Bool_t const CaseLambda(AliESDv0* const v0, Int_t &pdgV0, Int_t &pdgP, Int_t &pdgN, Int_t id);\r
+\r
+  Bool_t const V0CutsCommon(AliESDv0 * const v0);\r
+  Bool_t const SingleTrackCuts(AliESDv0 * const v0);\r
+  void   const Armenteros(AliESDv0* const v0, Float_t val[2]);\r
+  Bool_t const CheckSigns(AliESDv0* const v0);\r
+\r
+  Double_t const PsiPair(AliESDv0* const v0);\r
+  Bool_t   const GetConvPosXY(AliESDtrack * const ptrack, AliESDtrack * const ntrack, Double_t convpos[2]);\r
+  Bool_t   const GetHelixCenter(AliESDtrack * const track, Double_t b, Int_t charge, Double_t center[2]);\r
+\r
+ protected:\r
+  void Copy(TObject &ref) const;\r
+\r
+ private:\r
+\r
+  AliKFParticle *CreateMotherParticle(const AliVTrack* const pdaughter, const AliVTrack* const ndaughter, Int_t pspec, Int_t nspec);\r
+  void      SetCuts();                          // setup cuts for selected fMode and fType, see source file for details\r
+  Bool_t    GammaEffCuts(AliESDv0 * const v0);  // set of cuts optimized for high gamma efficiency\r
+\r
+ private:\r
+  AliESDEvent           *fEvent;          // current event\r
+  AliKFVertex           *fPrimaryVertex;  // primary vertex\r
+\r
+  Int_t                 fType;            // data type: p-p or Pb-Pb\r
+  Int_t                 fMode;            // current operation mode\r
+\r
+  // single track cuts\r
+  Int_t                 fTPCNcls;          // number of TPC clusters\r
+  Bool_t                fTPCrefit;         // TPC refit - yes [kTRUE] or do not care [kFALSE]\r
+  Float_t               fTPCchi2perCls;    // max. chi2 per TPC cluster\r
+  Float_t               fTPCclsRatio;      // min. TPC cluster ratio\r
+  Bool_t                fNoKinks;          // kinks - no [kTRUE] or do not care [kFalse]\r
+\r
+  // gamma cut values\r
+  Float_t               fGcutChi2NDF;      // Chi2NF cut value for the AliKFparticle gamma\r
+  Float_t               fGcutCosPoint[2];  // cos of the pointing angle [min, max]\r
+  Float_t               fGcutDCA[2];       // DCA between the daughter tracks [min, max]\r
+  Float_t               fGcutVertexR[2];   // radius of the conversion point [min, max]\r
+  Float_t               fGcutPsiPair[2];   // value of the psi pair cut [min, max]\r
+  Float_t               fGcutInvMass;      // upper value on the gamma invariant mass\r
+  // K0 cut values\r
+  Float_t               fK0cutChi2NDF;     // Chi2NF cut value for the AliKFparticle K0\r
+  Float_t               fK0cutCosPoint[2]; // cos of the pointing angle [min, max]\r
+  Float_t               fK0cutDCA[2];      // DCA between the daughter tracks [min, max]\r
+  Float_t               fK0cutVertexR[2];  // radius of the decay point [min, max]\r
+  Float_t               fK0cutInvMass[2];  // invariant mass window\r
+  // Lambda & anti-Lambda cut values\r
+  Float_t               fLcutChi2NDF;      // Chi2NF cut value for the AliKFparticle K0\r
+  Float_t               fLcutCosPoint[2];  // cos of the pointing angle [min, max]\r
+  Float_t               fLcutDCA[2];       // DCA between the daughter tracks [min, max]\r
+  Float_t               fLcutVertexR[2];   // radius of the decay point [min, max]\r
+  Float_t               fLcutInvMass[2];   // invariant mass window\r
+  \r
+  \r
+  ClassDef(AliESDv0KineCuts, 0);\r
+\r
+};\r
+\r
+#endif\r
index 084569de7df88f389c4fc2f20c98c9c1be8effc7..ae19bee65832d01266bc8dbe1121ca03e64fd82c 100644 (file)
@@ -25,7 +25,7 @@
 # SHLIBS - Shared Libraries and objects for linking (Executables only)           #
 #--------------------------------------------------------------------------------#
 
-set ( SRCS     AliAnalysisTaskSE.cxx AliAnalysisTaskME.cxx AliAnalysisTaskESDfilter.cxx AliAnalysisTaskMCParticleFilter.cxx AliKineTrackCuts.cxx AliESDtrackCuts.cxx  AliESDpidCuts.cxx AliESDv0Cuts.cxx AliEventPoolOTF.cxx AliEventPoolLoop.cxx AliEventPoolSparse.cxx AliAnalysisTaskTagCreator.cxx AliMultiEventInputHandler.cxx AliTriggerAnalysis.cxx AliPhysicsSelection.cxx AliBackgroundSelection.cxx AliPhysicsSelectionTask.cxx AliAnalysisFilter.cxx AliAnalysisCuts.cxx AliCollisionNormalization.cxx AliCollisionNormalizationTask.cxx AliCentralitySelectionTask.cxx AliAnalysisTaskAODCentralityMaker.cxx AliAnalysisTaskStat.cxx AliMultiInputEventHandler.cxx)
+set ( SRCS     AliAnalysisTaskSE.cxx AliAnalysisTaskME.cxx AliAnalysisTaskESDfilter.cxx AliAnalysisTaskMCParticleFilter.cxx AliKineTrackCuts.cxx AliESDtrackCuts.cxx  AliESDpidCuts.cxx AliESDv0Cuts.cxx AliEventPoolOTF.cxx AliEventPoolLoop.cxx AliEventPoolSparse.cxx AliAnalysisTaskTagCreator.cxx AliMultiEventInputHandler.cxx AliTriggerAnalysis.cxx AliPhysicsSelection.cxx AliBackgroundSelection.cxx AliPhysicsSelectionTask.cxx AliAnalysisFilter.cxx AliAnalysisCuts.cxx AliCollisionNormalization.cxx AliCollisionNormalizationTask.cxx AliCentralitySelectionTask.cxx AliAnalysisTaskAODCentralityMaker.cxx AliAnalysisTaskStat.cxx AliMultiInputEventHandler.cxx AliESDv0KineCuts.cxx)
 
 if( ROOTHASALIEN STREQUAL "yes")