]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PWG2/RESONANCES/AliRsnAnalysisPhi7TeV.cxx
fixed sig.segv
[u/mrichter/AliRoot.git] / PWG2 / RESONANCES / AliRsnAnalysisPhi7TeV.cxx
index 349b80c9a0482aab1d8dae30511b1b6b2bc45e2f..1ca7fd11d82ffcb33e9483228530ce24dc0f15a7 100644 (file)
@@ -5,6 +5,7 @@
 //
 
 #include "Riostream.h"
+#include <iomanip>
 
 #include "TH1.h"
 #include "TTree.h"
@@ -22,6 +23,7 @@
 #include "AliTOFT0maker.h"
 #include "AliTOFcalib.h"
 #include "AliCDBManager.h"
+#include "AliITSPIDResponse.h"
 
 #include "AliRsnAnalysisPhi7TeV.h"
 
 AliRsnAnalysisPhi7TeV::AliRsnAnalysisPhi7TeV(const char *name) :
   AliAnalysisTaskSE(name),
   fUseMC(kFALSE),
+  fCheckITS(kTRUE),
+  fCheckTPC(kTRUE),
+  fCheckTOF(kTRUE),
   fPDG(0),
+  fCh(0),
   fIM(0.0),
   fPt(0.0),
   fY(0.0),
   fEta(0.0),
-  fMaxDCAr(1E6),
-  fMaxDCAz(1E6),
-  fMaxChi2(1E6),
-  fMinNTPC(0),
+  fMaxVz(1E6),
+  fMaxITSband(1E6),
+  fTPCpLimit(0.35),
   fMinTPCband(-1E6),
   fMaxTPCband( 1E6),
   fRsnTreeComp(0x0),
   fRsnTreeTrue(0x0),
   fOutList(0x0),
   fHEvents(0x0),
-  fHCuts(0x0),
+  fESDtrackCutsTPC(),
+  fESDtrackCutsITS(),
   fESDpid(0x0),
   fTOFmaker(0x0),
   fTOFcalib(0x0),
@@ -68,22 +74,26 @@ AliRsnAnalysisPhi7TeV::AliRsnAnalysisPhi7TeV(const char *name) :
 AliRsnAnalysisPhi7TeV::AliRsnAnalysisPhi7TeV(const AliRsnAnalysisPhi7TeV& copy) :
   AliAnalysisTaskSE(copy),
   fUseMC(copy.fUseMC),
+  fCheckITS(copy.fCheckITS),
+  fCheckTPC(copy.fCheckTPC),
+  fCheckTOF(copy.fCheckTOF),
   fPDG(0),
+  fCh(0),
   fIM(0.0),
   fPt(0.0),
   fY(0.0),
   fEta(0.0),
-  fMaxDCAr(copy.fMaxDCAr),
-  fMaxDCAz(copy.fMaxDCAz),
-  fMaxChi2(copy.fMaxChi2),
-  fMinNTPC(copy.fMinNTPC),
+  fMaxVz(copy.fMaxVz),
+  fMaxITSband(copy.fMaxITSband),
+  fTPCpLimit(copy.fTPCpLimit),
   fMinTPCband(copy.fMinTPCband),
   fMaxTPCband(copy.fMaxTPCband),
   fRsnTreeComp(0x0),
   fRsnTreeTrue(0x0),
   fOutList(0x0),
   fHEvents(0x0),
-  fHCuts(0x0),
+  fESDtrackCutsTPC(copy.fESDtrackCutsTPC),
+  fESDtrackCutsITS(copy.fESDtrackCutsITS),
   fESDpid(0x0),
   fTOFmaker(0x0),
   fTOFcalib(0x0),
@@ -106,15 +116,20 @@ AliRsnAnalysisPhi7TeV& AliRsnAnalysisPhi7TeV::operator=(const AliRsnAnalysisPhi7
 //
 
   fUseMC = copy.fUseMC;
+  fCheckITS = copy.fCheckITS;
+  fCheckTPC = copy.fCheckTPC;
+  fCheckTOF = copy.fCheckTOF;
 
-  fMaxDCAr = copy.fMaxDCAr;
-  fMaxDCAz = copy.fMaxDCAz;
-  fMaxChi2 = copy.fMaxChi2;
-  fMinNTPC = copy.fMinNTPC;
-
+  fMaxVz   = copy.fMaxVz;
+  fMaxITSband = copy.fMaxITSband;
+  
+  fTPCpLimit  = copy.fTPCpLimit;
   fMinTPCband = copy.fMinTPCband;
   fMaxTPCband = copy.fMaxTPCband;
   
+  fESDtrackCutsTPC = copy.fESDtrackCutsTPC;
+  fESDtrackCutsITS = copy.fESDtrackCutsITS;
+  
   fTOFcalibrateESD = copy.fTOFcalibrateESD;
   fTOFcorrectTExp = copy.fTOFcorrectTExp;
   fTOFuseT0 = copy.fTOFuseT0;
@@ -134,7 +149,6 @@ AliRsnAnalysisPhi7TeV::~AliRsnAnalysisPhi7TeV()
   if (fRsnTreeComp) delete fRsnTreeComp;
   if (fRsnTreeTrue) delete fRsnTreeTrue;
   if (fHEvents)     delete fHEvents;
-  if (fHCuts)       delete fHCuts;
   if (fESDpid)      delete fESDpid;
 }
 
