1 /**************************************************************************
2 * Copyright(c) 1998-2009, 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 **************************************************************************/
17 // Base class for Heavy Flavour Correlations Analysis
18 // Single Event and Mixed Event Analysis are implemented
20 //-----------------------------------------------------------------------
23 // Author S.Bjelogrlic
25 // sandro.bjelogrlic@cern.ch
27 //-----------------------------------------------------------------------
29 /* $Id: AliHFCorrelator.cxx 64115 2013-09-05 12:34:55Z arossi $ */
31 #include <TParticle.h>
35 #include "AliHFCorrelator.h"
36 #include "AliRDHFCutsDStartoKpipi.h"
37 #include "AliHFAssociatedTrackCuts.h"
38 #include "AliEventPoolManager.h"
39 #include "AliReducedParticle.h"
40 #include "AliCentrality.h"
41 #include "AliAODMCParticle.h"
46 //_____________________________________________________
47 AliHFCorrelator::AliHFCorrelator() :
49 // default constructor
56 fDMesonCutObject(0x0),
57 fAssociatedTracks(0x0),
66 fUseCentrality(kFALSE),
70 fUseImpactParameter(0),
91 // default constructor
96 //_____________________________________________________
97 AliHFCorrelator::AliHFCorrelator(const Char_t* name, AliHFAssociatedTrackCuts *cuts, Bool_t useCentrality) :
103 fDMesonCutObject(0x0),
104 fAssociatedTracks(0x0),
113 fUseCentrality(useCentrality),
116 fUseImpactParameter(0),
137 if(!fDMesonCutObject) AliInfo("D meson cut object not loaded - if using centrality the estimator will be V0M!");
140 //_______________________________________________________________________________________
141 AliHFCorrelator::AliHFCorrelator(const Char_t* name, AliHFAssociatedTrackCuts *cuts, Bool_t useCentrality, AliRDHFCuts * cutObject) :
142 TNamed(name,"title"),
147 fDMesonCutObject(0x0),
148 fAssociatedTracks(0x0),
157 fUseCentrality(useCentrality),
160 fUseImpactParameter(0),
181 fDMesonCutObject = cutObject;
183 if(!fDMesonCutObject) AliInfo("D meson cut object not implemented properly! Check your centrality estimators");
188 //_____________________________________________________
189 AliHFCorrelator::~AliHFCorrelator()
195 if(fPoolMgr) {delete fPoolMgr; fPoolMgr=0;}
196 if(fPool) {delete fPool; fPool=0;}
197 if(fhadcuts) {delete fhadcuts; fhadcuts=0;}
198 if(fAODEvent) {delete fAODEvent; fAODEvent=0;}
199 if(fDMesonCutObject) {delete fDMesonCutObject; fDMesonCutObject=0;}
200 if(fAssociatedTracks) {delete fAssociatedTracks; fAssociatedTracks=0;}
201 if(fmcArray) {delete fmcArray; fmcArray=0;}
202 if(fReducedPart) {delete fReducedPart; fReducedPart=0;}
203 if(fD0cand) {delete fD0cand; fD0cand=0;}
206 if(fNofTracks) fNofTracks = 0;
208 if(fPhiMin) fPhiMin = 0;
209 if(fPhiMax) fPhiMax = 0;
211 if(fPtTrigger) fPtTrigger=0;
212 if(fPhiTrigger) fPhiTrigger=0;
213 if(fEtaTrigger) fEtaTrigger=0;
215 if(fDeltaPhi) fDeltaPhi=0;
216 if(fDeltaEta) fDeltaEta=0;
218 if(fk0InvMass) fk0InvMass=0;
221 //_____________________________________________________
222 Bool_t AliHFCorrelator::DefineEventPool(){
223 // definition of the Pool Manager for Event Mixing
226 Int_t MaxNofEvents = fhadcuts->GetMaxNEventsInPool();
227 Int_t MinNofTracks = fhadcuts->GetMinNTracksInPool();
228 Int_t NofCentBins = fhadcuts->GetNCentPoolBins();
229 Double_t * CentBins = fhadcuts->GetCentPoolBins();
230 Int_t NofZVrtxBins = fhadcuts->GetNZvtxPoolBins();
231 Double_t *ZVrtxBins = fhadcuts->GetZvtxPoolBins();
234 fPoolMgr = new AliEventPoolManager(MaxNofEvents, MinNofTracks, NofCentBins, CentBins, NofZVrtxBins, ZVrtxBins);
235 if(!fPoolMgr) return kFALSE;
238 //_____________________________________________________
239 Bool_t AliHFCorrelator::Initialize(){
241 // std::cout << "AliHFCorrelator::Initialize"<< std::endl;
242 // AliInfo("AliHFCorrelator::Initialize") ;
244 AliInfo("No AOD event") ;
247 //std::cout << "No AOD event" << std::endl;
249 AliCentrality *centralityObj = 0;
250 //Int_t multiplicity = -1;
251 //Double_t MultipOrCent = -1;
253 // initialize the pool for event mixing
254 if(!fUseCentrality){ // pp, pA
255 //multiplicity = fAODEvent->GetNTracks();
256 //MultipOrCent = AliVertexingHFUtils::GetNumberOfTrackletsInEtaRange(fAODEvent,-1.,1.);
257 fMultCentr = AliVertexingHFUtils::GetNumberOfTrackletsInEtaRange(fAODEvent,-1.,1.);
258 // MultipOrCent = multiplicity; // convert from Int_t to Double_t
259 // AliInfo(Form("Multiplicity is %f", MultipOrCent));
261 if(fUseCentrality){ // PbPb
262 if(!fDMesonCutObject){
264 centralityObj = fAODEvent->GetHeader()->GetCentralityP();
265 fMultCentr = centralityObj->GetCentralityPercentileUnchecked("V0M");
267 else fMultCentr = fDMesonCutObject->GetCentrality(fAODEvent);
268 // AliInfo(Form("Centrality is %f", MultipOrCent));
271 AliAODVertex *vtx = fAODEvent->GetPrimaryVertex();
272 Double_t zvertex = vtx->GetZ(); // zvertex
273 Double_t * CentBins = fhadcuts->GetCentPoolBins();
274 Double_t poolmin=CentBins[0];
275 Double_t poolmax=CentBins[fhadcuts->GetNCentPoolBins()];
278 if(TMath::Abs(zvertex)>=10 || fMultCentr>poolmax || fMultCentr < poolmin) {
279 if(!fUseCentrality)AliInfo(Form("Event with Zvertex = %.2f cm and multiplicity = %.0f out of pool bounds, SKIPPING",zvertex,fMultCentr));
280 if(fUseCentrality) AliInfo(Form("Event with Zvertex = %.2f cm and centrality = %.1f out of pool bounds, SKIPPING",zvertex,fMultCentr));
285 fPool = fPoolMgr->GetEventPool(fMultCentr, zvertex);
288 AliInfo(Form("No pool found for multiplicity = %f, zVtx = %f cm", fMultCentr, zvertex));
291 //fPool->PrintInfo();
295 //_____________________________________________________
296 Bool_t AliHFCorrelator::ProcessEventPool(){
297 // analysis on Mixed Events
298 //cout << "AliHFCorrelator::ProcessEventPool"<< endl;
299 if(!fmixing) return kFALSE;
300 if(!fPool->IsReady()) return kFALSE;
301 if(fPool->GetCurrentNEvents()<fhadcuts->GetMinEventsToMix()) return kFALSE;
302 // fPool->PrintInfo();
303 fPoolContent = fPool->GetCurrentNEvents();
309 //_____________________________________________________
310 Bool_t AliHFCorrelator::ProcessAssociatedTracks(Int_t EventLoopIndex, const TObjArray* associatedTracks){
311 // associatedTracks is not deleted, it should be (if needed) deleted in the user task
313 if(!fmixing){ // analysis on Single Event
314 if(fAssociatedTracks){
315 fAssociatedTracks->Delete();
316 delete fAssociatedTracks;
318 if(fselect==kHadron || fselect ==kKaon){
319 fAssociatedTracks = AcceptAndReduceTracks(fAODEvent);
320 fAssociatedTracks->SetOwner(kTRUE);
322 if(fselect==kKZero) {
323 fAssociatedTracks = AcceptAndReduceKZero(fAODEvent);
324 fAssociatedTracks->SetOwner(kTRUE);
326 if(fselect==kElectron && associatedTracks) {
327 fAssociatedTracks=new TObjArray(*associatedTracks);// Maybe better to call the copy constructor
328 fAssociatedTracks->SetOwner(kFALSE);
333 if(fmixing) { // analysis on Mixed Events
336 fAssociatedTracks = fPool->GetEvent(EventLoopIndex);
343 if(!fAssociatedTracks) return kFALSE;
345 fNofTracks = fAssociatedTracks->GetEntriesFast();
350 //_____________________________________________________
351 Bool_t AliHFCorrelator::Correlate(Int_t loopindex){
353 if(loopindex >= fNofTracks) return kFALSE;
354 if(!fAssociatedTracks) return kFALSE;
356 fReducedPart = (AliReducedParticle*)fAssociatedTracks->At(loopindex);
359 fDeltaPhi = SetCorrectPhiRange(fPhiTrigger - fReducedPart->Phi());
361 fDeltaEta = fEtaTrigger - fReducedPart->Eta();
367 //_____________________________________________________
368 Bool_t AliHFCorrelator::PoolUpdate(const TObjArray* associatedTracks){
370 if(!fmixing) return kFALSE;
371 if(!fPool) return kFALSE;
372 if(fmixing) { // update the pool for Event Mixing
373 TObjArray* objArr = NULL;
374 if(fselect==kHadron || fselect==kKaon) objArr = (TObjArray*)AcceptAndReduceTracks(fAODEvent);
375 else if(fselect==kKZero) objArr = (TObjArray*)AcceptAndReduceKZero(fAODEvent);
376 else if(fselect==kElectron && associatedTracks){
377 objArr = new TObjArray(*associatedTracks);
380 if(objArr->GetEntriesFast()>0) fPool->UpdatePool(objArr); // updating the pool only if there are entries in the array
387 //_____________________________________________________
388 Double_t AliHFCorrelator::SetCorrectPhiRange(Double_t phi){
389 Double_t pi = TMath::Pi();
391 if(phi<fPhiMin) phi = phi + 2*pi;
392 if(phi>fPhiMax) phi = phi - 2*pi;
397 //_____________________________________________________
398 TObjArray* AliHFCorrelator::AcceptAndReduceTracks(AliAODEvent* inputEvent){
401 Int_t nTracks = inputEvent->GetNTracks();
402 AliAODVertex * vtx = inputEvent->GetPrimaryVertex();
403 Double_t pos[3],cov[6];
405 vtx->GetCovarianceMatrix(cov);
406 const AliESDVertex vESD(pos,cov,100.,100);
408 Double_t Bz = inputEvent->GetMagneticField();
411 TObjArray* tracksClone = new TObjArray;
412 tracksClone->SetOwner(kTRUE);
414 //*******************************************************
415 // use reconstruction
417 for (Int_t iTrack=0; iTrack<nTracks; ++iTrack) {
418 AliAODTrack* track = inputEvent->GetTrack(iTrack);
419 if (!track) continue;
420 if(!fhadcuts->IsHadronSelected(track,&vESD,Bz)) continue; // apply ESD level selections
421 if(!fhadcuts->Charge(fDCharge,track)) continue; // apply selection on charge, if required
423 Double_t pT = track->Pt();
425 //compute impact parameter
426 Double_t d0z0[2],covd0z0[3];
427 Double_t d0=-999999.;
428 if(fUseImpactParameter) track->PropagateToDCA(vtx,Bz,100,d0z0,covd0z0);
429 else d0z0[0] = 1. ; // random number - be careful with the cuts you applied
431 if(fUseImpactParameter==1) d0 = TMath::Abs(d0z0[0]); // use impact parameter
432 if(fUseImpactParameter==2) { // use impact parameter over resolution
433 if(TMath::Abs(covd0z0[0])>0.00000001) d0 = TMath::Abs(d0z0[0])/TMath::Sqrt(covd0z0[0]);
434 else d0 = -1.; // if the resoultion is Zero, rejects the track - to be on the safe side
438 if(fmontecarlo) {// THIS TO BE CHECKED
439 Int_t hadLabel = track->GetLabel();
440 if(hadLabel < 0) continue;
443 if(!fhadcuts->CheckHadronKinematic(pT,d0)) continue; // apply kinematic cuts
444 Bool_t rejectsoftpi = kTRUE;// TO BE CHECKED: DO WE WANT IT TO kTRUE AS A DEFAULT?
445 if(fD0cand && !fmixing) rejectsoftpi = fhadcuts->InvMassDstarRejection(fD0cand,track,fhypD0); // TO BE CHECKED: WHY NOT FOR EM?
449 if(!fhadcuts->CheckKaonCompatibility(track,fmontecarlo,fmcArray,fPIDmode)) continue; // check if it is a Kaon - data and MC
451 weight=fhadcuts->GetTrackWeight(pT,track->Eta(),pos[2]);
452 tracksClone->Add(new AliReducedParticle(track->Eta(), track->Phi(), pT,track->GetLabel(),track->GetID(),d0,rejectsoftpi,track->Charge(),weight));
453 } // end loop on tracks
454 } // end if use reconstruction kTRUE
456 //*******************************************************
459 if(fmontecarlo && !fUseReco){
461 for (Int_t iPart=0; iPart<fmcArray->GetEntriesFast(); iPart++) {
462 AliAODMCParticle* mcPart = dynamic_cast<AliAODMCParticle*>(fmcArray->At(iPart));
464 AliWarning("MC Particle not found in tree, skipping");
467 if(!mcPart->Charge()) continue; // consider only charged tracks
469 Int_t PDG =TMath::Abs(mcPart->PdgCode());
470 if(fselect ==kHadron) {if(!((PDG==321)||(PDG==211)||(PDG==2212)||(PDG==13)||(PDG==11))) continue;} // select only if kaon, pion, proton, muon or electron
471 else if(fselect ==kKaon) {if(!(PDG==321)) continue;} // select only if kaon
472 else if(fselect ==kElectron) {if(!(PDG==11)) continue;} // select only if electron
474 Double_t pT = mcPart->Pt();
475 Double_t d0 =1; // set 1 fot the moment - no displacement calculation implemented yet
476 if(!fhadcuts->CheckHadronKinematic(pT,d0)) continue; // apply kinematic cuts
478 tracksClone->Add(new AliReducedParticle(mcPart->Eta(), mcPart->Phi(), pT,iPart,-1,d0,kFALSE,mcPart->Charge()));
481 } // end if use MC truth
487 //_____________________________________________________
488 TObjArray* AliHFCorrelator::AcceptAndReduceKZero(AliAODEvent* inputEvent){
490 Int_t nOfVZeros = inputEvent->GetNumberOfV0s();
491 TObjArray* KZeroClone = new TObjArray;
492 AliAODVertex *vertex1 = (AliAODVertex*)inputEvent->GetPrimaryVertex();
494 // use reconstruction
497 Int_t pdgDgK0toPipi[2] = {211,211};
498 Double_t mPDGK0=0.497614;//TDatabasePDG::Instance()->GetParticle(310)->Mass();
499 const Int_t size = inputEvent->GetNumberOfV0s();
500 Int_t prevnegID[size];
501 Int_t prevposID[size];
502 for(Int_t iv0 =0; iv0< nOfVZeros; iv0++){// loop on all v0 candidates
503 AliAODv0 *v0 = (static_cast<AliAODEvent*> (inputEvent))->GetV0(iv0);
505 AliInfo(Form("is not a v0 at step, %d", iv0)) ;
506 //cout << "is not a v0 at step " << iv0 << endl;
510 if(!fhadcuts->IsKZeroSelected(v0,vertex1)) continue; // check if it is a k0
512 // checks to avoid double counting
516 prevnegID[iv0] = -997;
517 prevposID[iv0]= -996;
518 negID = v0->GetNegID();
519 posID = v0->GetPosID();
520 Bool_t DoubleCounting = kFALSE;
522 for(Int_t k=0; k<iv0; k++){
523 if(((negID==prevnegID[k])&&(posID==prevposID[k]))||((negID==prevposID[k])&&(posID==prevnegID[k]))){
524 DoubleCounting = kTRUE;
530 if(DoubleCounting) continue;
532 prevposID[iv0] = posID;
533 prevnegID[iv0] = negID;
536 if(fmontecarlo) v0label = v0->MatchToMC(310,fmcArray, 0, pdgDgK0toPipi); //match a K0 short
537 Double_t k0pt = v0->Pt();
538 Double_t k0eta = v0->Eta();
539 Double_t k0Phi = v0->Phi();
540 fk0InvMass = v0->MassK0Short();
542 //if (loopindex == 0) {
543 // if(!plotassociation) ((TH2F*)fOutput->FindObject("KZeroSpectra"))->Fill(k0InvMass,k0pt); // spectra for all k0
544 // if(plotassociation) ((TH2F*)fOutput->FindObject("KZeroSpectraifHF"))->Fill(k0InvMass,k0pt); // spectra for k0 in association with a D*
546 // if there are more D* candidates per event, loopindex == 0 makes sure you fill the mass spectra only once!
548 if(TMath::Abs(fk0InvMass-mPDGK0)>3*0.004) continue; // select candidates within 3 sigma
549 KZeroClone->Add(new AliReducedParticle(k0eta,k0Phi,k0pt,v0label));
552 } // end if use reconstruction kTRUE
556 //*********************************************************************//
558 if(fmontecarlo && !fUseReco){
560 for (Int_t iPart=0; iPart<fmcArray->GetEntriesFast(); iPart++) {
561 AliAODMCParticle* mcPart = dynamic_cast<AliAODMCParticle*>(fmcArray->At(iPart));
563 AliWarning("MC Particle not found in tree, skipping");
567 Int_t PDG =TMath::Abs(mcPart->PdgCode());
568 if(!(PDG==310)) continue; // select only if k0 short
570 Double_t pT = mcPart->Pt();
571 Double_t d0 =1; // set 1 fot the moment - no displacement calculation implemented yet
572 if(!fhadcuts->CheckHadronKinematic(pT,d0)) continue; // apply kinematic cuts
574 KZeroClone->Add(new AliReducedParticle(mcPart->Eta(), mcPart->Phi(), pT,iPart,-1,d0,kTRUE,mcPart->Charge()));
577 } // end if use MC truth