1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Authors: Svein Lindal, Daniel Lohner *
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 ////////////////////////////////////////////////
17 //---------------------------------------------
18 // Class handling all kinds of selection cuts for
19 // Gamma Conversion analysis
20 //---------------------------------------------
21 ////////////////////////////////////////////////
23 #include "AliConversionMesonCuts.h"
25 #include "AliKFVertex.h"
26 #include "AliAODTrack.h"
27 #include "AliESDtrack.h"
28 #include "AliAnalysisManager.h"
29 #include "AliInputEventHandler.h"
30 #include "AliMCEventHandler.h"
31 #include "AliAODHandler.h"
32 #include "AliPIDResponse.h"
36 #include "AliAODConversionMother.h"
37 #include "TObjString.h"
38 #include "AliAODEvent.h"
39 #include "AliESDEvent.h"
40 #include "AliCentrality.h"
46 ClassImp(AliConversionMesonCuts)
49 const char* AliConversionMesonCuts::fgkCutNames[AliConversionMesonCuts::kNCuts] = {
53 "DegreesForRotationMethod",
64 //________________________________________________________________________
65 AliConversionMesonCuts::AliConversionMesonCuts(const char *name,const char *title) : AliAnalysisCuts(name,title),
72 fUseRotationMethodInBG(kFALSE),
73 fdoBGProbability(kFALSE),
74 fUseTrackMultiplicityForBG(kFALSE),
75 fnDegreeRotationPMForBG(0),
78 fDoToCloseV0sCut(kFALSE),
80 fDoSharedElecCut(kFALSE),
81 fUseMCPSmearing(kFALSE),
87 fElectronLabelArray(NULL),
92 for(Int_t jj=0;jj<kNCuts;jj++){fCuts[jj]=0;}
93 fCutString=new TObjString((GetCutNumber()).Data());
94 fElectronLabelArray = new Int_t[500];
96 fBrem = new TF1("fBrem","pow(-log(x),[0]/log(2.0)-1.0)/TMath::Gamma([0]/log(2.0))",0.00001,0.999999999);
97 // tests done with 1.0e-14
98 fBrem->SetParameter(0,fPBremSmearing);
99 fBrem->SetNpx(100000);
104 //________________________________________________________________________
105 AliConversionMesonCuts::~AliConversionMesonCuts() {
107 //Deleting fHistograms leads to seg fault it it's added to output collection of a task
109 // delete fHistograms;
110 // fHistograms = NULL;
111 if(fCutString != NULL){
115 if(fElectronLabelArray){
116 delete fElectronLabelArray;
117 fElectronLabelArray = NULL;
122 //________________________________________________________________________
123 void AliConversionMesonCuts::InitCutHistograms(TString name, Bool_t preCut){
125 // Initialize Cut Histograms for QA (only initialized and filled if function is called)
127 if(fHistograms != NULL){
131 if(fHistograms==NULL){
132 fHistograms=new TList();
133 if(name=="")fHistograms->SetName(Form("ConvMesonCuts_%s",GetCutNumber().Data()));
134 else fHistograms->SetName(Form("%s_%s",name.Data(),GetCutNumber().Data()));
138 hMesonCuts=new TH1F(Form("MesonCuts %s",GetCutNumber().Data()),"MesonCuts",10,-0.5,9.5);
139 hMesonCuts->GetXaxis()->SetBinLabel(1,"in");
140 hMesonCuts->GetXaxis()->SetBinLabel(2,"undef rapidity");
141 hMesonCuts->GetXaxis()->SetBinLabel(3,"rapidity cut");
142 hMesonCuts->GetXaxis()->SetBinLabel(4,"opening angle");
143 hMesonCuts->GetXaxis()->SetBinLabel(5,"alpha max");
144 hMesonCuts->GetXaxis()->SetBinLabel(6,"alpha min");
145 hMesonCuts->GetXaxis()->SetBinLabel(7,"out");
146 fHistograms->Add(hMesonCuts);
148 hMesonBGCuts=new TH1F(Form("MesonBGCuts %s",GetCutNumber().Data()),"MesonBGCuts",10,-0.5,9.5);
149 hMesonBGCuts->GetXaxis()->SetBinLabel(1,"in");
150 hMesonBGCuts->GetXaxis()->SetBinLabel(2,"undef rapidity");
151 hMesonBGCuts->GetXaxis()->SetBinLabel(3,"rapidity cut");
152 hMesonBGCuts->GetXaxis()->SetBinLabel(4,"opening angle");
153 hMesonBGCuts->GetXaxis()->SetBinLabel(5,"alpha max");
154 hMesonBGCuts->GetXaxis()->SetBinLabel(6,"alpha min");
155 hMesonBGCuts->GetXaxis()->SetBinLabel(7,"out");
156 fHistograms->Add(hMesonBGCuts);
160 //________________________________________________________________________
161 Bool_t AliConversionMesonCuts::MesonIsSelectedMC(TParticle *fMCMother,AliStack *fMCStack,Bool_t bMCDaughtersInAcceptance){
162 // Returns true for all pions within acceptance cuts for decay into 2 photons
163 // If bMCDaughtersInAcceptance is selected, it requires in addition that both daughter photons are within acceptance cuts
165 if(!fMCStack)return kFALSE;
167 if(fMCMother->GetPdgCode()==111 || fMCMother->GetPdgCode()==221){
168 if(fMCMother->R()>fMaxR) return kFALSE; // cuts on distance from collision point
170 Double_t rapidity = 10.;
171 if(fMCMother->Energy() - fMCMother->Pz() == 0 || fMCMother->Energy() + fMCMother->Pz() == 0){
174 rapidity = 0.5*(TMath::Log((fMCMother->Energy()+fMCMother->Pz()) / (fMCMother->Energy()-fMCMother->Pz())));
178 if(TMath::Abs(rapidity)>fRapidityCutMeson)return kFALSE;
180 // Select only -> 2y decay channel
181 if(fMCMother->GetNDaughters()!=2)return kFALSE;
183 for(Int_t i=0;i<2;i++){
184 TParticle *MDaughter=fMCStack->Particle(fMCMother->GetDaughter(i));
185 // Is Daughter a Photon?
186 if(MDaughter->GetPdgCode()!=22)return kFALSE;
187 // Is Photon in Acceptance?
188 // if(bMCDaughtersInAcceptance){
189 // if(!PhotonIsSelectedMC(MDaughter,fMCStack)){return kFALSE;}
197 //________________________________________________________________________
198 Bool_t AliConversionMesonCuts::MesonIsSelectedMCDalitz(TParticle *fMCMother,AliStack *fMCStack){
199 // Returns true for all pions within acceptance cuts for decay into 2 photons
200 // If bMCDaughtersInAcceptance is selected, it requires in addition that both daughter photons are within acceptance cuts
202 if(!fMCStack)return kFALSE;
204 if(fMCMother->GetPdgCode()==111 || fMCMother->GetPdgCode()==221){
206 if(fMCMother->R()>fMaxR) return kFALSE; // cuts on distance from collision point
208 Double_t rapidity = 10.;
209 if(fMCMother->Energy() - fMCMother->Pz() == 0 || fMCMother->Energy() + fMCMother->Pz() == 0){
213 rapidity = 0.5*(TMath::Log((fMCMother->Energy()+fMCMother->Pz()) / (fMCMother->Energy()-fMCMother->Pz())));
217 if(TMath::Abs(rapidity)>fRapidityCutMeson)return kFALSE;
219 // Select only -> Dalitz decay channel
220 if(fMCMother->GetNDaughters()!=3)return kFALSE;
222 Int_t daughterPDGs[3] = {0,0,0};
225 // iParticle->GetFirstDaughter(); idxPi0 <= iParticle->GetLastDaughter()
227 for(Int_t i=fMCMother->GetFirstDaughter(); i<= fMCMother->GetLastDaughter();i++){
228 TParticle *MDaughter=fMCStack->Particle(i);
229 // Is Daughter a Photon or an electron?
230 daughterPDGs[index]=MDaughter->GetPdgCode();
233 for (Int_t j=0;j<2;j++){
235 for (Int_t i=0;i<2;i++){
236 if (daughterPDGs[i] > daughterPDGs[i+1]){
237 Int_t interMed = daughterPDGs[i] ;
238 daughterPDGs[i] = daughterPDGs[i+1];
239 daughterPDGs[i+1] = interMed;
243 if (daughterPDGs[0] == -11 && daughterPDGs[1] == 11 && daughterPDGs[2] == 22) return kTRUE;
249 ///________________________________________________________________________
250 Bool_t AliConversionMesonCuts::MesonIsSelected(AliAODConversionMother *pi0,Bool_t IsSignal)
252 // Selection of reconstructed Meson candidates
253 // Use flag IsSignal in order to fill Fill different
254 // histograms for Signal and Background
259 if(IsSignal){hist=hMesonCuts;}
260 else{hist=hMesonBGCuts;}
264 if(hist)hist->Fill(cutIndex);
267 // Undefined Rapidity -> Floating Point exception
268 if((pi0->E()+pi0->Pz())/(pi0->E()-pi0->Pz())<=0){
269 if(hist)hist->Fill(cutIndex);
274 // PseudoRapidity Cut --> But we cut on Rapidity !!!
276 if(TMath::Abs(pi0->Rapidity())>fRapidityCutMeson){
277 //if(TMath::Abs(pi0->PseudoRapidity())>fRapidityCutMeson){
278 if(hist)hist->Fill(cutIndex);
285 //fOpeningAngle=2*TMath::ATan(0.134/pi0->P());// physical minimum opening angle
286 if( pi0->GetOpeningAngle() < fOpeningAngle){
287 if(hist)hist->Fill(cutIndex);
293 if(pi0->GetAlpha()>fAlphaCutMeson){
294 if(hist)hist->Fill(cutIndex);
300 if(pi0->GetAlpha()<fAlphaMinCutMeson){
301 if(hist)hist->Fill(cutIndex);
306 if(hist)hist->Fill(cutIndex);
312 ///________________________________________________________________________
313 ///________________________________________________________________________
314 Bool_t AliConversionMesonCuts::UpdateCutString(cutIds cutID, Int_t value) {
315 ///Update the cut string (if it has been created yet)
317 if(fCutString && fCutString->GetString().Length() == kNCuts) {
318 // cout << "Updating cut id in spot number " << cutID << " to " << value << endl;
319 fCutString->SetString(GetCutNumber());
321 // cout << "fCutString not yet initialized, will not be updated" << endl;
324 // cout << fCutString->GetString().Data() << endl;
328 ///________________________________________________________________________
329 Bool_t AliConversionMesonCuts::InitializeCutsFromCutString(const TString analysisCutSelection ) {
330 // Initialize Cuts from a given Cut string
331 AliInfo(Form("Set Meson Cutnumber: %s",analysisCutSelection.Data()));
332 if(analysisCutSelection.Length()!=kNCuts) {
333 AliError(Form("Cut selection has the wrong length! size is %d, number of cuts is %d", analysisCutSelection.Length(), kNCuts));
336 if(!analysisCutSelection.IsDigit()){
337 AliError("Cut selection contains characters");
341 const char *cutSelection = analysisCutSelection.Data();
342 #define ASSIGNARRAY(i) fCuts[i] = cutSelection[i] - '0'
343 for(Int_t ii=0;ii<kNCuts;ii++){
347 // Set Individual Cuts
348 for(Int_t ii=0;ii<kNCuts;ii++){
349 if(!SetCut(cutIds(ii),fCuts[ii]))return kFALSE;
355 ///________________________________________________________________________
356 Bool_t AliConversionMesonCuts::SetCut(cutIds cutID, const Int_t value) {
357 ///Set individual cut ID
359 //cout << "Updating cut " << fgkCutNames[cutID] << " (" << cutID << ") to " << value << endl;
362 if( SetMesonKind(value)) {
363 fCuts[kMesonKind] = value;
364 UpdateCutString(cutID, value);
366 } else return kFALSE;
370 if( SetChi2MesonCut(value)) {
371 fCuts[kchi2MesonCut] = value;
372 UpdateCutString(cutID, value);
374 } else return kFALSE;
377 if( SetAlphaMesonCut(value)) {
378 fCuts[kalphaMesonCut] = value;
379 UpdateCutString(cutID, value);
381 } else return kFALSE;
384 if( SetRCut(value)) {
385 fCuts[kRCut] = value;
386 UpdateCutString(cutID, value);
388 } else return kFALSE;
390 case kRapidityMesonCut:
391 if( SetRapidityMesonCut(value)) {
392 fCuts[kRapidityMesonCut] = value;
393 UpdateCutString(cutID, value);
395 } else return kFALSE;
397 case kBackgroundScheme:
398 if( SetBackgroundScheme(value)) {
399 fCuts[kBackgroundScheme] = value;
400 UpdateCutString(cutID, value);
402 } else return kFALSE;
404 case kDegreesForRotationMethod:
405 if( SetNDegreesForRotationMethod(value)) {
406 fCuts[kDegreesForRotationMethod] = value;
407 UpdateCutString(cutID, value);
409 } else return kFALSE;
411 case kNumberOfBGEvents:
412 if( SetNumberOfBGEvents(value)) {
413 fCuts[kNumberOfBGEvents] = value;
414 UpdateCutString(cutID, value);
416 } else return kFALSE;
418 case kuseMCPSmearing:
419 if( SetMCPSmearing(value)) {
420 fCuts[kuseMCPSmearing] = value;
421 UpdateCutString(cutID, value);
423 } else return kFALSE;
428 if( SetSharedElectronCut(value)) {
429 fCuts[kElecShare] = value;
430 UpdateCutString(cutID, value);
432 } else return kFALSE;
435 if( SetToCloseV0sCut(value)) {
436 fCuts[kToCloseV0s] = value;
437 UpdateCutString(cutID, value);
439 } else return kFALSE;
442 cout << "Error:: Cut id out of range"<< endl;
446 cout << "Error:: Cut id " << cutID << " not recognized "<< endl;
452 ///________________________________________________________________________
453 void AliConversionMesonCuts::PrintCuts() {
454 // Print out current Cut Selection
455 for(Int_t ic = 0; ic < kNCuts; ic++) {
456 printf("%-30s : %d \n", fgkCutNames[ic], fCuts[ic]);
460 ///________________________________________________________________________
461 Bool_t AliConversionMesonCuts::SetMesonKind(Int_t mesonKind){
471 cout<<"Warning: Meson kind not defined"<<mesonKind<<endl;
477 ///________________________________________________________________________
478 Bool_t AliConversionMesonCuts::SetRCut(Int_t rCut){
499 // High purity cuts for PbPb
504 cout<<"Warning: rCut not defined"<<rCut<<endl;
510 ///________________________________________________________________________
511 Bool_t AliConversionMesonCuts::SetChi2MesonCut(Int_t chi2MesonCut){
513 switch(chi2MesonCut){
515 fChi2CutMeson = 100.;
524 fChi2CutMeson = 200.;
527 fChi2CutMeson = 500.;
530 fChi2CutMeson = 1000.;
533 cout<<"Warning: Chi2MesonCut not defined "<<chi2MesonCut<<endl;
540 ///________________________________________________________________________
541 Bool_t AliConversionMesonCuts::SetAlphaMesonCut(Int_t alphaMesonCut)
543 switch(alphaMesonCut){
545 fAlphaMinCutMeson = 0.0;
546 fAlphaCutMeson = 0.7;
549 fAlphaMinCutMeson = 0.0;
550 fAlphaCutMeson = 0.5;
553 fAlphaMinCutMeson = 0.5;
557 fAlphaMinCutMeson = 0.0;
561 fAlphaMinCutMeson = 0.0;
562 fAlphaCutMeson = 0.65;
565 fAlphaMinCutMeson = 0.0;
566 fAlphaCutMeson = 0.75;
569 fAlphaMinCutMeson = 0.0;
570 fAlphaCutMeson = 0.8;
573 fAlphaMinCutMeson = 0.0;
574 fAlphaCutMeson = 0.85;
577 fAlphaMinCutMeson = 0.0;
578 fAlphaCutMeson = 0.6;
581 cout<<"Warning: AlphaMesonCut not defined "<<alphaMesonCut<<endl;
587 ///________________________________________________________________________
588 Bool_t AliConversionMesonCuts::SetRapidityMesonCut(Int_t RapidityMesonCut){
590 switch(RapidityMesonCut){
592 fRapidityCutMeson = 0.9;
595 fRapidityCutMeson = 0.8;
598 fRapidityCutMeson = 0.7;
601 fRapidityCutMeson = 0.6;
604 fRapidityCutMeson = 0.5;
608 cout<<"Warning: RapidityMesonCut not defined "<<RapidityMesonCut<<endl;
615 ///________________________________________________________________________
616 Bool_t AliConversionMesonCuts::SetBackgroundScheme(Int_t BackgroundScheme){
618 switch(BackgroundScheme){
620 fUseRotationMethodInBG=kTRUE;
621 fdoBGProbability=kFALSE;
623 case 1: // mixed event with V0 multiplicity
624 fUseRotationMethodInBG=kFALSE;
625 fUseTrackMultiplicityForBG=kFALSE;
626 fdoBGProbability=kFALSE;
628 case 2: // mixed event with track multiplicity
629 fUseRotationMethodInBG=kFALSE;
630 fUseTrackMultiplicityForBG=kTRUE;
631 fdoBGProbability=kFALSE;
634 fUseRotationMethodInBG=kTRUE;
635 fdoBGProbability=kTRUE;
638 cout<<"Warning: BackgroundScheme not defined "<<BackgroundScheme<<endl;
645 ///________________________________________________________________________
646 Bool_t AliConversionMesonCuts::SetNDegreesForRotationMethod(Int_t DegreesForRotationMethod){
648 switch(DegreesForRotationMethod){
650 fnDegreeRotationPMForBG = 5;
653 fnDegreeRotationPMForBG = 10;
656 fnDegreeRotationPMForBG = 15;
659 fnDegreeRotationPMForBG = 20;
662 cout<<"Warning: DegreesForRotationMethod not defined "<<DegreesForRotationMethod<<endl;
665 fCuts[kDegreesForRotationMethod]=DegreesForRotationMethod;
669 ///________________________________________________________________________
670 Bool_t AliConversionMesonCuts::SetNumberOfBGEvents(Int_t NumberOfBGEvents){
672 switch(NumberOfBGEvents){
674 fNumberOfBGEvents = 5;
677 fNumberOfBGEvents = 10;
680 fNumberOfBGEvents = 15;
683 fNumberOfBGEvents = 20;
686 fNumberOfBGEvents = 2;
689 fNumberOfBGEvents = 50;
692 fNumberOfBGEvents = 80;
695 fNumberOfBGEvents = 100;
698 cout<<"Warning: NumberOfBGEvents not defined "<<NumberOfBGEvents<<endl;
704 // ///________________________________________________________________________
705 // Bool_t AliConversionMesonCuts::SetPsiPairCut(Int_t psiCut) {
709 // fPsiPairCut = 10000; //
712 // fPsiPairCut = 0.1; //
715 // fPsiPairCut = 0.05; // Standard
718 // fPsiPairCut = 0.035; //
721 // fPsiPairCut = 0.15; //
724 // fPsiPairCut = 0.2; //
727 // fPsiPairCut = 0.03; //
730 // fPsiPairCut = 0.025; //
733 // fPsiPairCut = 0.01; //
736 // cout<<"Warning: PsiPairCut not defined "<<fPsiPairCut<<endl;
744 ///________________________________________________________________________
745 Bool_t AliConversionMesonCuts::SetSharedElectronCut(Int_t sharedElec) {
749 fDoSharedElecCut = kFALSE;
752 fDoSharedElecCut = kTRUE;
755 cout<<"Warning: Shared Electron Cut not defined "<<sharedElec<<endl;
762 ///________________________________________________________________________
763 Bool_t AliConversionMesonCuts::SetToCloseV0sCut(Int_t toClose) {
767 fDoToCloseV0sCut = kFALSE;
771 fDoToCloseV0sCut = kTRUE;
775 fDoToCloseV0sCut = kTRUE;
779 fDoToCloseV0sCut = kTRUE;
783 cout<<"Warning: Shared Electron Cut not defined "<<toClose<<endl;
789 ///________________________________________________________________________
790 Bool_t AliConversionMesonCuts::SetMCPSmearing(Int_t useMCPSmearing)
792 switch(useMCPSmearing){
801 fPBremSmearing=1.0e-14;
807 fPBremSmearing=1.0e-15;
815 fPSigSmearingCte=0.002;
821 fPSigSmearingCte=0.007;
827 fPSigSmearingCte=0.016;
833 fPSigSmearingCte=0.016;
837 fPBremSmearing=1.0e-16;
845 fPSigSmearingCte=0.014;
851 fPSigSmearingCte=0.011;
855 AliError("Warning: UseMCPSmearing not defined");
861 // Bool_t AliConversionMesonCuts::PsiPairCut(const AliConversionPhotonBase * photon) const {
863 // if(photon->GetPsiPair() > fPsiPairCut){
865 // else{return kTRUE;}
869 ///________________________________________________________________________
870 TString AliConversionMesonCuts::GetCutNumber(){
871 // returns TString with current cut number
873 for(Int_t ii=0;ii<kNCuts;ii++){
874 a.Append(Form("%d",fCuts[ii]));
879 ///________________________________________________________________________
880 void AliConversionMesonCuts::FillElectonLabelArray(AliAODConversionPhoton* photon, Int_t nV0){
882 Int_t posLabel = photon->GetTrackLabelPositive();
883 Int_t negLabel = photon->GetTrackLabelNegative();
885 fElectronLabelArray[nV0*2] = posLabel;
886 fElectronLabelArray[(nV0*2)+1] = negLabel;
889 ///________________________________________________________________________
890 Bool_t AliConversionMesonCuts::RejectSharedElectronV0s(AliAODConversionPhoton* photon, Int_t nV0, Int_t nV0s){
892 Int_t posLabel = photon->GetTrackLabelPositive();
893 Int_t negLabel = photon->GetTrackLabelNegative();
895 for(Int_t i = 0; i<nV0s*2;i++){
896 if(i==nV0*2) continue;
897 if(i==(nV0*2)+1) continue;
898 if(fElectronLabelArray[i] == posLabel){
900 if(fElectronLabelArray[i] == negLabel){
906 ///________________________________________________________________________
907 Bool_t AliConversionMesonCuts::RejectToCloseV0s(AliAODConversionPhoton* photon, TList *photons, Int_t nV0){
908 Double_t posX = photon->GetConversionX();
909 Double_t posY = photon->GetConversionY();
910 Double_t posZ = photon->GetConversionZ();
912 for(Int_t i = 0;i<photons->GetEntries();i++){
913 if(nV0 == i) continue;
914 AliAODConversionPhoton *photonComp = (AliAODConversionPhoton*) photons->At(i);
915 Double_t posCompX = photonComp->GetConversionX();
916 Double_t posCompY = photonComp->GetConversionY();
917 Double_t posCompZ = photonComp->GetConversionZ();
919 Double_t dist = pow((posX - posCompX),2)+pow((posY - posCompY),2)+pow((posZ - posCompZ),2);
921 if(dist < fminV0Dist*fminV0Dist){
922 if(photon->GetChi2perNDF() < photonComp->GetChi2perNDF()) return kTRUE;
931 ///________________________________________________________________________
932 void AliConversionMesonCuts::SmearParticle(AliAODConversionPhoton* photon)
934 Double_t facPBrem = 1.;
935 Double_t facPSig = 0.;
945 theta=acos( photon->Pz()/ photon->P());
948 if( fPSigSmearing != 0. || fPSigSmearingCte!=0. ){
949 facPSig = TMath::Sqrt(fPSigSmearingCte*fPSigSmearingCte+fPSigSmearing*fPSigSmearing*P*P)*fRandom.Gaus(0.,1.);
952 if( fPBremSmearing != 1.){
954 facPBrem = fBrem->GetRandom();
958 photon->SetPx(facPBrem* (1+facPSig)* P*sin(theta)*cos(phi)) ;
959 photon->SetPy(facPBrem* (1+facPSig)* P*sin(theta)*sin(phi)) ;
960 photon->SetPz(facPBrem* (1+facPSig)* P*cos(theta)) ;
961 photon->SetE(photon->P());