@@ -161,11 +175,13 @@ void AliRsnAnalysisPhi7TeV::UserCreateOutputObjects()
   OpenFile(1);
   fRsnTreeComp = new TTree("rsnTree", "Pairs");
 
-  fRsnTreeComp->Branch("pdg", &fPDG, "pdg/S");
-  fRsnTreeComp->Branch("im" , &fIM , "im/F" );
-  fRsnTreeComp->Branch("y"  , &fY  , "y/F"  );
-  fRsnTreeComp->Branch("pt" , &fPt , "pt/F" );
-  fRsnTreeComp->Branch("eta", &fEta, "eta/F");
+  fRsnTreeComp->Branch("pdg", &fPDG, "pdg/S"   );
+  fRsnTreeComp->Branch("ch" , &fCh , "ch/S"    );
+  fRsnTreeComp->Branch("im" , &fIM , "im/F"    );
+  fRsnTreeComp->Branch("y"  , &fY  , "y/F"     );
+  fRsnTreeComp->Branch("pt" , &fPt , "pt/F"    );
+  fRsnTreeComp->Branch("eta", &fEta, "eta/F"   );
+  fRsnTreeComp->Branch("its", &fITS, "its[2]/S");
 
   OpenFile(2);
   fRsnTreeTrue = new TTree("rsnTrue", "True pairs");
@@ -176,22 +192,28 @@ void AliRsnAnalysisPhi7TeV::UserCreateOutputObjects()
   fRsnTreeTrue->Branch("eta", &fEta, "eta/F");
 
   OpenFile(3);
-  fOutList = new TList;
-  fHEvents = new TH1I("hEvents", "Event details", 4, 0, 4);
-  fHCuts   = new TH1I("hCuts", "Cuts not passed", 11, 0, 11);
-  fHCuts->GetXaxis()->SetBinLabel( 1, "Flags");
-  fHCuts->GetXaxis()->SetBinLabel( 2, "No TPC inner");
-  fHCuts->GetXaxis()->SetBinLabel( 3, "Kink daughter");
-  fHCuts->GetXaxis()->SetBinLabel( 4, "Few clusters in TPC");
-  fHCuts->GetXaxis()->SetBinLabel( 5, "Large #chi^{2}");
-  fHCuts->GetXaxis()->SetBinLabel( 6, "No SPD clusters");
-  fHCuts->GetXaxis()->SetBinLabel( 7, "Failed revert to vertex");
-  fHCuts->GetXaxis()->SetBinLabel( 8, "Too large DCA");
-  fHCuts->GetXaxis()->SetBinLabel( 9, "Failed TPC PID");
-  fHCuts->GetXaxis()->SetBinLabel(10, "Failed TOF PID");
-  fHCuts->GetXaxis()->SetBinLabel(11, "Track OK");
+  fOutList    = new TList;
+  fHEvents    = new TH1I("hEvents", "Event details", 5, 0, 5);
+  fVertexX[0] = new TH1F("hVertexTracksX", "X position of primary vertex (tracks)", 200,  -2,  2);
+  fVertexY[0] = new TH1F("hVertexTracksY", "Y position of primary vertex (tracks)", 200,  -2,  2);
+  fVertexZ[0] = new TH1F("hVertexTracksZ", "Z position of primary vertex (tracks)", 400, -40, 40);
+  fVertexX[1] = new TH1F("hVertexSPDX", "X position of primary vertex (SPD)", 200,  -2,  2);
+  fVertexY[1] = new TH1F("hVertexSPDY", "Y position of primary vertex (SPD)", 200,  -2,  2);
+  fVertexZ[1] = new TH1F("hVertexSPDZ", "Z position of primary vertex (SPD)", 400, -40, 40);
+  
+  fHEvents->GetXaxis()->SetBinLabel(1, "Good vertex with tracks");
+  fHEvents->GetXaxis()->SetBinLabel(2, "Good vertex with SPD");
+  fHEvents->GetXaxis()->SetBinLabel(3, "Far vertex with tracks");
+  fHEvents->GetXaxis()->SetBinLabel(4, "Far vertex with SPD");
+  fHEvents->GetXaxis()->SetBinLabel(5, "No good vertex");
+
   fOutList->Add(fHEvents);
