1 /**************************************************************************
2 * Copyright(c) 1998-2010, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 /////////////////////////////////////////////////////////////
18 // Class for cuts on AOD reconstructed D0->Kpi
20 // Author: A.Dainese, andrea.dainese@pd.infn.it
21 /////////////////////////////////////////////////////////////
23 #include <TDatabasePDG.h>
24 #include <Riostream.h>
26 #include "AliRDHFCutsD0toKpi.h"
27 #include "AliAODRecoDecayHF2Prong.h"
28 #include "AliAODTrack.h"
29 #include "AliESDtrack.h"
30 #include "AliAODPid.h"
31 #include "AliTPCPIDResponse.h"
32 #include "AliAODVertex.h"
34 ClassImp(AliRDHFCutsD0toKpi)
36 //--------------------------------------------------------------------------
37 AliRDHFCutsD0toKpi::AliRDHFCutsD0toKpi(const char* name) :
39 fRemoveDaughtersFromPrimary(kFALSE),
40 fUseSpecialCuts(kFALSE)
43 // Default Constructor
47 TString varNames[9]={"inv. mass [GeV]",
56 Bool_t isUpperCut[9]={kTRUE,
65 SetVarNames(nvars,varNames,isUpperCut);
66 Bool_t forOpt[9]={kFALSE,
75 SetVarsForOpt(4,forOpt);
76 Float_t limits[2]={0,999999999.};
80 //--------------------------------------------------------------------------
81 AliRDHFCutsD0toKpi::AliRDHFCutsD0toKpi(const AliRDHFCutsD0toKpi &source) :
83 fRemoveDaughtersFromPrimary(source.fRemoveDaughtersFromPrimary),
84 fUseSpecialCuts(source.fUseSpecialCuts)
91 //--------------------------------------------------------------------------
92 AliRDHFCutsD0toKpi &AliRDHFCutsD0toKpi::operator=(const AliRDHFCutsD0toKpi &source)
95 // assignment operator
97 if(&source == this) return *this;
99 AliRDHFCuts::operator=(source);
100 fRemoveDaughtersFromPrimary=source.fRemoveDaughtersFromPrimary;
101 fUseSpecialCuts=source.fUseSpecialCuts;
107 //---------------------------------------------------------------------------
108 void AliRDHFCutsD0toKpi::GetCutVarsForOpt(AliAODRecoDecayHF *d,Float_t *vars,Int_t nvars,Int_t *pdgdaughters) {
110 // Fills in vars the values of the variables
113 if(nvars!=fnVarsForOpt) {
114 printf("AliRDHFCutsD0toKpi::GetCutsVarsForOpt: wrong number of variables\n");
118 AliAODRecoDecayHF2Prong *dd = (AliAODRecoDecayHF2Prong*)d;
123 if(TMath::Abs(pdgdaughters[0])==211) {
124 vars[iter]=dd->InvMassD0();
126 vars[iter]=dd->InvMassD0bar();
131 vars[iter]=dd->GetDCA();
135 if(TMath::Abs(pdgdaughters[0])==211) {
136 vars[iter] = dd->CosThetaStarD0();
138 vars[iter] = dd->CosThetaStarD0bar();
143 if(TMath::Abs(pdgdaughters[0])==321) {
144 vars[iter]=dd->PtProng(0);
147 vars[iter]=dd->PtProng(1);
152 if(TMath::Abs(pdgdaughters[0])==211) {
153 vars[iter]=dd->PtProng(0);
156 vars[iter]=dd->PtProng(1);
161 if(TMath::Abs(pdgdaughters[0])==321) {
162 vars[iter]=dd->Getd0Prong(0);
165 vars[iter]=dd->Getd0Prong(1);
170 if(TMath::Abs(pdgdaughters[0])==211) {
171 vars[iter]=dd->Getd0Prong(0);
174 vars[iter]=dd->Getd0Prong(1);
179 vars[iter]= dd->Prodd0d0();
183 vars[iter]=dd->CosPointingAngle();
188 //---------------------------------------------------------------------------
189 Int_t AliRDHFCutsD0toKpi::IsSelected(TObject* obj,Int_t selectionLevel,AliAODEvent* aod) {
195 cout<<"Cut matrice not inizialized. Exit..."<<endl;
199 AliAODRecoDecayHF2Prong* d=(AliAODRecoDecayHF2Prong*)obj;
202 cout<<"AliAODRecoDecayHF2Prong null"<<endl;
206 // selection on daughter tracks
207 if(selectionLevel==AliRDHFCuts::kAll ||
208 selectionLevel==AliRDHFCuts::kTracks) {
209 if(!AreDaughtersSelected(d)) return 0;
214 // returnvalue: 0 not sel, 1 only D0, 2 only D0bar, 3 both
215 Int_t returnvaluePID=3;
216 Int_t returnvalueCuts=3;
219 if(selectionLevel==AliRDHFCuts::kAll ||
220 selectionLevel==AliRDHFCuts::kCandidate ||
221 selectionLevel==AliRDHFCuts::kPID) {
222 returnvaluePID = IsSelectedPID(d);
227 // selection on candidate
228 if(selectionLevel==AliRDHFCuts::kAll ||
229 selectionLevel==AliRDHFCuts::kCandidate) {
231 //recalculate vertex w/o daughters
232 AliAODVertex *origownvtx=0x0;
233 AliAODVertex *recvtx=0x0;
234 if(aod && fRemoveDaughtersFromPrimary) {
235 if(d->GetOwnPrimaryVtx()) origownvtx=new AliAODVertex(*d->GetOwnPrimaryVtx());
236 recvtx=d->RemoveDaughtersFromPrimaryVtx(aod);
238 AliDebug(2,"Removal of daughter tracks failed");
239 //recvtx=d->GetPrimaryVtx();
246 //set recalculed primary vertex
247 d->SetOwnPrimaryVtx(recvtx);
248 delete recvtx; recvtx=NULL;
254 Int_t okD0=0,okD0bar=0;
256 Int_t ptbin=PtBin(pt);
259 d->SetOwnPrimaryVtx(origownvtx);
263 else d->UnsetOwnPrimaryVtx();
266 Double_t mD0,mD0bar,ctsD0,ctsD0bar;
269 Double_t mD0PDG = TDatabasePDG::Instance()->GetParticle(421)->Mass();
271 if(d->PtProng(1) < fCutsRD[GetGlobalIndex(3,ptbin)] || d->PtProng(0) < fCutsRD[GetGlobalIndex(4,ptbin)]) okD0 = 0;
272 if(d->PtProng(0) < fCutsRD[GetGlobalIndex(3,ptbin)] || d->PtProng(1) < fCutsRD[GetGlobalIndex(4,ptbin)]) okD0bar = 0;
273 if(!okD0 && !okD0bar) returnvalueCuts=0;
276 if(TMath::Abs(d->Getd0Prong(1)) > fCutsRD[GetGlobalIndex(5,ptbin)] ||
277 TMath::Abs(d->Getd0Prong(0)) > fCutsRD[GetGlobalIndex(6,ptbin)]) okD0 = 0;
278 if(TMath::Abs(d->Getd0Prong(0)) > fCutsRD[GetGlobalIndex(6,ptbin)] ||
279 TMath::Abs(d->Getd0Prong(1)) > fCutsRD[GetGlobalIndex(5,ptbin)]) okD0bar = 0;
280 if(!okD0 && !okD0bar) returnvalueCuts=0;
282 if(d->GetDCA() > fCutsRD[GetGlobalIndex(1,ptbin)]) returnvalueCuts=0;
284 d->InvMassD0(mD0,mD0bar);
285 if(TMath::Abs(mD0-mD0PDG) > fCutsRD[GetGlobalIndex(0,ptbin)]) okD0 = 0;
286 if(TMath::Abs(mD0bar-mD0PDG) > fCutsRD[GetGlobalIndex(0,ptbin)]) okD0bar = 0;
287 if(!okD0 && !okD0bar) returnvalueCuts=0;
289 d->CosThetaStarD0(ctsD0,ctsD0bar);
290 if(TMath::Abs(ctsD0) > fCutsRD[GetGlobalIndex(2,ptbin)]) okD0 = 0;
291 if(TMath::Abs(ctsD0bar) > fCutsRD[GetGlobalIndex(2,ptbin)]) okD0bar = 0;
292 if(!okD0 && !okD0bar) returnvalueCuts=0;
294 if(d->Prodd0d0() > fCutsRD[GetGlobalIndex(7,ptbin)]) returnvalueCuts=0;
296 if(d->CosPointingAngle() < fCutsRD[GetGlobalIndex(8,ptbin)]) returnvalueCuts=0;
298 if (returnvalueCuts!=0) {
299 if (okD0) returnvalueCuts=1; //cuts passed as D0
300 if (okD0bar) returnvalueCuts=2; //cuts passed as D0bar
301 if (okD0 && okD0bar) returnvalueCuts=3; //cuts passed as D0 and D0bar
306 if(fUseSpecialCuts) special=IsSelectedSpecialCuts(d);
307 if(!special) returnvalueCuts=0;
309 // unset recalculated primary vertex when not needed any more
311 d->SetOwnPrimaryVtx(origownvtx);
314 } else if(fRemoveDaughtersFromPrimary) {
315 d->UnsetOwnPrimaryVtx();
316 AliDebug(3,"delete new vertex\n");
323 // cout<<"Pid = "<<returnvaluePID<<endl;
324 return CombineSelectionLevels(3,returnvalueCuts,returnvaluePID);
326 //---------------------------------------------------------------------------
327 Bool_t AliRDHFCutsD0toKpi::IsInFiducialAcceptance(Double_t pt, Double_t y) const
330 // Checking if D0 is in fiducial acceptance region
334 // applying cut for pt > 5 GeV
335 AliDebug(2,Form("pt of D0 = %f (> 5), cutting at |y| < 0.8\n",pt));
336 if (TMath::Abs(y) > 0.8){
340 // appliying smooth cut for pt < 5 GeV
341 Double_t maxFiducialY = -0.2/15*pt*pt+1.9/15*pt+0.5;
342 Double_t minFiducialY = 0.2/15*pt*pt-1.9/15*pt-0.5;
343 AliDebug(2,Form("pt of D0 = %f (< 5), cutting according to the fiducial zone [%f, %f]\n",pt,minFiducialY,maxFiducialY));
344 if (y < minFiducialY || y > maxFiducialY){
351 //---------------------------------------------------------------------------
352 Int_t AliRDHFCutsD0toKpi::IsSelectedPID(AliAODRecoDecayHF* d)
354 // ############################################################
356 // Apply PID selection
359 // temporary selection: PID AS USED FOR D0 by Andrea Rossi (up to 28/06/2010)
361 // d must be a AliAODRecoDecayHF2Prong object
362 // returns 0 if both D0 and D0bar are rejectecd
363 // 1 if D0 is accepted while D0bar is rejected
364 // 2 if D0bar is accepted while D0 is rejected
365 // 3 if both are accepted
366 // fWhyRejection variable (not returned for the moment, print it if needed)
367 // keeps some information on why a candidate has been
368 // rejected according to the following (unfriendly?) scheme
369 // if more rejection cases are considered interesting, just add numbers
371 // TO BE CONSIDERED WITH A GRAIN OF SALT (the order in which cut are applied is relevant)
372 // from 20 to 30: "detector" selection (PID acceptance)
375 // 28: no (TOF||TPC) pid information (no kTOFpid,kTOFout,kTIME,kTPCpid,...)
377 // from 30 to 40: PID selection
378 // 31: no Kaon compatible tracks found between daughters
379 // 32: no Kaon identified tracks found (strong sel. at low momenta)
380 // 33: both mass hypotheses are rejected
382 // ############################################################
384 if(!fUsePID) return 3;
386 Int_t isD0D0barPID[2]={1,2};
387 Double_t nsigmaTPCpi=-1., nsigmaTPCK=-1.; //used for TPC pid
388 Double_t tofSig,times[5];// used fot TOF pid
389 Int_t hasPID[2]={2,2};// flag to count how many detectors give PID info for the daughters
390 Int_t isKaonPionTOF[2][2],isKaonPionTPC[2][2];
391 Int_t combinedPID[2][2];// CONVENTION: [daught][isK,IsPi]; [0][0]=(prong 1, isK)=value [0][1]=(prong 1, isPi)=value;
393 // values convention -1 = discarded
394 // 0 = not identified (but compatible) || No PID (->hasPID flag)
396 // PID search: pion (TPC) or not K (TOF), Kaon hypothesis for both
397 // Initial hypothesis: unknwon (but compatible)
398 isKaonPionTOF[0][0]=0;
399 isKaonPionTOF[0][1]=0;
400 isKaonPionTOF[1][0]=0;
401 isKaonPionTOF[1][1]=0;
403 isKaonPionTPC[0][0]=0;
404 isKaonPionTPC[0][1]=0;
405 isKaonPionTPC[1][0]=0;
406 isKaonPionTPC[1][1]=0;
415 for(Int_t daught=0;daught<2;daught++){
418 // ########### Step 0- CHECKING minimal PID "ACCEPTANCE" ####################
420 AliAODTrack *aodtrack=(AliAODTrack*)d->GetDaughter(daught);
422 if(!(aodtrack->GetStatus()&AliESDtrack::kTPCrefit)){
426 if(!(aodtrack->GetStatus()&AliESDtrack::kITSrefit)){
431 AliAODPid *pid=aodtrack->GetDetPid();
438 // ########### Step 1- Check of TPC and TOF response ####################
440 Double_t ptrack=aodtrack->P();
441 //#################### TPC PID #######################
442 if (!(aodtrack->GetStatus()&AliESDtrack::kTPCpid )){
443 // NO TPC PID INFO FOR THIS TRACK
447 static AliTPCPIDResponse theTPCpid;
448 nsigmaTPCpi = theTPCpid.GetNumberOfSigmas((Float_t)aodtrack->P(),(Float_t)pid->GetTPCsignal(),(Int_t)aodtrack->GetTPCClusterMap().CountBits(),AliPID::kPion);
449 nsigmaTPCK = theTPCpid.GetNumberOfSigmas((Float_t)aodtrack->P(),(Float_t)pid->GetTPCsignal(),(Int_t)aodtrack->GetTPCClusterMap().CountBits(),AliPID::kKaon);
451 if(TMath::Abs(nsigmaTPCK)<2.)isKaonPionTPC[daught][0]=1;
452 else if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
453 if(TMath::Abs(nsigmaTPCpi)<2.)isKaonPionTPC[daught][1]=1;
454 else if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
457 if(TMath::Abs(nsigmaTPCK)<1.)isKaonPionTPC[daught][0]=1;
458 else if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
459 if(TMath::Abs(nsigmaTPCpi)<1.)isKaonPionTPC[daught][1]=1;
460 else if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
463 // if(nsigmaTPCK>-2.&&nsigmaTPCK<1.)isKaonPionTPC[daught][0]=1;
464 if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
465 //if(nsigmaTPCpi>-1.&&nsigmaTPCpi<2.)isKaonPionTPC[daught][1]=1;
466 if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
471 // ##### TOF PID: do not ask nothing for pion/protons ############
472 if(!((aodtrack->GetStatus()&AliESDtrack::kTOFpid)&&(aodtrack->GetStatus()&AliESDtrack::kTOFout)&&(aodtrack->GetStatus()&AliESDtrack::kTIME))){
473 // NO TOF PID INFO FOR THIS TRACK
477 tofSig=pid->GetTOFsignal();
478 pid->GetIntegratedTimes(times);
479 if(TMath::Abs(tofSig-times[3])>3.*160.){
480 isKaonPionTOF[daught][0]=-1;
484 isKaonPionTOF[daught][0]=1;
489 //######### Step 2: COMBINE TOF and TPC PID ###############
490 // we apply the following convention: if TPC and TOF disagree (discarded Vs identified) -> unknown
491 combinedPID[daught][0]=isKaonPionTOF[daught][0]+isKaonPionTPC[daught][0];
492 combinedPID[daught][1]=isKaonPionTOF[daught][1]+isKaonPionTPC[daught][1];
495 //######### Step 3: USE PID INFO
497 if(combinedPID[daught][0]<=-1&&combinedPID[daught][1]<=-1){// if not a K- and not a pi- both D0 and D0bar excluded
501 else if(combinedPID[daught][0]==2&&combinedPID[daught][1]>=1){// if in conflict (both pi- and K-), if k for both TPC and TOF -> is K
502 if(aodtrack->Charge()==-1)isD0D0barPID[1]=0;//if K- D0bar excluded
503 else isD0D0barPID[0]=0;// if K+ D0 excluded
505 else if(combinedPID[daught][0]==1&&combinedPID[daught][1]>=1){// if in conflict (both pi- and K-) and k- only for TPC or TOF -> reject
509 else if(combinedPID[daught][0]>=1||combinedPID[daught][1]<=-1){
510 if(aodtrack->Charge()==-1)isD0D0barPID[1]=0;// not a D0bar if K- or if pi- excluded
511 else isD0D0barPID[0]=0;// not a D0 if K+ or if pi+ excluded
513 else if(combinedPID[daught][0]<=-1||combinedPID[daught][1]>=1){
514 if(aodtrack->Charge()==-1)isD0D0barPID[0]=0;// not a D0 if pi- or if K- excluded
515 else isD0D0barPID[1]=0;// not a D0bar if pi+ or if K+ excluded
518 // ########## ALSO DIFFERENT TPC PID REQUEST FOR LOW pt D0: request of K identification ###############################
519 // ########## more tolerant criteria for single particle ID-> more selective criteria for D0 ##############################
520 // ############### NOT OPTIMIZED YET ###################################
522 isKaonPionTPC[daught][0]=0;
523 isKaonPionTPC[daught][1]=0;
525 if(TMath::Abs(nsigmaTPCK)<3.)isKaonPionTPC[daught][0]=1;
526 else if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
527 if(TMath::Abs(nsigmaTPCpi)<3.)isKaonPionTPC[daught][1]=1;
528 else if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
531 if(TMath::Abs(nsigmaTPCK)<2.)isKaonPionTPC[daught][0]=1;
532 else if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
533 if(TMath::Abs(nsigmaTPCpi)<3.)isKaonPionTPC[daught][1]=1;
534 else if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
537 if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
538 if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
542 }// END OF LOOP ON DAUGHTERS
544 // FURTHER PID REQUEST (both daughter info is needed)
545 if(combinedPID[0][0]<=-1&&combinedPID[1][0]<=-1){
546 fWhyRejection=31;// reject cases in which no kaon-compatible tracks are found
549 else if(hasPID[0]==0&&hasPID[1]==0){
550 fWhyRejection=28;// reject cases in which no PID info is available
554 // request of K identification at low D0 pt
560 combinedPID[0][0]=isKaonPionTOF[0][0]+isKaonPionTPC[0][0];
561 combinedPID[0][1]=isKaonPionTOF[0][1]+isKaonPionTPC[0][1];
562 combinedPID[0][0]=isKaonPionTOF[1][0]+isKaonPionTPC[1][0];
563 combinedPID[0][1]=isKaonPionTOF[1][1]+isKaonPionTPC[1][1];
565 if(combinedPID[0][0]<=0&&combinedPID[1][0]<=0){
566 fWhyRejection=32;// reject cases where the Kaon is not identified
571 // cout<<"Why? "<<fWhyRejection<<endl;
572 return isD0D0barPID[0]+isD0D0barPID[1];
575 //---------------------------------------------------------------------------
576 Int_t AliRDHFCutsD0toKpi::CombineSelectionLevels(Int_t selectionvalTrack,
577 Int_t selectionvalCand,
578 Int_t selectionvalPID) const
581 // This method combines the tracks, PID and cuts selection results
583 if(selectionvalTrack==0) return 0;
587 switch(selectionvalPID) {
592 returnvalue=((selectionvalCand==1 || selectionvalCand==3) ? 1 : 0);
595 returnvalue=((selectionvalCand==2 || selectionvalCand==3) ? 2 : 0);
598 returnvalue=selectionvalCand;
607 //----------------------------------------------------------------------------
608 Int_t AliRDHFCutsD0toKpi::IsSelectedSpecialCuts(AliAODRecoDecayHF *d) const
611 // Note: this method is temporary
612 // Additional cuts on decay lenght and lower cut for d0 norm are applied using vertex without candidate's daughters
617 Float_t normDecLengthCut=1.,decLengthCut=TMath::Min(d->P()*0.0066+0.01,0.06/*cm*/), normd0Cut=0.5;
618 // "decay length" expo law with tau' = beta*gamma*ctau= p/m*ctau =p*0.0123/1.864~p*0.0066
619 // decay lenght > ctau' implies to retain (1-1/e) (for signal without considering detector resolution),
621 Int_t returnvalue=3; //cut passed
622 for(Int_t i=0;i<2/*prongs*/;i++){
623 if(TMath::Abs(d->Normalizedd0Prong(i))<normd0Cut) return 0; //normd0Cut not passed
625 if(d->DecayLength()<decLengthCut) return 0; //decLengthCut not passed
626 if(d->NormalizedDecayLength()<normDecLengthCut) return 0; //decLengthCut not passed