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 fUseSpecialCuts(kFALSE)
42 // Default Constructor
46 TString varNames[9]={"inv. mass [GeV]",
55 Bool_t isUpperCut[9]={kTRUE,
64 SetVarNames(nvars,varNames,isUpperCut);
65 Bool_t forOpt[9]={kFALSE,
74 SetVarsForOpt(4,forOpt);
75 Float_t limits[2]={0,999999999.};
78 SetRemoveDaughtersFromPrim(kTRUE);
80 //--------------------------------------------------------------------------
81 AliRDHFCutsD0toKpi::AliRDHFCutsD0toKpi(const AliRDHFCutsD0toKpi &source) :
83 fUseSpecialCuts(source.fUseSpecialCuts)
90 //--------------------------------------------------------------------------
91 AliRDHFCutsD0toKpi &AliRDHFCutsD0toKpi::operator=(const AliRDHFCutsD0toKpi &source)
94 // assignment operator
96 if(&source == this) return *this;
98 AliRDHFCuts::operator=(source);
99 fUseSpecialCuts=source.fUseSpecialCuts;
105 //---------------------------------------------------------------------------
106 void AliRDHFCutsD0toKpi::GetCutVarsForOpt(AliAODRecoDecayHF *d,Float_t *vars,Int_t nvars,Int_t *pdgdaughters) {
108 // Fills in vars the values of the variables
111 if(nvars!=fnVarsForOpt) {
112 printf("AliRDHFCutsD0toKpi::GetCutsVarsForOpt: wrong number of variables\n");
116 AliAODRecoDecayHF2Prong *dd = (AliAODRecoDecayHF2Prong*)d;
121 if(TMath::Abs(pdgdaughters[0])==211) {
122 vars[iter]=dd->InvMassD0();
124 vars[iter]=dd->InvMassD0bar();
129 vars[iter]=dd->GetDCA();
133 if(TMath::Abs(pdgdaughters[0])==211) {
134 vars[iter] = dd->CosThetaStarD0();
136 vars[iter] = dd->CosThetaStarD0bar();
141 if(TMath::Abs(pdgdaughters[0])==321) {
142 vars[iter]=dd->PtProng(0);
145 vars[iter]=dd->PtProng(1);
150 if(TMath::Abs(pdgdaughters[0])==211) {
151 vars[iter]=dd->PtProng(0);
154 vars[iter]=dd->PtProng(1);
159 if(TMath::Abs(pdgdaughters[0])==321) {
160 vars[iter]=dd->Getd0Prong(0);
163 vars[iter]=dd->Getd0Prong(1);
168 if(TMath::Abs(pdgdaughters[0])==211) {
169 vars[iter]=dd->Getd0Prong(0);
172 vars[iter]=dd->Getd0Prong(1);
177 vars[iter]= dd->Prodd0d0();
181 vars[iter]=dd->CosPointingAngle();
186 //---------------------------------------------------------------------------
187 Int_t AliRDHFCutsD0toKpi::IsSelected(TObject* obj,Int_t selectionLevel,AliAODEvent* aod) {
193 cout<<"Cut matrice not inizialized. Exit..."<<endl;
197 AliAODRecoDecayHF2Prong* d=(AliAODRecoDecayHF2Prong*)obj;
200 cout<<"AliAODRecoDecayHF2Prong null"<<endl;
204 // selection on daughter tracks
205 if(selectionLevel==AliRDHFCuts::kAll ||
206 selectionLevel==AliRDHFCuts::kTracks) {
207 if(!AreDaughtersSelected(d)) return 0;
212 // returnvalue: 0 not sel, 1 only D0, 2 only D0bar, 3 both
213 Int_t returnvaluePID=3;
214 Int_t returnvalueCuts=3;
217 if(selectionLevel==AliRDHFCuts::kAll ||
218 selectionLevel==AliRDHFCuts::kCandidate ||
219 selectionLevel==AliRDHFCuts::kPID) {
220 returnvaluePID = IsSelectedPID(d);
225 // selection on candidate
226 if(selectionLevel==AliRDHFCuts::kAll ||
227 selectionLevel==AliRDHFCuts::kCandidate) {
229 //recalculate vertex w/o daughters
230 AliAODVertex *origownvtx=0x0;
231 AliAODVertex *recvtx=0x0;
232 if(fRemoveDaughtersFromPrimary) {
234 AliError("Can not remove daughters from vertex without AOD event");
237 if(d->GetOwnPrimaryVtx()) origownvtx=new AliAODVertex(*d->GetOwnPrimaryVtx());
238 recvtx=d->RemoveDaughtersFromPrimaryVtx(aod);
240 AliDebug(2,"Removal of daughter tracks failed");
241 //recvtx=d->GetPrimaryVtx();
248 //set recalculed primary vertex
249 d->SetOwnPrimaryVtx(recvtx);
250 delete recvtx; recvtx=NULL;
256 Int_t okD0=0,okD0bar=0;
258 Int_t ptbin=PtBin(pt);
261 d->SetOwnPrimaryVtx(origownvtx);
265 else d->UnsetOwnPrimaryVtx();
268 Double_t mD0,mD0bar,ctsD0,ctsD0bar;
271 Double_t mD0PDG = TDatabasePDG::Instance()->GetParticle(421)->Mass();
273 if(d->PtProng(1) < fCutsRD[GetGlobalIndex(3,ptbin)] || d->PtProng(0) < fCutsRD[GetGlobalIndex(4,ptbin)]) okD0 = 0;
274 if(d->PtProng(0) < fCutsRD[GetGlobalIndex(3,ptbin)] || d->PtProng(1) < fCutsRD[GetGlobalIndex(4,ptbin)]) okD0bar = 0;
275 if(!okD0 && !okD0bar) returnvalueCuts=0;
278 if(TMath::Abs(d->Getd0Prong(1)) > fCutsRD[GetGlobalIndex(5,ptbin)] ||
279 TMath::Abs(d->Getd0Prong(0)) > fCutsRD[GetGlobalIndex(6,ptbin)]) okD0 = 0;
280 if(TMath::Abs(d->Getd0Prong(0)) > fCutsRD[GetGlobalIndex(6,ptbin)] ||
281 TMath::Abs(d->Getd0Prong(1)) > fCutsRD[GetGlobalIndex(5,ptbin)]) okD0bar = 0;
282 if(!okD0 && !okD0bar) returnvalueCuts=0;
284 if(d->GetDCA() > fCutsRD[GetGlobalIndex(1,ptbin)]) returnvalueCuts=0;
286 d->InvMassD0(mD0,mD0bar);
287 if(TMath::Abs(mD0-mD0PDG) > fCutsRD[GetGlobalIndex(0,ptbin)]) okD0 = 0;
288 if(TMath::Abs(mD0bar-mD0PDG) > fCutsRD[GetGlobalIndex(0,ptbin)]) okD0bar = 0;
289 if(!okD0 && !okD0bar) returnvalueCuts=0;
291 d->CosThetaStarD0(ctsD0,ctsD0bar);
292 if(TMath::Abs(ctsD0) > fCutsRD[GetGlobalIndex(2,ptbin)]) okD0 = 0;
293 if(TMath::Abs(ctsD0bar) > fCutsRD[GetGlobalIndex(2,ptbin)]) okD0bar = 0;
294 if(!okD0 && !okD0bar) returnvalueCuts=0;
296 if(d->Prodd0d0() > fCutsRD[GetGlobalIndex(7,ptbin)]) returnvalueCuts=0;
298 if(d->CosPointingAngle() < fCutsRD[GetGlobalIndex(8,ptbin)]) returnvalueCuts=0;
300 if (returnvalueCuts!=0) {
301 if (okD0) returnvalueCuts=1; //cuts passed as D0
302 if (okD0bar) returnvalueCuts=2; //cuts passed as D0bar
303 if (okD0 && okD0bar) returnvalueCuts=3; //cuts passed as D0 and D0bar
308 if(fUseSpecialCuts) special=IsSelectedSpecialCuts(d);
309 if(!special) returnvalueCuts=0;
311 // unset recalculated primary vertex when not needed any more
313 d->SetOwnPrimaryVtx(origownvtx);
316 } else if(fRemoveDaughtersFromPrimary) {
317 d->UnsetOwnPrimaryVtx();
318 AliDebug(3,"delete new vertex\n");
325 // cout<<"Pid = "<<returnvaluePID<<endl;
326 return CombineSelectionLevels(3,returnvalueCuts,returnvaluePID);
328 //---------------------------------------------------------------------------
329 Bool_t AliRDHFCutsD0toKpi::IsInFiducialAcceptance(Double_t pt, Double_t y) const
332 // Checking if D0 is in fiducial acceptance region
336 // applying cut for pt > 5 GeV
337 AliDebug(2,Form("pt of D0 = %f (> 5), cutting at |y| < 0.8\n",pt));
338 if (TMath::Abs(y) > 0.8){
342 // appliying smooth cut for pt < 5 GeV
343 Double_t maxFiducialY = -0.2/15*pt*pt+1.9/15*pt+0.5;
344 Double_t minFiducialY = 0.2/15*pt*pt-1.9/15*pt-0.5;
345 AliDebug(2,Form("pt of D0 = %f (< 5), cutting according to the fiducial zone [%f, %f]\n",pt,minFiducialY,maxFiducialY));
346 if (y < minFiducialY || y > maxFiducialY){
353 //---------------------------------------------------------------------------
354 Int_t AliRDHFCutsD0toKpi::IsSelectedPID(AliAODRecoDecayHF* d)
356 // ############################################################
358 // Apply PID selection
361 // temporary selection: PID AS USED FOR D0 by Andrea Rossi (up to 28/06/2010)
363 // d must be a AliAODRecoDecayHF2Prong object
364 // returns 0 if both D0 and D0bar are rejectecd
365 // 1 if D0 is accepted while D0bar is rejected
366 // 2 if D0bar is accepted while D0 is rejected
367 // 3 if both are accepted
368 // fWhyRejection variable (not returned for the moment, print it if needed)
369 // keeps some information on why a candidate has been
370 // rejected according to the following (unfriendly?) scheme
371 // if more rejection cases are considered interesting, just add numbers
373 // TO BE CONSIDERED WITH A GRAIN OF SALT (the order in which cut are applied is relevant)
374 // from 20 to 30: "detector" selection (PID acceptance)
377 // 28: no (TOF||TPC) pid information (no kTOFpid,kTOFout,kTIME,kTPCpid,...)
379 // from 30 to 40: PID selection
380 // 31: no Kaon compatible tracks found between daughters
381 // 32: no Kaon identified tracks found (strong sel. at low momenta)
382 // 33: both mass hypotheses are rejected
384 // ############################################################
386 if(!fUsePID) return 3;
388 Int_t isD0D0barPID[2]={1,2};
389 Double_t nsigmaTPCpi=-1., nsigmaTPCK=-1.; //used for TPC pid
390 Double_t tofSig,times[5];// used fot TOF pid
391 Int_t hasPID[2]={2,2};// flag to count how many detectors give PID info for the daughters
392 Int_t isKaonPionTOF[2][2],isKaonPionTPC[2][2];
393 Int_t combinedPID[2][2];// CONVENTION: [daught][isK,IsPi]; [0][0]=(prong 1, isK)=value [0][1]=(prong 1, isPi)=value;
395 // values convention -1 = discarded
396 // 0 = not identified (but compatible) || No PID (->hasPID flag)
398 // PID search: pion (TPC) or not K (TOF), Kaon hypothesis for both
399 // Initial hypothesis: unknwon (but compatible)
400 isKaonPionTOF[0][0]=0;
401 isKaonPionTOF[0][1]=0;
402 isKaonPionTOF[1][0]=0;
403 isKaonPionTOF[1][1]=0;
405 isKaonPionTPC[0][0]=0;
406 isKaonPionTPC[0][1]=0;
407 isKaonPionTPC[1][0]=0;
408 isKaonPionTPC[1][1]=0;
417 for(Int_t daught=0;daught<2;daught++){
420 // ########### Step 0- CHECKING minimal PID "ACCEPTANCE" ####################
422 AliAODTrack *aodtrack=(AliAODTrack*)d->GetDaughter(daught);
424 if(!(aodtrack->GetStatus()&AliESDtrack::kTPCrefit)){
428 if(!(aodtrack->GetStatus()&AliESDtrack::kITSrefit)){
433 AliAODPid *pid=aodtrack->GetDetPid();
440 // ########### Step 1- Check of TPC and TOF response ####################
442 Double_t ptrack=aodtrack->P();
443 //#################### TPC PID #######################
444 if (!(aodtrack->GetStatus()&AliESDtrack::kTPCpid )){
445 // NO TPC PID INFO FOR THIS TRACK
449 static AliTPCPIDResponse theTPCpid;
450 nsigmaTPCpi = theTPCpid.GetNumberOfSigmas((Float_t)aodtrack->P(),(Float_t)pid->GetTPCsignal(),(Int_t)aodtrack->GetTPCClusterMap().CountBits(),AliPID::kPion);
451 nsigmaTPCK = theTPCpid.GetNumberOfSigmas((Float_t)aodtrack->P(),(Float_t)pid->GetTPCsignal(),(Int_t)aodtrack->GetTPCClusterMap().CountBits(),AliPID::kKaon);
453 if(TMath::Abs(nsigmaTPCK)<2.)isKaonPionTPC[daught][0]=1;
454 else if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
455 if(TMath::Abs(nsigmaTPCpi)<2.)isKaonPionTPC[daught][1]=1;
456 else if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
459 if(TMath::Abs(nsigmaTPCK)<1.)isKaonPionTPC[daught][0]=1;
460 else if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
461 if(TMath::Abs(nsigmaTPCpi)<1.)isKaonPionTPC[daught][1]=1;
462 else if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
465 // if(nsigmaTPCK>-2.&&nsigmaTPCK<1.)isKaonPionTPC[daught][0]=1;
466 if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
467 //if(nsigmaTPCpi>-1.&&nsigmaTPCpi<2.)isKaonPionTPC[daught][1]=1;
468 if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
473 // ##### TOF PID: do not ask nothing for pion/protons ############
474 if(!((aodtrack->GetStatus()&AliESDtrack::kTOFpid)&&(aodtrack->GetStatus()&AliESDtrack::kTOFout)&&(aodtrack->GetStatus()&AliESDtrack::kTIME))){
475 // NO TOF PID INFO FOR THIS TRACK
479 tofSig=pid->GetTOFsignal();
480 pid->GetIntegratedTimes(times);
481 if(TMath::Abs(tofSig-times[3])>3.*160.){
482 isKaonPionTOF[daught][0]=-1;
486 isKaonPionTOF[daught][0]=1;
491 //######### Step 2: COMBINE TOF and TPC PID ###############
492 // we apply the following convention: if TPC and TOF disagree (discarded Vs identified) -> unknown
493 combinedPID[daught][0]=isKaonPionTOF[daught][0]+isKaonPionTPC[daught][0];
494 combinedPID[daught][1]=isKaonPionTOF[daught][1]+isKaonPionTPC[daught][1];
497 //######### Step 3: USE PID INFO
499 if(combinedPID[daught][0]<=-1&&combinedPID[daught][1]<=-1){// if not a K- and not a pi- both D0 and D0bar excluded
503 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
504 if(aodtrack->Charge()==-1)isD0D0barPID[1]=0;//if K- D0bar excluded
505 else isD0D0barPID[0]=0;// if K+ D0 excluded
507 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
511 else if(combinedPID[daught][0]>=1||combinedPID[daught][1]<=-1){
512 if(aodtrack->Charge()==-1)isD0D0barPID[1]=0;// not a D0bar if K- or if pi- excluded
513 else isD0D0barPID[0]=0;// not a D0 if K+ or if pi+ excluded
515 else if(combinedPID[daught][0]<=-1||combinedPID[daught][1]>=1){
516 if(aodtrack->Charge()==-1)isD0D0barPID[0]=0;// not a D0 if pi- or if K- excluded
517 else isD0D0barPID[1]=0;// not a D0bar if pi+ or if K+ excluded
520 // ########## ALSO DIFFERENT TPC PID REQUEST FOR LOW pt D0: request of K identification ###############################
521 // ########## more tolerant criteria for single particle ID-> more selective criteria for D0 ##############################
522 // ############### NOT OPTIMIZED YET ###################################
524 isKaonPionTPC[daught][0]=0;
525 isKaonPionTPC[daught][1]=0;
527 if(TMath::Abs(nsigmaTPCK)<3.)isKaonPionTPC[daught][0]=1;
528 else if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
529 if(TMath::Abs(nsigmaTPCpi)<3.)isKaonPionTPC[daught][1]=1;
530 else if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
533 if(TMath::Abs(nsigmaTPCK)<2.)isKaonPionTPC[daught][0]=1;
534 else if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
535 if(TMath::Abs(nsigmaTPCpi)<3.)isKaonPionTPC[daught][1]=1;
536 else if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
539 if(TMath::Abs(nsigmaTPCK)>3.)isKaonPionTPC[daught][0]=-1;
540 if(TMath::Abs(nsigmaTPCpi)>3.)isKaonPionTPC[daught][1]=-1;
544 }// END OF LOOP ON DAUGHTERS
546 // FURTHER PID REQUEST (both daughter info is needed)
547 if(combinedPID[0][0]<=-1&&combinedPID[1][0]<=-1){
548 fWhyRejection=31;// reject cases in which no kaon-compatible tracks are found
551 else if(hasPID[0]==0&&hasPID[1]==0){
552 fWhyRejection=28;// reject cases in which no PID info is available
556 // request of K identification at low D0 pt
562 combinedPID[0][0]=isKaonPionTOF[0][0]+isKaonPionTPC[0][0];
563 combinedPID[0][1]=isKaonPionTOF[0][1]+isKaonPionTPC[0][1];
564 combinedPID[1][0]=isKaonPionTOF[1][0]+isKaonPionTPC[1][0];
565 combinedPID[1][1]=isKaonPionTOF[1][1]+isKaonPionTPC[1][1];
567 if(combinedPID[0][0]<=0&&combinedPID[1][0]<=0){
568 fWhyRejection=32;// reject cases where the Kaon is not identified
573 // cout<<"Why? "<<fWhyRejection<<endl;
574 return isD0D0barPID[0]+isD0D0barPID[1];
577 //---------------------------------------------------------------------------
578 Int_t AliRDHFCutsD0toKpi::CombineSelectionLevels(Int_t selectionvalTrack,
579 Int_t selectionvalCand,
580 Int_t selectionvalPID) const
583 // This method combines the tracks, PID and cuts selection results
585 if(selectionvalTrack==0) return 0;
589 switch(selectionvalPID) {
594 returnvalue=((selectionvalCand==1 || selectionvalCand==3) ? 1 : 0);
597 returnvalue=((selectionvalCand==2 || selectionvalCand==3) ? 2 : 0);
600 returnvalue=selectionvalCand;
609 //----------------------------------------------------------------------------
610 Int_t AliRDHFCutsD0toKpi::IsSelectedSpecialCuts(AliAODRecoDecayHF *d) const
613 // Note: this method is temporary
614 // Additional cuts on decay lenght and lower cut for d0 norm are applied using vertex without candidate's daughters
619 Float_t normDecLengthCut=1.,decLengthCut=TMath::Min(d->P()*0.0066+0.01,0.06/*cm*/), normd0Cut=0.5;
620 // "decay length" expo law with tau' = beta*gamma*ctau= p/m*ctau =p*0.0123/1.864~p*0.0066
621 // decay lenght > ctau' implies to retain (1-1/e) (for signal without considering detector resolution),
623 Int_t returnvalue=3; //cut passed
624 for(Int_t i=0;i<2/*prongs*/;i++){
625 if(TMath::Abs(d->Normalizedd0Prong(i))<normd0Cut) return 0; //normd0Cut not passed
627 if(d->DecayLength()<decLengthCut) return 0; //decLengthCut not passed
628 if(d->NormalizedDecayLength()<normDecLengthCut) return 0; //decLengthCut not passed