-  fOutList->Add(fHCuts);
+  fOutList->Add(fVertexX[0]);
+  fOutList->Add(fVertexY[0]);
+  fOutList->Add(fVertexZ[0]);
+  fOutList->Add(fVertexX[1]);
+  fOutList->Add(fVertexY[1]);
+  fOutList->Add(fVertexZ[1]);
 }
 
 //__________________________________________________________________________________________________
@@ -212,46 +234,19 @@ void AliRsnAnalysisPhi7TeV::UserExec(Option_t *)
   // retrieve ESD event and related stack (if available)
   AliESDEvent *esd   = dynamic_cast<AliESDEvent*>(fInputEvent);
   AliStack    *stack = (fMCEvent ? fMCEvent->Stack() : 0x0);
-  //cout << "NTRACKS: " << esd->GetNumberOfTracks() << endl;
   
-  // get the best primary vertex:
-  // first try the one with tracks
-  Int_t type = 0;
-  const AliESDVertex *v = esd->GetPrimaryVertexTracks();
-  //cout << "[ev " << evNum << "] vertex tracks: " << v << " contrib = " << v->GetNContributors() << " -- status = " << v->GetStatus() << endl;
-  if(v->GetNContributors() < 1)
-  {
-    // if not good, try SPD vertex
-    type = 1;
-    v = esd->GetPrimaryVertexSPD();
-    //cout << "[ev " << evNum << "] vertex SPD: " << v << " contrib = " << v->GetNContributors() << " -- status = " << v->GetStatus() << endl;
-    
-    // if this is not good skip this event
-    if (v->GetNContributors() < 1)
-    {
-      fHEvents->Fill(3);
-      PostData(3, fOutList);
-      return;
-    }
-  }
-
-  // if the Z position is larger than 10, skip this event
-  //cout << "[ev " << evNum << "] vertex Z = " << v->GetZv() << endl;
-  if (TMath::Abs(v->GetZv()) > 10.0)
+  // check the event
+  Int_t eval = EventEval(esd);
+  fHEvents->Fill(eval);
+  
+  // if the event is good for analysis, process it
+  if (eval == kGoodTracksPrimaryVertex || eval == kGoodSPDPrimaryVertex)
   {
-    fHEvents->Fill(2);
-    PostData(3, fOutList);
-    return;
+    ProcessESD(esd, stack);
+    ProcessMC(stack);
   }
   
-  //cout << "EVENT " << evNum << " is OK" << endl;
-
-  // use the type to fill the histogram
-  fHEvents->Fill(type);
-
-  ProcessESD(esd, v, stack);
-  ProcessMC(stack);
-
+  // update histogram container
   PostData(3, fOutList);
 }
 
@@ -263,22 +258,91 @@ void AliRsnAnalysisPhi7TeV::Terminate(Option_t *)
 //
 }
 
+//__________________________________________________________________________________________________
+Int_t AliRsnAnalysisPhi7TeV::EventEval(AliESDEvent *esd)
+{
+//
+// Checks if the event is good for analysis.
+// Returns one of the flag values defined in the header
+//
+
+  static Int_t evNum = 0;
+  evNum++;
+  
+  // get the best primary vertex:
+  // first try the one with tracks
+  const AliESDVertex *vTrk  = esd->GetPrimaryVertexTracks();
+  const AliESDVertex *vSPD  = esd->GetPrimaryVertexSPD();
+  Double_t            vzTrk = 1000.0;
+  Double_t            vzSPD = 1000.0;
+  Int_t               ncTrk = -1;
+  Int_t               ncSPD = -1;
+  if (vTrk) ncTrk = (Int_t)vTrk->GetNContributors();
+  if (vSPD) ncSPD = (Int_t)vSPD->GetNContributors();
+  if (vTrk) vzTrk = TMath::Abs(vTrk->GetZv());
+  if (vSPD) vzSPD = TMath::Abs(vSPD->GetZv());
+  if(vTrk && ncTrk > 0)
+  {
+    // fill the histograms
+    fVertexX[0]->Fill(vTrk->GetXv());
+    fVertexY[0]->Fill(vTrk->GetYv());
+    fVertexZ[0]->Fill(vTrk->GetZv());
+    
+    // check VZ position
+    if (vzTrk <= fMaxVz)
+      return kGoodTracksPrimaryVertex;
+    else
+      return kFarTracksPrimaryVertex;
+  }
+  else if (vSPD && ncSPD > 0)
+  {
+    // fill the histograms
+    fVertexX[1]->Fill(vSPD->GetXv());
+    fVertexY[1]->Fill(vSPD->GetYv());
+    fVertexZ[1]->Fill(vSPD->GetZv());
+    
+    // check VZ position
+    if (vzSPD <= fMaxVz)
+      return kGoodSPDPrimaryVertex;
+    else
+      return kFarSPDPrimaryVertex;
+  }
+  else
+    return kNoGoodPrimaryVertex;
+}
+
 //__________________________________________________________________________________________________
 void AliRsnAnalysisPhi7TeV::ProcessESD
