1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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 // study displaced electrons from beauty and charm
18 // with cut on impact parameters in various pT bins
22 // Hongyan Yang <hongyan@physi.uni-heidelberg.de>
33 #include <TObjArray.h>
34 #include <TParticle.h>
39 #include "AliCFManager.h"
40 #include "AliMCEvent.h"
41 #include "AliMCEventHandler.h"
42 #include "AliESDEvent.h"
43 #include "AliESDInputHandler.h"
44 #include "AliESDtrack.h"
45 #include "AliAnalysisManager.h"
46 #include "AliMCParticle.h"
49 #include "AliHFEpid.h"
50 #include "AliHFEcuts.h"
51 #include "AliHFEdisplacedElectrons.h"
53 #include "AliAnalysisTaskDisplacedElectrons.h"
56 //____________________________________________________________
57 AliAnalysisTaskDisplacedElectrons::AliAnalysisTaskDisplacedElectrons():
58 AliAnalysisTaskSE("Task for displaced electron study")
72 , fDisplacedElectrons(0x0)
73 , fHistDisplacedElectrons(0x0)
78 DefineInput(0, TChain::Class());
79 DefineOutput(2, TList::Class()); // output
80 DefineOutput(1, TList::Class()); // output
90 //____________________________________________________________
91 AliAnalysisTaskDisplacedElectrons::AliAnalysisTaskDisplacedElectrons(const char * name):
92 AliAnalysisTaskSE(name)
106 , fDisplacedElectrons(0x0)
107 , fHistDisplacedElectrons(0x0)
110 // Default constructor
112 DefineInput(0, TChain::Class());
113 DefineOutput(2, TList::Class());
114 DefineOutput(1, TList::Class());
119 //____________________________________________________________
120 AliAnalysisTaskDisplacedElectrons::AliAnalysisTaskDisplacedElectrons(const AliAnalysisTaskDisplacedElectrons &ref):
121 AliAnalysisTaskSE(ref)
122 , fDebugLevel(ref.fDebugLevel)
123 , fPIDdetectors(ref.fPIDdetectors)
124 , fPIDstrategy(ref.fPIDstrategy)
125 , fPlugins(ref.fPlugins)
131 , fNEvents(ref.fNEvents)
132 , fElectronsPt(ref.fElectronsPt)
133 , fOutput(ref.fOutput)
134 , fCorrection(ref.fCorrection)
135 , fDisplacedElectrons(ref.fDisplacedElectrons)
136 , fHistDisplacedElectrons(ref.fHistDisplacedElectrons)
143 //____________________________________________________________
144 AliAnalysisTaskDisplacedElectrons &AliAnalysisTaskDisplacedElectrons::operator=(const AliAnalysisTaskDisplacedElectrons &ref){
146 // Assignment operator
148 if(this == &ref) return *this;
149 AliAnalysisTask::operator=(ref);
150 fDebugLevel = ref.fDebugLevel;
151 fPIDdetectors = ref.fPIDdetectors;
152 fPIDstrategy = ref.fPIDstrategy;
153 fPlugins = ref.fPlugins;
159 fNEvents = ref.fNEvents;
160 fOutput = ref.fOutput;
161 fCorrection = ref.fCorrection;
162 fDisplacedElectrons = ref.fDisplacedElectrons;
163 fHistDisplacedElectrons = ref.fHistDisplacedElectrons;
168 //____________________________________________________________
169 AliAnalysisTaskDisplacedElectrons::~AliAnalysisTaskDisplacedElectrons(){
174 if(fPID) delete fPID;
176 if(fESD) delete fESD;
179 if(fCFM) delete fCFM;
181 if(fNEvents) delete fNEvents;
183 if(fElectronsPt) delete fElectronsPt;
192 fCorrection->Clear();
196 if(fDisplacedElectrons) delete fDisplacedElectrons;
198 if(fHistDisplacedElectrons){
199 fHistDisplacedElectrons->Clear();
200 delete fHistDisplacedElectrons;
206 //____________________________________________________________
207 void AliAnalysisTaskDisplacedElectrons::UserCreateOutputObjects(){
208 // create output objects
210 // MC and Data containers
212 fNEvents = new TH1I("nEvents", "Number of Events in the Analysis", 2, 0, 2);
213 const Int_t nBins = 14;
214 const Float_t ptBins[nBins] = {0.0,0.5,1.0,1.5,2.0,2.5,3.0,4.0,5.0,7.0,9.0,12.0,16.0,20.0};
215 fElectronsPt = new TH1F("esdPt", "p_{T} distribution of identified electrons (HFEpid);p_{T} (GeV/c);dN/dp_{T};", nBins-1, ptBins);
216 if(!fOutput) fOutput = new TList;
217 fOutput->SetName("results");
218 fOutput->AddAt(fElectronsPt,0);
219 fOutput->AddAt(fNEvents,1);
220 // Initialize correction Framework and Cuts
221 fCFM = new AliCFManager;
222 MakeEventContainer();
223 MakeParticleContainer();
225 if(!fCorrection) fCorrection = new TList();
226 fCorrection->SetName("corrections");
227 fCorrection->AddAt(fCFM->GetEventContainer(), 0);
228 fCorrection->AddAt(fCFM->GetParticleContainer(), 1);
229 fCorrection->Print();
231 // Temporary fix: Initialize particle cuts with 0x0
232 for(Int_t istep = 0; istep < fCFM->GetEventContainer()->GetNStep(); istep++)
233 fCFM->SetEventCutsList(istep, 0x0);
234 for(Int_t istep = 0; istep < fCFM->GetParticleContainer()->GetNStep(); istep++)
235 fCFM->SetParticleCutsList(istep, 0x0);
237 AliWarning("Cuts not available. Default cuts will be used");
238 fCuts = new AliHFEcuts;
239 fCuts->CreateStandardCuts();
243 fCuts->SetCutITSpixel(AliHFEextraCuts::kBoth);
245 fCuts->Initialize(fCFM);
247 fPID->SetHasMCData(HasMCData());
248 if(!fPIDdetectors.Length() && ! fPIDstrategy) AddPIDdetector("TPC");
250 fPID->InitializePID(Form("Strategy%d", fPIDstrategy));
252 fPID->InitializePID(fPIDdetectors.Data()); // Only restrictions to TPC allowed
254 // displaced electron study----------------------------------
255 if(GetPlugin(kDisplacedElectrons)){
257 fDisplacedElectrons = new AliHFEdisplacedElectrons;
258 fDisplacedElectrons->SetDebugLevel(fDebugLevel);
259 fDisplacedElectrons->SetHasMCData(HasMCData());
261 if(!fHistDisplacedElectrons) fHistDisplacedElectrons = new TList();
263 fDisplacedElectrons->CreateOutputs(fHistDisplacedElectrons);
265 fOutput->AddAt(fHistDisplacedElectrons, 2);
273 //____________________________________________________________
274 void AliAnalysisTaskDisplacedElectrons::UserExec(Option_t *){
279 AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler *>(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
281 AliError("No ESD input handler");
284 fESD = esdH->GetEvent();
287 AliMCEventHandler *mcH = dynamic_cast<AliMCEventHandler *>(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
289 AliError("No MC truth handler");
292 fMC = mcH->MCEvent();
295 if(fDebugLevel>=5)AliInfo("Processing ESD events");
297 AliError("No ESD Event");
302 if(fDebugLevel>=5)AliInfo(Form("MC Event: %p", fMC));
304 AliError("No MC Event, but MC Data required");
309 AliError("HFE cuts not available");
313 // process data: ESD tracks with MC information
314 Double_t container[8]; // container for the output in THnSparse
315 memset(container, 0, sizeof(Double_t) * 8);
317 Bool_t signal = kTRUE;
318 Bool_t alreadyseen = kFALSE;
319 LabelContainer cont(fESD->GetNumberOfTracks());
323 AliESDtrack *track = 0x0;
325 Double_t nContrib = fESD->GetPrimaryVertex()->GetNContributors();
326 if(!fCFM->CheckEventCuts(AliHFEcuts::kEventStepReconstructed, fESD)) return;
327 if(GetPlugin(kCorrection)){
328 fCFM->GetEventContainer()->Fill(&nContrib, AliHFEcuts::kEventStepReconstructed);
330 fCFM->SetRecEventInfo(fESD);
332 for(Int_t itrack = 0; itrack < fESD->GetNumberOfTracks(); itrack++){
333 track = fESD->GetTrack(itrack);
336 // track quality cut: 1st step: ITS and TPC cut; 2nd step: Rec prim; 3rd step: hfe cut on ITS pixel layer
338 // require within rapidity range +/-0.9
340 // if((TMath::Abs(track->Eta()))>0.9) continue;
343 if(GetPlugin(kDisplacedElectrons)) {
346 // RecKine: ITSTPC cuts : ITS & TPC refit, covmatrix: (2, 2, 0.5, 0.5, 2); min_tpccls: 50, chi2_tpccls: 3.5
347 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepRecKineITSTPC, track)){
352 container[0] = track->Pt();
353 container[1] = track->Eta();
354 container[2] = track->Phi();
355 container[3] = track->Charge();
357 AliStack *stack = fMC->Stack();
360 AliMCParticle *mctrack = NULL;
362 mctrack = dynamic_cast<AliMCParticle *>(fMCEvent->GetTrack(TMath::Abs(track->GetLabel())));
363 if(!mctrack) continue;
365 container[4] = mctrack->Pt();
366 container[5] = mctrack->Eta();
367 container[6] = mctrack->Phi();
368 container[7] = mctrack->Charge();
370 // if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepMCGenerated, mctrack)) signal = kFALSE;
371 if(TMath::Abs(mctrack->Eta())>0.9) {
374 } // cut on kinematics
379 if(signal && GetPlugin(kCorrection)){
380 alreadyseen = cont.Find(TMath::Abs(track->GetLabel())); // double counted track
381 cont.Append(TMath::Abs(track->GetLabel()));
382 fCFM->GetParticleContainer()->Fill(&container[4], AliHFEcuts::kStepRecKineITSTPC);
383 fCFM->GetParticleContainer()->Fill(&container[0], AliHFEcuts::kStepRecKineITSTPC + 2*AliHFEcuts::kNcutStepsESDtrack);
385 fCFM->GetParticleContainer()->Fill(&container[4], AliHFEcuts::kStepRecKineITSTPC + AliHFEcuts::kNcutStepsESDtrack);
387 } // fill correction --- 1st
390 // RecPrim: cut on track quality : DCA to vertex max: 3cm and 10cm; reject kink daughters
391 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepRecPrim, track)) {
397 alreadyseen = cont.Find(TMath::Abs(track->GetLabel()));
398 cont.Append(TMath::Abs(track->GetLabel()));
400 fCFM->GetParticleContainer()->Fill(&container[4], AliHFEcuts::kStepRecPrim);
401 fCFM->GetParticleContainer()->Fill(&container[0], AliHFEcuts::kStepRecPrim + 2*AliHFEcuts::kNcutStepsESDtrack);
403 fCFM->GetParticleContainer()->Fill(&container[4], AliHFEcuts::kStepRecPrim + AliHFEcuts::kNcutStepsESDtrack);
408 // HFEcuts: ITS layers cuts: ITS pixel layer: kFirst, kSecond, kBoth, kNone or kAny
409 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepHFEcutsITS, track)){
415 alreadyseen = cont.Find(TMath::Abs(track->GetLabel()));
416 cont.Append(TMath::Abs(track->GetLabel()));
418 fCFM->GetParticleContainer()->Fill(&container[4], AliHFEcuts::kStepHFEcutsITS);
419 fCFM->GetParticleContainer()->Fill(&container[0], AliHFEcuts::kStepHFEcutsITS + 2*AliHFEcuts::kNcutStepsESDtrack);
421 fCFM->GetParticleContainer()->Fill(&container[4], AliHFEcuts::kStepHFEcutsITS + AliHFEcuts::kNcutStepsESDtrack);
425 fDisplacedElectrons->FillMCOutput(fESD, track, stack);
427 // track accepted, do PID --> only electron candidate will be processed
428 AliHFEpidObject hfetrack;
429 hfetrack.fAnalysisType = AliHFEpidObject::kESDanalysis;
430 hfetrack.fRecTrack = track;
431 if((fPID->IsSelected(&hfetrack)==kTRUE))
433 AliInfo(Form("ESD info: this particle is %s identified as electron by HFEpid method \n", (fPID->IsSelected(&hfetrack)==kTRUE)?" ":" NOT "));
434 if(!fPID->IsSelected(&hfetrack)) continue;
440 fElectronsPt->Fill(track->Pt());
443 fCFM->GetParticleContainer()->Fill(container, AliHFEcuts::kStepPID + 2*AliHFEcuts::kNcutStepsESDtrack);
444 fCFM->GetParticleContainer()->Fill(&container[4], AliHFEcuts::kStepPID);
446 fCFM->GetParticleContainer()->Fill(&container[4], (AliHFEcuts::kStepPID + (AliHFEcuts::kNcutStepsESDtrack)));
450 fDisplacedElectrons->FillESDOutput(fESD, track);
452 } // analyze displaced electrons plugin switched on
456 AliInfo(Form("ESD info: number of electrons found in this event: %d\n", nElectrons));
461 PostData(1, fOutput);
462 PostData(2, fCorrection);
466 //____________________________________________________________
467 void AliAnalysisTaskDisplacedElectrons::Terminate(Option_t *){
469 // Terminate not implemented at the moment
472 if(GetPlugin(kDisplacedElectrons))
475 fOutput = dynamic_cast<TList *>(GetOutputData(1));
476 fCorrection= dynamic_cast<TList *>(GetOutputData(2));
478 if(!fOutput || !fCorrection){
479 if(!fCorrection) AliError("correction list not available\n");
480 if(!fOutput) AliError("output list not available\n");
486 fCorrection->Print();
488 AliInfo("analysis done!\n");
498 //____________________________________________________________
499 void AliAnalysisTaskDisplacedElectrons::PrintStatus() const {
502 // Print Analysis status
504 printf("\n\tAnalysis Settings\n\t========================================\n");
505 printf("\tdisplaced electrons' analysis is %s\n", GetPlugin(kDisplacedElectrons)?"ON":"OFF");
506 printf("\tcorrection container is %s\n", GetPlugin(kCorrection)?"ON":"OFF");
507 printf("\tpost processing is %s\n", GetPlugin(kPostProcess)?"ON":"OFF");
508 printf("\tcuts: %s\n", (fCuts != NULL) ? "YES" : "NO");
513 //__________________________________________
514 void AliAnalysisTaskDisplacedElectrons::SwitchOnPlugin(Int_t plug){
518 // - analyze impact parameter
523 case kDisplacedElectrons:
524 SETBIT(fPlugins, plug);
527 SETBIT(fPlugins, plug);
530 SETBIT(fPlugins, plug);
533 AliError("Unknown Plugin");
538 //____________________________________________________________
539 void AliAnalysisTaskDisplacedElectrons::MakeParticleContainer(){
541 // Create the particle container (borrowed from AliAnalysisTaskHFE)
543 const Int_t kNvar = 4; //number of variables on the grid:pt,eta, phi
544 const Double_t kPtmin = 0.1, kPtmax = 20.; // used for fixed pt bins
545 // const Float_t ptBins[14] = {0.0,0.5,1.0,1.5,2.0,2.5,3.0,4.0,5.0,7.0,9.0,12.0,16.0,20.0};
546 const Double_t kEtamin = -0.9, kEtamax = 0.9;
547 const Double_t kPhimin = 0., kPhimax = 2. * TMath::Pi();
549 //arrays for the number of bins in each dimension
551 iBin[0] = 40; //bins in pt // used for fixed pt bins
552 // iBin[0] = 13; //bins in pt
553 iBin[1] = 8; //bins in eta
554 iBin[2] = 18; // bins in phi
555 iBin[3] = 2; // bins in charge
557 //arrays for lower bounds :
558 Double_t* binEdges[kNvar];
559 for(Int_t ivar = 0; ivar < kNvar; ivar++)
560 binEdges[ivar] = new Double_t[iBin[ivar] + 1];
562 //values for bin lower bounds
563 // for(Int_t i=0; i<=iBin[0]; i++) binEdges[0][i]=ptBins[i]; // using variable bins
564 for(Int_t i=0; i<=iBin[0]; i++)
565 binEdges[0][i]=(Double_t)TMath::Power(10,TMath::Log10(kPtmin) + (TMath::Log10(kPtmax)-TMath::Log10(kPtmin))/iBin[0]*(Double_t)i); // fixed pt bin
566 for(Int_t i=0; i<=iBin[1]; i++) binEdges[1][i]=(Double_t)kEtamin + (kEtamax-kEtamin)/iBin[1]*(Double_t)i;
567 for(Int_t i=0; i<=iBin[2]; i++) binEdges[2][i]=(Double_t)kPhimin + (kPhimax-kPhimin)/iBin[2]*(Double_t)i;
568 for(Int_t i=0; i<=iBin[3]; i++) binEdges[3][i]=1.1*i-1.1; // Numeric precision
570 //one "container" for MC
571 AliCFContainer* container = new AliCFContainer("container","container for tracks",
572 (AliHFEcuts::kNcutStepsTrack + 1 + 2*(AliHFEcuts::kNcutStepsESDtrack + 1)),
575 //setting the bin limits
576 for(Int_t ivar = 0; ivar < kNvar; ivar++)
577 container -> SetBinLimits(ivar, binEdges[ivar]);
578 fCFM->SetParticleContainer(container);
580 //create correlation matrix for unfolding
581 Int_t thnDim[2*kNvar];
582 for (int k=0; k<kNvar; k++) {
583 //first half : reconstructed
586 thnDim[k+kNvar] = iBin[k];
589 // add more containers
594 //____________________________________________________________
595 void AliAnalysisTaskDisplacedElectrons::MakeEventContainer(){
597 // Create the event container for the correction framework and link it
599 const Int_t kNvar = 1; // number of variables on the grid: number of tracks per event
600 const Double_t kNTrackBound[2] = {-0.5, 200.5};
601 const Int_t kNBins = 201;
603 AliCFContainer *evCont = new AliCFContainer("eventContainer", "Container for events", AliHFEcuts::kNcutStepsEvent, kNvar, &kNBins);
605 Double_t trackBins[kNBins];
606 for(Int_t ibin = 0; ibin < kNBins; ibin++) trackBins[ibin] = kNTrackBound[0] + static_cast<Double_t>(ibin);
607 evCont->SetBinLimits(0,trackBins);
609 fCFM->SetEventContainer(evCont);
615 //__________________________________________________________
616 void AliAnalysisTaskDisplacedElectrons::AddPIDdetector(TString detector){
618 // Adding PID detector to the task
620 if(!fPIDdetectors.Length())
621 fPIDdetectors = detector;
623 fPIDdetectors += ":" + detector;
628 //____________________________________________________________
629 AliAnalysisTaskDisplacedElectrons::LabelContainer::LabelContainer(Int_t capacity):
637 // Default constructor
639 fContainer = new Int_t[capacity];
640 fBegin = &fContainer[0];
641 fEnd = &fContainer[capacity - 1];
642 fLast = fCurrent = fBegin;
645 //____________________________________________________________
646 Bool_t AliAnalysisTaskDisplacedElectrons::LabelContainer::Append(Int_t label){
648 // Add Label to the container
650 if(fLast > fEnd) return kFALSE;
655 //____________________________________________________________
656 Bool_t AliAnalysisTaskDisplacedElectrons::LabelContainer::Find(Int_t label) const {
658 // Find track in the list of labels
660 for(Int_t *entry = fBegin; entry <= fLast; entry++)
661 if(*entry == label) return kTRUE;
665 //____________________________________________________________
666 Int_t AliAnalysisTaskDisplacedElectrons::LabelContainer::Next() {
670 if(fCurrent > fLast) return -1;