-(AliESDEvent *esd, const AliESDVertex *v, AliStack *stack)
+(AliESDEvent *esd, AliStack *stack)
 {
 //
 // This function works with the ESD object
 //
 
+  static Int_t lastRun = -1;
+
+  // ITS stuff #1 create the response function
+  Bool_t isMC = (stack != 0x0);
+  AliITSPIDResponse itsrsp(isMC);
+
   // TOF stuff #1: init OCDB
   Int_t run = esd->GetRunNumber();
-  AliCDBManager *cdb = AliCDBManager::Instance();
-  cdb->SetDefaultStorage("raw://");
-  cdb->SetRun(run);
+  if (run != lastRun)
+  {
+    cout << "Run = " << run << " -- LAST = " << lastRun << endl;
+    lastRun = run;
+    AliCDBManager *cdb = AliCDBManager::Instance();
+    cdb->SetDefaultStorage("raw://");
+    cdb->SetRun(run);
+    fTOFcalib->SetCorrectTExp(fTOFcorrectTExp);
+    fTOFcalib->Init();
+  }
+  //AliCDBManager *cdb = AliCDBManager::Instance();
+  //cdb->SetDefaultStorage("raw://");
+  //cdb->SetRun(run);
   // TOF stuff #2: init calibration
-  fTOFcalib->SetCorrectTExp(fTOFcorrectTExp);
-  fTOFcalib->Init();
+  //fTOFcalib->SetCorrectTExp(fTOFcorrectTExp);
+  //fTOFcalib->Init();
   // TOF stuff #3: calibrate
   if (fTOFcalibrateESD) fTOFcalib->CalibrateESD(esd);
   if (fTOFtuneMC) fTOFmaker->TuneForMC(esd);
@@ -288,116 +352,185 @@ void AliRsnAnalysisPhi7TeV::ProcessESD
     fTOFmaker->ApplyT0TOF(esd);
     fESDpid->MakePID(esd, kFALSE, 0.);
   }
+  // TOF stuff #4: define fixed function for compatibility range
+  Double_t a1 = 0.01, a2 = -0.03;
+  Double_t b1 = 0.25, b2 =  0.25;
+  Double_t c1 = 0.05, c2 = -0.03;
+  Double_t ymax, ymin;
 
   // prepare to look on all tracks to select the ones
   // which pass all the cuts
   Int_t   ntracks = esd->GetNumberOfTracks();
   TArrayI pos(ntracks);
   TArrayI neg(ntracks);
+  TArrayI itspos(ntracks);
+  TArrayI itsneg(ntracks);
   
-  // define fixed functions for TOF compatibility range
-  Double_t a1 = 0.01, a2 = -0.03;
-  Double_t b1 = 0.25, b2 =  0.25;
-  Double_t c1 = 0.05, c2 = -0.03;
-  Double_t ymax, ymin;
-
   // loop on all tracks
-  Int_t    i, icut, charge, nSPD, npos = 0, nneg = 0;
-  Float_t  chi2, b[2], bCov[3];
-  Double_t mom, tpcNSigma, tpcMaxNSigma, tofTime, tofSigma, tofRef, tofRel, times[10];
-  Bool_t   okTOF;
+  ULong_t  status;
+  Int_t    i, k, charge, npos = 0, nneg = 0, nITS;
+  Double_t times[10], tpcNSigma, tpcMaxNSigma, itsSignal, itsNSigma, mom, tofTime, tofSigma, tofRef, tofDiff, tofRel;
+  Bool_t   okQuality, okTOF, okTPC, okITS, okTrack, isTPC, isITSSA;
+  UChar_t  itsCluMap;
   for (i = 0; i < ntracks; i++)
   {
     AliESDtrack *track = esd->GetTrack(i);
-    if (!track) {fHCuts->Fill(icut); continue;}
-
-    // skip if it has not the required flags
-    icut = 0;
-    if (!track->IsOn(AliESDtrack::kTPCin)) {fHCuts->Fill(icut); continue;}
-    if (!track->IsOn(AliESDtrack::kTPCrefit)) {fHCuts->Fill(icut); continue;}
-    if (!track->IsOn(AliESDtrack::kITSrefit)) {fHCuts->Fill(icut); continue;}
-
-    // skip if it has not the TPC inner wall projection
-    icut = 1;
-    if (!track->GetInnerParam()) {fHCuts->Fill(icut); continue;}
+    if (!track) continue;
+    
+    // get commonly used variables
+    status  = (ULong_t)track->GetStatus();
+    mom     = track->P();
+    isTPC   = ((status & AliESDtrack::kTPCin)  != 0);
+    isITSSA = ((status & AliESDtrack::kTPCin)  == 0 && (status & AliESDtrack::kITSrefit) != 0 && (status & AliESDtrack::kITSpureSA) == 0 && (status & AliESDtrack::kITSpid) != 0);
+    //cout << isTPC << ' ' << isITSSA << endl;
+    
+    // accept only tracks which are TPC+ITS or ITS standalone
+    if (!isTPC && !isITSSA) continue;
     
-    // skip kink daughters
-    icut = 2;
-    if ((Int_t)track->GetKinkIndex(0) > 0) {fHCuts->Fill(icut); continue;}
-
-    // check clusters in TPC
-    icut = 3;
-    if (track->GetTPCclusters(0) < fMinNTPC) {fHCuts->Fill(icut); continue;}
-
-    // check chi2
-    icut = 4;
-    chi2  = (Float_t)track->GetTPCchi2();
-    chi2 /= (Float_t)track->GetTPCclusters(0);
-    if (chi2 > fMaxChi2) {fHCuts->Fill(icut); continue;}
-
-    // check that has at least 1 SPD cluster
-    icut = 5;
-    nSPD = 0;
-    if (track->HasPointOnITSLayer(0)) nSPD++;
-    if (track->HasPointOnITSLayer(1)) nSPD++;
-    if (nSPD < 1) {fHCuts->Fill(icut); continue;}
-
-    // check primary by reverting to vertex
-    // and checking DCA
-    icut = 6;
-    if (!track->RelateToVertex(v, esd->GetMagneticField(), kVeryBig)) {fHCuts->Fill(icut); continue;}
-    icut = 7;
-    track->GetImpactParameters(b, bCov);
-    if (b[0] > fMaxDCAr) {fHCuts->Fill(icut); continue;}
-    if (b[1] > fMaxDCAz) {fHCuts->Fill(icut); continue;}
-
-    // check TPC dE/dx
-    icut = 8;
-    //cout << "TPC SIGMA: " << fESDpid->NumberOfSigmasTPC(track, AliPID::kKaon) << endl;
-    tpcNSigma = TMath::Abs(fESDpid->NumberOfSigmasTPC(track, AliPID::kKaon));
-    if (track->GetInnerParam()->P() > fTPCpLimit) tpcMaxNSigma = fMinTPCband; else tpcMaxNSigma = fMaxTPCband;
-    if (tpcNSigma > tpcMaxNSigma) {fHCuts->Fill(icut); continue;}
-
-    // if possible, check TOF
-    icut = 9;
-    okTOF = kTRUE;
-    if (track->IsOn(AliESDtrack::kTOFout | AliESDtrack::kTIME))
+    // define selection properties depending on track type
+    // it track is standard TPC+ITS+TOF track, check standard cuts and TOF
+    // if the track is an ITS standalone, check its specific cuts only
+    okTrack = kTRUE;
+    
+    if (isTPC)
     {
-      mom = track->P();
-      if (mom <= 0.26)
+      // check standard ESD cuts
+      okQuality = fESDtrackCutsTPC.IsSelected(track);
+      //cout << "GLOBAL -- quality = " << (okQuality ? "GOOD" : "BAD") << endl;
+      if (!okQuality) continue;
+      
+      // check TPC dE/dx
+      if (fCheckTPC)
+      {
+        tpcNSigma = TMath::Abs(fESDpid->NumberOfSigmasTPC(track, AliPID::kKaon));
+        if (track->GetInnerParam()->P() > fTPCpLimit) tpcMaxNSigma = fMinTPCband; else tpcMaxNSigma = fMaxTPCband;
+        okTPC = (tpcNSigma <= tpcMaxNSigma);
+        //cout << "ALT -- TPC    -- nsigma = " << tpcNSigma << ", max = " << tpcMaxNSigma << " --> " << (okTPC ? "OK" : "FAILED") << endl;
+        //cout << "ALTTPC -- " << fTPCpar[0] << ' ' << fTPCpar[1] << ' ' << fTPCpar[2] << ' ' << fTPCpar[3] << ' ' << fTPCpar[4] << endl;
+      }
+      else
+      {
+        okTPC = kTRUE;
+      }
+      
+      // check TOF (only if momentum is large than function asymptote and flags are OK)
+      if (fCheckTOF)
+      {
+        if (((status & AliESDtrack::kTOFout) != 0) && ((status & AliESDtrack::kTIME) != 0) && mom > TMath::Max(b1, b2))
+        {
+          track->GetIntegratedTimes(times);
+          tofTime  = (Double_t)track->GetTOFsignal();
+          tofSigma = fTOFmaker->GetExpectedSigma(mom, times[AliPID::kKaon], AliPID::ParticleMass(AliPID::kKaon));
+          tofRef   = times[AliPID::kKaon];
+          if (tofRef > 0.0)
+          {
+            tofDiff  = (tofTime - tofRef);
+            tofRel   = (tofTime - tofRef) / tofRef;
+            ymax     = a1 / (mom - b1) + c1;
+            ymin     = a2 / (mom - b2) + c2;
+            okTOF    = (tofRel >= ymin && tofRel <= ymax);
+            //cout << "TOF    -- diff = " << tofDiff << ", rel diff = " << tofRel << ", range = " << ymin << " to " << ymax << ", sigma = " << tofSigma << " --> " << (okTOF ? "OK" : "FAILED") << endl;
+          }
+          else
+          {
+            okTOF = kTRUE;
+            //cout << "TOF    -- not checked due to ZERO reference time" << endl;
+          }
+        }
+        else
+        {
+          okTOF = kTRUE;
+          //cout << "TOF    -- not checked because TOF pid absent" << endl;
+        }
+      }
+      else
+      {
         okTOF = kTRUE;
+      }
+      
+      okTrack = okQuality && okTPC && okTOF;
+      //cout << "GLOBAL -- overall = " << (okTrack ? "ACCEPTED" : "REJECTED") << endl;
+    }
+    else
+    {
+      // check standard ESD cuts
+      okQuality = fESDtrackCutsITS.IsSelected(track);
+      //cout << "ITSSA  -- quality = " << (okQuality ? "GOOD" : "BAD") << endl;
+      if (!okQuality) continue;
+      
+      // check dE/dx
+      if (fCheckITS)
+      {
+        itsSignal = track->GetITSsignal();
+        itsCluMap = track->GetITSClusterMap();
+        nITS      = 0;
+        for(k = 2; k < 6; k++) if(itsCluMap & (1 << k)) ++nITS;
+        if (nITS < 3) 
+        {
+          okITS = kFALSE;
+          //cout << "ITS    -- not checked due to too few PID clusters" << endl;
+        }
+        else
+        {
+          itsNSigma = itsrsp.GetNumberOfSigmas(mom, itsSignal, AliPID::kKaon, nITS, kTRUE);
+          okITS = (TMath::Abs(itsNSigma) <= fMaxITSband);
+          //cout << "ITS    -- nsigma = " << itsNSigma << ", max = " << fMaxITSband << " --> " << (okITS ? "OK" : "FAILED") << endl;
+        }
+      }
       else
       {
-        track->GetIntegratedTimes(times);
-        tofTime  = (Double_t)track->GetTOFsignal();
-        tofSigma = fTOFmaker->GetExpectedSigma(mom, times[AliPID::kKaon], AliPID::ParticleMass(AliPID::kKaon));
-        tofRef   = times[AliPID::kKaon];
-        tofRel   = (tofTime - tofRef) / tofRef;
-        ymax     = a1 / (mom - b1) + c1;
-        ymin     = a2 / (mom - b2) + c2;
-        okTOF    = (tofRel >= ymin && tofRel <= ymax);
+        okITS = kTRUE;
       }
+      
+      okTrack = okQuality && okITS;
+      //cout << "ITSSA  -- overall = " << (okTrack ? "ACCEPTED" : "REJECTED") << endl;
     }
-    if (!okTOF) {fHCuts->Fill(icut); continue;}
-
-    // if we arrive here, all cuts were passed
-    // and we add the track to one array depending on charge
-    icut = 10;
+    
+    // skip tracks not passing cuts
+    if (!okTrack) continue;
+    
+    // if all checks are passed, add the track index in one of the
+    // charged tracks arrays
     charge = (Int_t)track->Charge();
     if (charge > 0)
-      pos[npos++] = i;
+    {
+      pos[npos] = i;
+      if (isITSSA) itspos[npos] = 1; else itspos[npos] = 0;
+      npos++;
+    }
     else if (charge < 0)
-      neg[nneg++] = i;
-    
-    // fill the bin corresponding to passed cuts
-    fHCuts->Fill(icut);
+    {
+      neg[nneg] = i;
+      if (isITSSA) itsneg[nneg] = 1; else itsneg[nneg] = 0;
+      nneg++;
+    }
   }
   
   // resize arrays accordingly
   pos.Set(npos);
   neg.Set(nneg);
-
-  // loop to compute invariant mass
+  itspos.Set(npos);
+  itsneg.Set(nneg);
+  
+  /*
+  // fill unlike-sign
+  Int_t i1, i2;
+  for (i1 = 0; i1 < npos; i1++)
+    for (i2 = 0; i2 < nneg; i2++)
+      AddEntryFromESD(esd, i1, i2, itspos[i1], itsneg[i2], 0, stack);
+      
+  // fill ++ like-sign
+  for (i1 = 0; i1 < npos; i1++)
+    for (i2 = i1 + 1; i2 < npos; i2++)
+      AddEntryFromESD(esd, i1, i2, itspos[i1], itspos[i2], 1, 0x0);
+      
+  // fill -- like-sign
+  for (i1 = 0; i1 < nneg; i1++)
+    for (i2 = i1 + 1; i2 < nneg; i2++)
+      AddEntryFromESD(esd, i1, i2, itsneg[i1], itsneg[i2], -1, 0x0);
+      */
+      
+  // loop on unlike-sign pairs to compute invariant mass signal
   Int_t           ip, in, lp, ln;
   AliPID          pid;
   Double_t        kmass = pid.ParticleMass(AliPID::kKaon);
@@ -413,7 +546,11 @@ void AliRsnAnalysisPhi7TeV::ProcessESD
 
     for (in = 0; in < nneg; in++)
     {
-      if (pos[ip] == neg[in]) continue;
+      if (pos[ip] == neg[in]) 
+      {
+        AliError("POS = NEG");
+        continue;
+      }
       tn = esd->GetTrack(neg[in]);
       ln = TMath::Abs(tn->GetLabel());
       if (stack) partn = stack->Particle(ln);
@@ -437,11 +574,81 @@ void AliRsnAnalysisPhi7TeV::ProcessESD
       vsum = vp + vn;
       vref.SetXYZM(vsum.X(), vsum.Y(), vsum.Z(), phimass);
 
-      fIM  = (Float_t)vsum.M();
-      fPt  = (Float_t)vsum.Perp();
-      fEta = (Float_t)vsum.Eta();
-      fY   = (Float_t)vref.Rapidity();
+      fCh     = 0;
+      fIM     = (Float_t)vsum.M();
+      fPt     = (Float_t)vsum.Perp();
+      fEta    = (Float_t)vsum.Eta();
+      fY      = (Float_t)vref.Rapidity();
+      fITS[0] = itspos[ip];
+      fITS[1] = itsneg[in];
+
+      //if (fIM < 0.9 || fIM >  1.4) continue;
+      //if (fPt < 0.0 || fPt > 20.0) continue;
+      
+      fRsnTreeComp->Fill();
+    }
+  }
+  
+  // loop on like-sign pairs to compute invariant mass background
+  Int_t           i1, i2;
+  AliESDtrack    *t1 = 0x0, *t2 = 0x0;
+  TLorentzVector  v1, v2;
+  
+  // pos-pos
+  for (i1 = 0; i1 < npos; i1++)
+  {
+    t1 = esd->GetTrack(pos[i1]);
+
+    for (i2 = i1+1; i2 < npos; i2++)
+    {
+      t2 = esd->GetTrack(pos[i2]);
 
+      v1.SetXYZM(t1->Px(), t1->Py(), t1->Pz(), kmass);
+      v2.SetXYZM(t2->Px(), t2->Py(), t2->Pz(), kmass);
+      vsum = v1 + v2;
+      vref.SetXYZM(vsum.X(), vsum.Y(), vsum.Z(), phimass);
+
+      fPDG    = 0;
+      fCh     = 1;
+      fIM     = (Float_t)vsum.M();
+      fPt     = (Float_t)vsum.Perp();
+      fEta    = (Float_t)vsum.Eta();
+      fY      = (Float_t)vref.Rapidity();
+      fITS[0] = itspos[i1];
+      fITS[1] = itspos[i2];
+
+      //if (fIM < 0.9 || fIM >  1.4) continue;
+      //if (fPt < 0.0 || fPt > 20.0) continue;
+      
+      fRsnTreeComp->Fill();
+    }
+  }
+  // neg-neg
+  for (i1 = 0; i1 < nneg; i1++)
+  {
+    t1 = esd->GetTrack(neg[i1]);
+
+    for (i2 = i1+1; i2 < nneg; i2++)
+    {
+      t2 = esd->GetTrack(neg[i2]);
+
+      v1.SetXYZM(t1->Px(), t1->Py(), t1->Pz(), kmass);
+      v2.SetXYZM(t2->Px(), t2->Py(), t2->Pz(), kmass);
+      vsum = v1 + v2;
+      vref.SetXYZM(vsum.X(), vsum.Y(), vsum.Z(), phimass);
+
+      fPDG    = 0;
+      fCh     = -1;
+      fIM     = (Float_t)vsum.M();
+      fPt     = (Float_t)vsum.Perp();
+      fEta    = (Float_t)vsum.Eta();
+      fY      = (Float_t)vref.Rapidity();
+      fITS[0] = itsneg[i1];
+      fITS[1] = itsneg[i2];
+
+      //if (fIM < 0.9 || fIM >  1.4) continue;
+      //if (fPt < 0.0 || fPt > 20.0) continue;
+      
       fRsnTreeComp->Fill();
     }
   }
@@ -449,6 +656,63 @@ void AliRsnAnalysisPhi7TeV::ProcessESD
   PostData(1, fRsnTreeComp);
 }
 
+//__________________________________________________________________________________________________
+void AliRsnAnalysisPhi7TeV::AddEntryFromESD(AliESDEvent *esd, Int_t i1, Int_t i2, Int_t its1, Int_t its2, Short_t charge, AliStack *stack)
+{
+//
+// Add an entry to the output TTree computed from two tracks in the ESD
+//
+
+  // loop on unlike-sign pairs to compute invariant mass signal
+  AliPID          pid;
+  Double_t        kmass = pid.ParticleMass(AliPID::kKaon);
+  Double_t        phimass = 1.019455;
+  TLorentzVector  v1, v2, vsum, vref;
+  
+  AliESDtrack *t1 = esd->GetTrack(i1);
+  AliESDtrack *t2 = esd->GetTrack(i2);
+
+  v1.SetXYZM(t1->Px(), t1->Py(), t1->Pz(), kmass);
+  v2.SetXYZM(t2->Px(), t2->Py(), t2->Pz(), kmass);
+  vsum = v1 + v2;
+  vref.SetXYZM(vsum.X(), vsum.Y(), vsum.Z(), phimass);
+  
+  // if stack is present, search for true pair
+  fPDG = 0;
+  Int_t l1 = TMath::Abs(t1->GetLabel());
+  Int_t l2 = TMath::Abs(t2->GetLabel());
+  if (stack) 
+  {
+    TParticle *part1 = stack->Particle(l1);
+    TParticle *part2 = stack->Particle(l2);
+    if (part1 && part2)
+    {
+      if (part1->GetFirstMother() == part2->GetFirstMother())
+      {
+        if (part1->GetFirstMother() > 0)
+        {
+          TParticle *mum = stack->Particle(part1->GetFirstMother());
+          fPDG = mum->GetPdgCode();
+        }
+      }
+    }
+  }
+  
+  fPDG = TMath::Abs(fPDG);
+  fCh     = charge;
+  fIM     = (Float_t)vsum.M();
+  fPt     = (Float_t)vsum.Perp();
+  fEta    = (Float_t)vsum.Eta();
+  fY      = (Float_t)vref.Rapidity();
+  fITS[0] = its1;
+  fITS[1] = its2;
+
+  //if (fIM < 0.9 || fIM >  1.4) return;
+  //if (fPt < 0.0 || fPt > 20.0) return;
+      
+  fRsnTreeComp->Fill();
+}
+  
 //__________________________________________________________________________________________________
 void AliRsnAnalysisPhi7TeV::ProcessMC(AliStack *stack)
 {