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 // Filling an AliCFContainer with the quantities pt, eta and phi
18 // for tracks which survivied the particle cuts (MC resp. ESD tracks)
19 // Track selection is done using the AliHFE package
22 // Raphaelle Bailhache <R.Bailhache@gsi.de>
23 // Markus Fasel <M.Fasel@gsi.de>
24 // Matus Kalisky <matus.kalisky@cern.ch>
25 // MinJung Kweon <minjung@physi.uni-heidelberg.de>
30 #include <TDirectory.h>
36 #include <TIterator.h>
40 #include <TObjArray.h>
41 #include <TParticle.h>
46 #include "AliCFContainer.h"
47 #include "AliCFManager.h"
48 #include "AliCFEffGrid.h"
49 #include "AliESDEvent.h"
50 #include "AliESDInputHandler.h"
51 #include "AliESDtrack.h"
52 #include "AliESDtrackCuts.h"
54 #include "AliAnalysisManager.h"
55 #include "AliMCEvent.h"
56 #include "AliMCEventHandler.h"
57 #include "AliMCParticle.h"
61 #include "AliHFEpid.h"
62 #include "AliHFEcuts.h"
63 #include "AliHFEmcQA.h"
64 #include "AliHFEsecVtx.h"
65 #include "AliAnalysisTaskHFE.h"
67 //____________________________________________________________
68 AliAnalysisTaskHFE::AliAnalysisTaskHFE():
69 AliAnalysisTask("PID efficiency Analysis", "")
77 , fPIDperformance(0x0)
83 , fNElectronTracksEvent(0x0)
92 DefineInput(0, TChain::Class());
93 DefineOutput(0, TH1I::Class());
94 DefineOutput(1, TList::Class());
95 DefineOutput(2, TList::Class());
103 //____________________________________________________________
104 AliAnalysisTaskHFE::AliAnalysisTaskHFE(const char * name):
105 AliAnalysisTask(name, "")
113 , fPIDperformance(0x0)
119 , fNElectronTracksEvent(0x0)
126 // Default constructor
128 DefineInput(0, TChain::Class());
129 DefineOutput(0, TH1I::Class());
130 DefineOutput(1, TList::Class());
131 DefineOutput(2, TList::Class());
134 fPID = new AliHFEpid;
139 //____________________________________________________________
140 AliAnalysisTaskHFE::AliAnalysisTaskHFE(const AliAnalysisTaskHFE &ref):
142 , fQAlevel(ref.fQAlevel)
143 , fPIDdetectors(ref.fPIDdetectors)
144 , fPIDstrategy(ref.fPIDstrategy)
148 , fCorrelation(ref.fCorrelation)
149 , fPIDperformance(ref.fPIDperformance)
152 , fSecVtx(ref.fSecVtx)
154 , fNEvents(ref.fNEvents)
155 , fNElectronTracksEvent(ref.fNElectronTracksEvent)
157 , fOutput(ref.fOutput)
158 , fHistMCQA(ref.fHistMCQA)
159 , fHistSECVTX(ref.fHistSECVTX)
166 //____________________________________________________________
167 AliAnalysisTaskHFE &AliAnalysisTaskHFE::operator=(const AliAnalysisTaskHFE &ref){
169 // Assignment operator
171 if(this == &ref) return *this;
172 AliAnalysisTask::operator=(ref);
173 fQAlevel = ref.fQAlevel;
174 fPIDdetectors = ref.fPIDdetectors;
175 fPIDstrategy = ref.fPIDstrategy;
179 fCorrelation = ref.fCorrelation;
180 fPIDperformance = ref.fPIDperformance;
183 fSecVtx = ref.fSecVtx;
185 fNEvents = ref.fNEvents;
186 fNElectronTracksEvent = ref.fNElectronTracksEvent;
188 fOutput = ref.fOutput;
189 fHistMCQA = ref.fHistMCQA;
190 fHistSECVTX = ref.fHistSECVTX;
194 //____________________________________________________________
195 AliAnalysisTaskHFE::~AliAnalysisTaskHFE(){
199 if(fESD) delete fESD;
201 if(fPID) delete fPID;
215 fHistSECVTX->Clear();
218 if(fSecVtx) delete fSecVtx;
219 if(fMCQA) delete fMCQA;
220 if(fNEvents) delete fNEvents;
222 fCorrelation->Clear();
225 if(fPIDperformance) delete fPIDperformance;
228 //____________________________________________________________
229 void AliAnalysisTaskHFE::ConnectInputData(Option_t *){
231 // Connecting the input
232 // Called once per worker
234 /* TTree *esdchain = dynamic_cast<TChain *>(GetInputData(0));
236 AliError("ESD chain empty");
239 esdchain->SetBranchStatus("Tracks", 1);
242 AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler *>(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
244 AliError("No ESD input handler");
247 fESD = esdH->GetEvent();
249 AliMCEventHandler *mcH = dynamic_cast<AliMCEventHandler *>(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
251 AliError("No MC truth handler");
254 fMC = mcH->MCEvent();
258 //____________________________________________________________
259 void AliAnalysisTaskHFE::CreateOutputObjects(){
261 // Creating output container and output objects
262 // Here we also Initialize the correction framework container and
267 // QA histograms are created if requested
268 // Called once per worker
270 fNEvents = new TH1I("nEvents", "Number of Events in the Analysis", 2, 0, 2); // Number of Events neccessary for the analysis and not a QA histogram
271 fNElectronTracksEvent = new TH1I("nElectronTracksEvent", "Number of Electron Candidates", 100, 0, 100);
272 // First Step: TRD alone
273 if(!fQA) fQA = new TList;
274 fQA->AddAt(new TProfile("conr", "Electron PID contamination", 20, 0, 20), 0);
275 fQA->AddAt(new TH1F("alpha_rec", "Alpha from reconstructed tracks with TRD hits", 36, -TMath::Pi(), TMath::Pi()), 1);
276 fQA->AddAt(new TH1F("alpha_sim", "Alpha from simulated electron tracks", 36, -TMath::Pi(), TMath::Pi()), 2);
277 fQA->AddAt(new TH1F("nElectron", "Number of electrons", 100, 0, 100), 3);
278 fQA->AddAt(new TProfile("pidquality", "TRD PID quality as function of momentum", 20, 0, 20), 4);
279 fQA->AddAt(new TProfile("ntrdclusters", "Number of TRD clusters as function of momentum", 20, 0, 20), 5);
280 fQA->AddAt(new TH1F("chi2TRD","#chi2 per TRD cluster", 20, 0, 20), 6);
282 if(!fOutput) fOutput = new TList;
283 // Initialize correction Framework and Cuts
284 fCFM = new AliCFManager;
285 MakeParticleContainer();
286 // Temporary fix: Initialize particle cuts with 0x0
287 for(Int_t istep = 0; istep < fCFM->GetParticleContainer()->GetNStep(); istep++)
288 fCFM->SetParticleCutsList(istep, 0x0);
290 AliWarning("Cuts not available. Default cuts will be used");
291 fCuts = new AliHFEcuts;
292 fCuts->CreateStandardCuts();
294 fCuts->Initialize(fCFM);
295 if(fCuts->IsInDebugMode()) fQA->Add(fCuts->GetQAhistograms());
297 // add output objects to the List
298 fOutput->AddAt(fCFM->GetParticleContainer(), 0);
299 fOutput->AddAt(fCorrelation, 1);
300 fOutput->AddAt(fPIDperformance, 2);
301 fOutput->AddAt(fNElectronTracksEvent, 3);
305 AliInfo("PID QA switched on");
306 //fPID->SetDebugLevel(2);
308 fQA->Add(fPID->GetQAhistograms());
310 fPID->SetHasMCData(HasMCData());
311 if(!fPIDdetectors.Length() && ! fPIDstrategy) AddPIDdetector("TPC");
313 fPID->InitializePID(Form("Strategy%d", fPIDstrategy));
315 fPID->InitializePID(fPIDdetectors.Data()); // Only restrictions to TPC allowed
317 // mcQA----------------------------------
320 if(!fMCQA) fMCQA = new AliHFEmcQA;
321 if(!fHistMCQA) fHistMCQA = new TList();
322 fHistMCQA->SetName("MCqa");
323 fMCQA->CreateHistograms(AliHFEmcQA::kCharm,0,"mcqa_"); // create histograms for charm
324 fMCQA->CreateHistograms(AliHFEmcQA::kBeauty,0,"mcqa_"); // create histograms for beauty
325 fMCQA->CreateHistograms(AliHFEmcQA::kCharm,1,"mcqa_barrel_"); // create histograms for charm
326 fMCQA->CreateHistograms(AliHFEmcQA::kBeauty,1,"mcqa_barrel_"); // create histograms for beauty
327 fMCQA->CreateHistograms(AliHFEmcQA::kCharm,2,"mcqa_unitY_"); // create histograms for charm
328 fMCQA->CreateHistograms(AliHFEmcQA::kBeauty,2,"mcqa_unitY_"); // create histograms for beauty
329 fMCQA->CreateHistograms(AliHFEmcQA::kCharm,3,"mcqa_reccut_"); // create histograms for charm
330 fMCQA->CreateHistograms(AliHFEmcQA::kBeauty,3,"mcqa_reccut_"); // create histograms for beauty
331 fMCQA->CreateHistograms(AliHFEmcQA::kCharm,4,"mcqa_recpidcut_"); // create histograms for charm
332 fMCQA->CreateHistograms(AliHFEmcQA::kBeauty,4,"mcqa_recpidcut_"); // create histograms for beauty
333 TIter next(gDirectory->GetList());
337 while ((obj = next.Next())) {
338 objname = obj->GetName();
339 TObjArray *toks = objname.Tokenize("_");
340 if (toks->GetEntriesFast()){
341 TObjString *fpart = (TObjString *)(toks->UncheckedAt(0));
342 if ((fpart->String()).CompareTo("mcqa") == 0) fHistMCQA->AddAt(obj, counter++);
348 // secvtx----------------------------------
350 AliInfo("Secondary Vertex Analysis on");
351 fSecVtx = new AliHFEsecVtx;
353 if(!fHistSECVTX) fHistSECVTX = new TList();
354 fHistSECVTX->SetName("SecVtx");
355 fSecVtx->CreateHistograms("secvtx_");
356 TIter next(gDirectory->GetList());
360 while ((obj = next.Next())) {
361 objname = obj->GetName();
362 TObjArray *toks = objname.Tokenize("_");
363 if (toks->GetEntriesFast()){
364 TObjString *fpart = (TObjString *)(toks->UncheckedAt(0));
365 if ((fpart->String()).CompareTo("secvtx") == 0) fHistSECVTX->AddAt(obj, counter++);
368 fOutput->Add(fHistSECVTX);
372 //____________________________________________________________
373 void AliAnalysisTaskHFE::Exec(Option_t *){
378 AliError("No ESD Event");
382 AliError("No MC Event");
386 AliError("HFE cuts not available");
390 //fCFM->CheckEventCuts(AliCFManager::kEvtGenCuts, fMC);
391 Double_t container[6];
392 // container for the output THnSparse
393 Double_t dataE[5]; // [pT, eta, Phi, type, 'C' or 'B']
395 // Loop over the Monte Carlo tracks to see whether we have overlooked any track
396 AliMCParticle *mctrack = 0x0;
397 Int_t nElectrons = 0;
400 fSecVtx->SetEvent(fESD);
401 fSecVtx->SetStack(fMC->Stack());
404 // run mc QA ------------------------------------------------
406 AliDebug(2, "Running MC QA");
408 fMCQA->SetStack(fMC->Stack());
411 Int_t nMCTracks = fMC->Stack()->GetNtrack();
413 // loop over all tracks for decayed electrons
414 for (Int_t igen = 0; igen < nMCTracks; igen++){
415 TParticle* mcpart = fMC->Stack()->Particle(igen);
416 fMCQA->GetQuarkKine(mcpart, igen, AliHFEmcQA::kCharm);
417 fMCQA->GetQuarkKine(mcpart, igen, AliHFEmcQA::kBeauty);
418 fMCQA->GetHadronKine(mcpart, AliHFEmcQA::kCharm);
419 fMCQA->GetHadronKine(mcpart, AliHFEmcQA::kBeauty);
420 fMCQA->GetDecayedKine(mcpart, AliHFEmcQA::kCharm, AliHFEmcQA::kElectronPDG, 0); // no accept cut
421 fMCQA->GetDecayedKine(mcpart, AliHFEmcQA::kBeauty, AliHFEmcQA::kElectronPDG, 0); // no accept cut
422 if (TMath::Abs(mcpart->Eta()) < 0.9) {
423 fMCQA->GetDecayedKine(mcpart, AliHFEmcQA::kCharm, AliHFEmcQA::kElectronPDG, 1); // accept |eta|<0.9
424 fMCQA->GetDecayedKine(mcpart, AliHFEmcQA::kBeauty, AliHFEmcQA::kElectronPDG, 1); // accept |eta|<0.9
426 if (TMath::Abs(GetRapidity(mcpart)) < 0.5) {
427 fMCQA->GetDecayedKine(mcpart, AliHFEmcQA::kCharm, AliHFEmcQA::kElectronPDG, 2); // accept |y|<0.5
428 fMCQA->GetDecayedKine(mcpart, AliHFEmcQA::kBeauty, AliHFEmcQA::kElectronPDG, 2); // accept |y|<0.5
431 fMCQA->EndOfEventAna(AliHFEmcQA::kCharm);
432 fMCQA->EndOfEventAna(AliHFEmcQA::kBeauty);
434 } // end of MC QA loop
435 // -----------------------------------------------------------------
440 fCuts->SetEventInfo(fMC);
441 for(Int_t imc = fMC->GetNumberOfTracks(); imc--;){
442 mctrack = dynamic_cast<AliMCParticle *>(fMC->GetTrack(imc));
444 container[0] = mctrack->Pt();
445 container[1] = mctrack->Eta();
446 container[2] = mctrack->Phi();
448 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepMCGenerated, mctrack)) continue;
449 fCFM->GetParticleContainer()->Fill(container, AliHFEcuts::kStepMCGenerated);
450 if(IsSignalElectron(mctrack)) fCFM->GetParticleContainer()->Fill(container, AliHFEcuts::kStepMCsignal);
451 (dynamic_cast<TH1F *>(fQA->At(2)))->Fill(mctrack->Phi() - TMath::Pi());
452 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepMCInAcceptance, mctrack)) continue;
453 // find the label in the vector
454 fCFM->GetParticleContainer()->Fill(container, AliHFEcuts::kStepMCInAcceptance);
457 (dynamic_cast<TH1F *>(fQA->At(3)))->Fill(nElectrons);
459 // fCFM->CheckEventCuts(AliCFManager::kEvtRecCuts, fESD);
465 Int_t nElectronCandidates = 0;
466 AliESDtrack *track = 0x0, *htrack = 0x0;
468 // For double counted tracks
469 LabelContainer cont(fESD->GetNumberOfTracks());
470 Bool_t alreadyseen = kFALSE;
472 Bool_t signal = kTRUE;
474 fCuts->SetEventInfo(fESD);
475 for(Int_t itrack = 0; itrack < fESD->GetNumberOfTracks(); itrack++){
477 track = fESD->GetTrack(itrack);
479 container[0] = track->Pt();
480 container[1] = track->Eta();
481 container[2] = track->Phi();
483 dataE[0] = track->Pt();
484 dataE[1] = track->Eta();
485 dataE[2] = track->Phi();
491 // RecKine: ITSTPC cuts
492 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepRecKineITSTPC, track)) continue;
494 // Check if it is electrons near the vertex
495 if(!(mctrack = dynamic_cast<AliMCParticle *>(fMC->GetTrack(TMath::Abs(track->GetLabel()))))) continue;
496 TParticle* mctrack4QA = fMC->Stack()->Particle(TMath::Abs(track->GetLabel()));
498 container[3] = mctrack->Pt();
499 container[4] = mctrack->Eta();
500 container[5] = mctrack->Phi();
502 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepMCGenerated, mctrack)) signal = kFALSE;
505 alreadyseen = cont.Find(TMath::Abs(track->GetLabel()));
506 cont.Append(TMath::Abs(track->GetLabel()));
508 fCFM->GetParticleContainer()->Fill(&container[3], AliHFEcuts::kStepRecKineITSTPC);
509 fCFM->GetParticleContainer()->Fill(&container[0], (AliHFEcuts::kStepRecKineITSTPC + 2*(AliHFEcuts::kNcutESDSteps + 1)));
511 fCFM->GetParticleContainer()->Fill(&container[3], (AliHFEcuts::kStepRecKineITSTPC + (AliHFEcuts::kNcutESDSteps + 1)));
515 // Check TRD criterions (outside the correction framework)
516 if(track->GetTRDncls()){
517 (dynamic_cast<TH1F *>(fQA->At(6)))->Fill(track->GetTRDchi2()/track->GetTRDncls());
518 (dynamic_cast<TH1F *>(fQA->At(1)))->Fill(track->GetAlpha()); // Check the acceptance without tight cuts
519 (dynamic_cast<TProfile *>(fQA->At(4)))->Fill(container[0], track->GetTRDpidQuality());
520 (dynamic_cast<TProfile *>(fQA->At(5)))->Fill(container[0], track->GetTRDncls());
525 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepRecPrim, track)) continue;
527 fCFM->GetParticleContainer()->Fill(container, AliHFEcuts::kStepRecPrim + 2*(AliHFEcuts::kNcutESDSteps + 1));
528 fCFM->GetParticleContainer()->Fill(&container[3], AliHFEcuts::kStepRecPrim);
530 fCFM->GetParticleContainer()->Fill(&container[3], AliHFEcuts::kStepRecPrim + AliHFEcuts::kNcutESDSteps + 1);
535 // HFEcuts: ITS layers cuts
536 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepHFEcutsITS, track)) continue;
538 fCFM->GetParticleContainer()->Fill(container, AliHFEcuts::kStepHFEcutsITS + 2*(AliHFEcuts::kNcutESDSteps + 1));
539 fCFM->GetParticleContainer()->Fill(&container[3], AliHFEcuts::kStepHFEcutsITS);
541 fCFM->GetParticleContainer()->Fill(&container[3], AliHFEcuts::kStepHFEcutsITS + AliHFEcuts::kNcutESDSteps + 1);
545 // HFEcuts: Nb of tracklets TRD0
546 if(!fCFM->CheckParticleCuts(AliHFEcuts::kStepHFEcutsTRD, track)) continue;
548 fCFM->GetParticleContainer()->Fill(container, AliHFEcuts::kStepHFEcutsTRD + 2*(AliHFEcuts::kNcutESDSteps + 1));
549 fCFM->GetParticleContainer()->Fill(&container[3], AliHFEcuts::kStepHFEcutsTRD);
551 fCFM->GetParticleContainer()->Fill(&container[3], (AliHFEcuts::kStepHFEcutsTRD + (AliHFEcuts::kNcutESDSteps + 1)));
553 // dimensions 3&4&5 : pt,eta,phi (MC)
554 ((THnSparseF *)fCorrelation->At(0))->Fill(container);
558 // mc qa for after the reconstruction cuts
559 AliDebug(2, "Running MC QA");
560 fMCQA->GetDecayedKine(mctrack4QA, AliHFEmcQA::kCharm, AliHFEmcQA::kElectronPDG, 3); // charm
561 fMCQA->GetDecayedKine(mctrack4QA, AliHFEmcQA::kBeauty, AliHFEmcQA::kElectronPDG, 3); // beauty
564 // track accepted, do PID
565 AliHFEpidObject hfetrack;
566 hfetrack.fAnalysisType = AliHFEpidObject::kESDanalysis;
567 hfetrack.fRecTrack = track;
568 if(HasMCData()) hfetrack.fMCtrack = mctrack;
569 if(!fPID->IsSelected(&hfetrack)) continue;
570 nElectronCandidates++;
573 // mc qa for after the reconstruction and pid cuts
574 AliDebug(2, "Running MC QA");
575 fMCQA->GetDecayedKine(mctrack4QA, AliHFEmcQA::kCharm, AliHFEmcQA::kElectronPDG, 4); // charm
576 fMCQA->GetDecayedKine(mctrack4QA, AliHFEmcQA::kBeauty, AliHFEmcQA::kElectronPDG, 4); // beauty
581 fCFM->GetParticleContainer()->Fill(container, AliHFEcuts::kStepHFEcutsTRD +1 + 2*(AliHFEcuts::kNcutESDSteps + 1));
582 fCFM->GetParticleContainer()->Fill(&container[3], AliHFEcuts::kStepHFEcutsTRD + 1);
584 fCFM->GetParticleContainer()->Fill(&container[3], (AliHFEcuts::kStepHFEcutsTRD + 1 + (AliHFEcuts::kNcutESDSteps + 1)));
586 // dimensions 3&4&5 : pt,eta,phi (MC)
587 ((THnSparseF *)fCorrelation->At(1))->Fill(container);
590 // Track selected: distinguish between true and fake
591 AliDebug(1, Form("Candidate Selected, filling THnSparse, PID: %d\n", mctrack->Particle()->GetPdgCode()));
592 if((pid = TMath::Abs(mctrack->Particle()->GetPdgCode())) == 11){
593 Int_t type = IsSignalElectron(track);
594 AliDebug(1, Form("Type: %d\n", type));
596 dataE[4] = type; // beauty[1] or charm[2]
597 dataE[3] = 2; // signal electron
600 dataE[3] = 1; // not a signal electron
603 // pair analysis [mj]
605 AliDebug(2, "Running Secondary Vertex Analysis");
606 fSecVtx->InitAnaPair();
607 for(Int_t jtrack = 0; jtrack < fESD->GetNumberOfTracks(); jtrack++){
608 htrack = fESD->GetTrack(jtrack);
609 if ( itrack == jtrack ) continue;
610 //if( fPID->IsSelected(htrack) && (itrack < jtrack)) continue;
611 if( abs(fSecVtx->GetMCPID(track)) == 11 && (itrack < jtrack)) continue;
612 fSecVtx->AnaPair(track, htrack, jtrack);
614 // based on the partner of e info, you run secandary vertexing function
615 fSecVtx->RunSECVTX(track);
616 } // end of pair analysis
619 // Fill THnSparse with the information for Fake Electrons
623 // fill the performance THnSparse, if the mc origin could be defined
625 AliDebug(1, Form("Entries: [%.3f|%.3f|%.3f|%f|%f]\n", dataE[0],dataE[1],dataE[2],dataE[3],dataE[4]));
626 fPIDperformance->Fill(dataE);
632 fNElectronTracksEvent->Fill(nElectronCandidates);
635 PostData(0, fNEvents);
636 PostData(1, fOutput);
640 //____________________________________________________________
641 void AliAnalysisTaskHFE::Terminate(Option_t *){
643 // Terminate not implemented at the moment
645 if(IsRunningPostProcess()){
646 fOutput = dynamic_cast<TList *>(GetOutputData(1));
648 AliError("Results not available");
655 //____________________________________________________________
656 void AliAnalysisTaskHFE::Load(TString filename){
658 // Load Results into the task
660 fQA = NULL; fOutput = NULL; fNEvents = NULL;
661 TFile *input = TFile::Open(filename.Data());
662 if(!input || input->IsZombie()){
663 AliError("Cannot read file");
666 TH1 *htmp = dynamic_cast<TH1I *>(input->Get("nEvents"));
668 fNEvents = dynamic_cast<TH1I *>(htmp->Clone());
670 AliError("Event Counter histogram not found");
671 TList *ltmp = dynamic_cast<TList *>(input->Get("Results"));
673 fOutput = dynamic_cast<TList *>(ltmp->Clone());
675 AliError("Output Histograms not found");
676 ltmp = dynamic_cast<TList *>(input->Get("QA"));
678 fQA = dynamic_cast<TList *>(ltmp->Clone());
680 AliError("QA histograms not found");
684 if(fNEvents) nObjects++;
685 if(fOutput) nObjects++;
687 AliInfo(Form("Loaded %d Objects into task", nObjects));
690 //____________________________________________________________
691 void AliAnalysisTaskHFE::PostProcess(){
693 // Plotting Ratio histograms
694 // + All electrons / all candidates (Purity for Electrons)
695 // + All signal electrons / all electrons (Purity for signals)
696 // For this the following pt-histograms have to be projected from the THnSparse
697 // + All Electron candidates
698 // + All Real electrons
699 // + All Signal Electrons
700 // + All misidentified electrons
701 // Additionally we draw Efficiency histograms:
702 // + Reconstructible Electrons
703 // + Signal Electrons
704 // + Selected Electrons
705 // + Selected Electrons in Acceptance
708 fPIDperformance = dynamic_cast<THnSparseF *>(fOutput->FindObject("PIDperformance"));
709 if(!fPIDperformance){
710 AliError("PID Performance histogram not found in the output container");
714 // always project to pt dimension
715 // get the histograms under our control
716 TH1 *allCandidates = NULL, *allElectrons = NULL, *allSignals = NULL, *allFakes = NULL;
717 allCandidates = fPIDperformance->Projection(0);
718 allCandidates->SetName("hAllCandidates");
719 allCandidates->SetTitle("All Candidates");
720 allCandidates->Sumw2();
721 Int_t firstDim3 = fPIDperformance->GetAxis(3)->GetFirst(), lastDim3 = fPIDperformance->GetAxis(3)->GetLast();
722 fPIDperformance->GetAxis(3)->SetRange(firstDim3 + 1, lastDim3);
723 allElectrons = fPIDperformance->Projection(0);
724 allElectrons->Sumw2();
725 allElectrons->SetName("hAllElectrons");
726 allElectrons->SetTitle("All Electrons");
727 Int_t firstDim4 = fPIDperformance->GetAxis(4)->GetFirst(), lastDim4 = fPIDperformance->GetAxis(4)->GetLast();
728 fPIDperformance->GetAxis(4)->SetRange(firstDim4 + 1, lastDim4);
729 allSignals = fPIDperformance->Projection(0);
731 allSignals->SetName("hAllSignals");
732 allSignals->SetTitle("All Signal Electrons");
733 fPIDperformance->GetAxis(4)->SetRange(firstDim4, lastDim4); // Reset 4th axis
734 fPIDperformance->GetAxis(3)->SetRange(firstDim3, firstDim3); // Select fakes
735 allFakes = fPIDperformance->Projection(0);
737 allFakes->SetName("hAllFakes");
738 allFakes->SetTitle("All Fakes");
739 fPIDperformance->GetAxis(3)->SetRange(firstDim3, lastDim3); // Reset also 3rd axis
742 TH1D *electronPurity = dynamic_cast<TH1D *>(allElectrons->Clone());
743 electronPurity->Divide(allCandidates);
744 electronPurity->SetName("electronPurity");
745 electronPurity->SetTitle("Electron Purity");
746 electronPurity->GetXaxis()->SetTitle("p_{T} / GeV/c");
747 electronPurity->GetYaxis()->SetTitle("Purity / %");
748 TH1D *signalPurity = dynamic_cast<TH1D *>(allSignals->Clone());
749 signalPurity->Divide(allElectrons);
750 signalPurity->SetName("signalPurity");
751 signalPurity->SetTitle("Purity of Electrons coming from Heavy flavours");
752 signalPurity->GetXaxis()->SetTitle("p_{T} / GeV/c");
753 signalPurity->GetYaxis()->SetTitle("Purity / %");
754 TH1D *fakeContamination = dynamic_cast<TH1D *>(allFakes->Clone());
755 fakeContamination->Divide(allCandidates);
756 fakeContamination->SetName("fakeContamination");
757 fakeContamination->SetTitle("Contamination of misidentified hadrons");
758 fakeContamination->GetXaxis()->SetTitle("p_{T} / GeV/c");
759 fakeContamination->GetYaxis()->SetTitle("Purity / %");
762 const Int_t nHistos = 7;
763 TH1 *hptr[7] = {allCandidates, allElectrons, allSignals, allFakes, electronPurity, signalPurity, fakeContamination}, *histo;
764 for(Int_t ihist = 0; ihist < nHistos; ihist++){
765 (histo = hptr[ihist])->SetStats(kFALSE);
766 histo->SetLineColor(kBlack);
767 histo->SetMarkerColor(kBlue);
768 histo->SetMarkerStyle(22);
771 // Make percent output
772 electronPurity->Scale(100);
773 signalPurity->Scale(100);
774 fakeContamination->Scale(100);
777 TCanvas *cSpectra = new TCanvas("cSpectra","pt Spectra", 800, 600);
778 cSpectra->Divide(2,2);
779 TCanvas *cRatios = new TCanvas("cRatios", "Ratio Plots", 800, 600);
780 cRatios->Divide(2,2);
783 allCandidates->GetXaxis()->SetTitle("p_{T} / GeV/c");
784 allCandidates->GetYaxis()->SetTitle("dN/dp_{T} 1/GeV/c");
785 allCandidates->Draw("e");
788 allElectrons->GetXaxis()->SetTitle("p_{T} / GeV/c");
789 allElectrons->GetYaxis()->SetTitle("dN/dp_{T} 1/GeV/c");
790 allElectrons->Draw("e");
793 allSignals->GetXaxis()->SetTitle("p_{T} / GeV/c");
794 allSignals->GetYaxis()->SetTitle("dN/dp_{T} 1/GeV/c");
795 allSignals->Draw("e");
798 allFakes->GetXaxis()->SetTitle("p_{T} / GeV/c");
799 allFakes->GetYaxis()->SetTitle("dN/dp_{T} 1/GeV/c");
802 electronPurity->Draw("e");
804 signalPurity->Draw("e");
806 fakeContamination->Draw("e");
808 // Now draw the Efficiency
810 // + InAcceptance / Generated
811 // + Signal / Generated
812 // + Selected / Generated
813 // + Selected / InAcceptance (Reconstructible)
814 TCanvas *cEff = new TCanvas("cEff", "Efficiency", 800, 600);
816 AliCFContainer *effc = dynamic_cast<AliCFContainer *>(fOutput->At(0));
818 AliError("Efficiency Container not found in Output Container");
821 AliCFEffGrid *effCalc = new AliCFEffGrid("effCalc", "Efficiency Calculation Grid", *effc);
822 effCalc->CalculateEfficiency(AliHFEcuts::kStepMCInAcceptance, AliHFEcuts::kStepMCGenerated);
823 TH1 *effReconstructibleP = effCalc->Project(0);
824 effReconstructibleP->SetName("effReconstructibleP");
825 effReconstructibleP->SetTitle("Efficiency of reconstructible tracks");
826 effReconstructibleP->GetXaxis()->SetTitle("p_{T} / GeV/c");
827 effReconstructibleP->GetYaxis()->SetTitle("Efficiency");
828 effReconstructibleP->GetYaxis()->SetRangeUser(0.,1.);
829 effReconstructibleP->SetMarkerStyle(22);
830 effReconstructibleP->SetMarkerColor(kBlue);
831 effReconstructibleP->SetLineColor(kBlack);
832 effReconstructibleP->SetStats(kFALSE);
834 effReconstructibleP->Draw("e");
835 effCalc->CalculateEfficiency(AliHFEcuts::kStepMCsignal, AliHFEcuts::kStepMCGenerated);
836 TH1 *effSignal = effCalc->Project(0);
837 effSignal->SetName("effSignal");
838 effSignal->SetTitle("Efficiency of Signal Electrons");
839 effSignal->GetXaxis()->SetTitle("p_{T} / GeV/c");
840 effSignal->GetYaxis()->SetTitle("Efficiency");
841 effSignal->GetYaxis()->SetRangeUser(0., 1.);
842 effSignal->SetMarkerStyle(22);
843 effSignal->SetMarkerColor(kBlue);
844 effSignal->SetLineColor(kBlack);
845 effSignal->SetStats(kFALSE);
847 effSignal->Draw("e");
848 effCalc->CalculateEfficiency(AliHFEcuts::kStepHFEcutsTRD + 1, AliHFEcuts::kStepMCGenerated);
849 TH1 *effPIDP = effCalc->Project(0);
850 effPIDP->SetName("effPIDP");
851 effPIDP->SetTitle("Efficiency of selected tracks");
852 effPIDP->GetXaxis()->SetTitle("p_{T} / GeV/c");
853 effPIDP->GetYaxis()->SetTitle("Efficiency");
854 effPIDP->GetYaxis()->SetRangeUser(0.,1.);
855 effPIDP->SetMarkerStyle(22);
856 effPIDP->SetMarkerColor(kBlue);
857 effPIDP->SetLineColor(kBlack);
858 effPIDP->SetStats(kFALSE);
861 effCalc->CalculateEfficiency(AliHFEcuts::kStepHFEcutsTRD + 1, AliHFEcuts::kStepMCInAcceptance);
862 TH1 *effPIDAcc = effCalc->Project(0);
863 effPIDAcc->SetName("effPIDAcc");
864 effPIDAcc->SetTitle("Efficiency of selected tracks in acceptance");
865 effPIDAcc->GetXaxis()->SetTitle("p_{T} / GeV/c");
866 effPIDAcc->GetYaxis()->SetTitle("Efficiency");
867 effPIDAcc->GetYaxis()->SetRangeUser(0.,1.);
868 effPIDAcc->SetMarkerStyle(22);
869 effPIDAcc->SetMarkerColor(kBlue);
870 effPIDAcc->SetLineColor(kBlack);
871 effPIDAcc->SetStats(kFALSE);
873 effPIDAcc->Draw("e");
877 //delete allCandidates; delete allElectrons; delete allSignals; delete allFakes;
878 //delete electronPurity; delete signalPurity; delete fakeContamination;
881 //____________________________________________________________
882 void AliAnalysisTaskHFE::MakeParticleContainer(){
884 // Create the particle container for the correction framework manager and
887 const Int_t kNvar = 3 ; //number of variables on the grid:pt,eta, phi
888 const Double_t kPtmin = 0.1, kPtmax = 10.;
889 const Double_t kEtamin = -0.9, kEtamax = 0.9;
890 const Double_t kPhimin = 0., kPhimax = 2. * TMath::Pi();
892 //arrays for the number of bins in each dimension
894 iBin[0] = 40; //bins in pt
895 iBin[1] = 8; //bins in eta
896 iBin[2] = 18; // bins in phi
898 //arrays for lower bounds :
899 Double_t* binEdges[kNvar];
900 for(Int_t ivar = 0; ivar < kNvar; ivar++)
901 binEdges[ivar] = new Double_t[iBin[ivar] + 1];
903 //values for bin lower bounds
904 for(Int_t i=0; i<=iBin[0]; i++) binEdges[0][i]=(Double_t)TMath::Power(10,TMath::Log10(kPtmin) + (TMath::Log10(kPtmax)-TMath::Log10(kPtmin))/iBin[0]*(Double_t)i);
905 for(Int_t i=0; i<=iBin[1]; i++) binEdges[1][i]=(Double_t)kEtamin + (kEtamax-kEtamin)/iBin[1]*(Double_t)i;
906 for(Int_t i=0; i<=iBin[2]; i++) binEdges[2][i]=(Double_t)kPhimin + (kPhimax-kPhimin)/iBin[2]*(Double_t)i;
908 //one "container" for MC
909 AliCFContainer* container = new AliCFContainer("container","container for tracks", (AliHFEcuts::kNcutSteps + 1 + 2*(AliHFEcuts::kNcutESDSteps + 1)), kNvar, iBin);
911 //setting the bin limits
912 for(Int_t ivar = 0; ivar < kNvar; ivar++)
913 container -> SetBinLimits(ivar, binEdges[ivar]);
914 fCFM->SetParticleContainer(container);
916 //create correlation matrix for unfolding
917 Int_t thnDim[2*kNvar];
918 for (int k=0; k<kNvar; k++) {
919 //first half : reconstructed
922 thnDim[k+kNvar] = iBin[k];
925 if(!fCorrelation) fCorrelation = new TList();
926 fCorrelation->SetName("correlation");
928 THnSparseF *correlation0 = new THnSparseF("correlationstepbeforePID","THnSparse with correlations",2*kNvar,thnDim);
929 THnSparseF *correlation1 = new THnSparseF("correlationstepafterPID","THnSparse with correlations",2*kNvar,thnDim);
930 for (int k=0; k<kNvar; k++) {
931 correlation0->SetBinEdges(k,binEdges[k]);
932 correlation0->SetBinEdges(k+kNvar,binEdges[k]);
933 correlation1->SetBinEdges(k,binEdges[k]);
934 correlation1->SetBinEdges(k+kNvar,binEdges[k]);
936 correlation0->Sumw2();
937 correlation1->Sumw2();
939 fCorrelation->AddAt(correlation0,0);
940 fCorrelation->AddAt(correlation1,1);
942 // Add a histogram for Fake electrons
944 Int_t nBin[nDim] = {40, 8, 18, 3, 3};
945 Double_t* binEdges2[nDim];
946 for(Int_t ivar = 0; ivar < nDim; ivar++)
947 binEdges2[ivar] = new Double_t[nBin[ivar] + 1];
949 //values for bin lower bounds
950 for(Int_t i=0; i<=nBin[0]; i++) binEdges2[0][i]=(Double_t)TMath::Power(10,TMath::Log10(kPtmin) + (TMath::Log10(kPtmax)-TMath::Log10(kPtmin))/nBin[0]*(Double_t)i);
951 for(Int_t i=0; i<=nBin[1]; i++) binEdges2[1][i]=(Double_t)kEtamin + (kEtamax-kEtamin)/nBin[1]*(Double_t)i;
952 for(Int_t i=0; i<=nBin[2]; i++) binEdges2[2][i]=(Double_t)kPhimin + (kPhimax-kPhimin)/nBin[2]*(Double_t)i;
953 for(Int_t i=0; i<=nBin[3]; i++) binEdges2[3][i] = i;
954 for(Int_t i=0; i<=nBin[4]; i++) binEdges2[4][i] = i;
956 fPIDperformance = new THnSparseF("PIDperformance", "PID performance; pT [GeV/c]; theta [rad]; phi [rad] type (0 - not el, 1 - other el, 2 - HF el; flavor (0 - no, 1 - charm, 2 - bottom)", nDim, nBin);
957 for(Int_t idim = 0; idim < nDim; idim++)
958 fPIDperformance->SetBinEdges(idim, binEdges2[idim]);
961 //____________________________________________________________
962 void AliAnalysisTaskHFE::AddPIDdetector(Char_t *detector){
964 // Adding PID detector to the task
966 if(!fPIDdetectors.Length())
967 fPIDdetectors = detector;
969 fPIDdetectors += Form(":%s", detector);
972 //____________________________________________________________
973 void AliAnalysisTaskHFE::PrintStatus() const {
975 // Print Analysis status
977 printf("\n\tAnalysis Settings\n\t========================================\n\n");
978 printf("\tSecondary Vertex finding: %s\n", IsSecVtxOn() ? "YES" : "NO");
979 printf("\tPrimary Vertex resolution: %s\n", IsPriVtxOn() ? "YES" : "NO");
981 printf("\tParticle Identification Detectors:\n");
982 TObjArray *detectors = fPIDdetectors.Tokenize(":");
983 for(Int_t idet = 0; idet < detectors->GetEntries(); idet++)
984 printf("\t\t%s\n", (dynamic_cast<TObjString *>(detectors->At(idet)))->String().Data());
987 printf("\t\tPID: %s\n", IsQAOn(kPIDqa) ? "YES" : "NO");
988 printf("\t\tCUTS: %s\n", (fCuts != NULL && fCuts->IsInDebugMode()) ? "YES" : "NO");
989 printf("\t\tMC: %s\n", IsQAOn(kMCqa) ? "YES" : "NO");
993 //____________________________________________________________
994 AliAnalysisTaskHFE::LabelContainer::LabelContainer(Int_t capacity):
1002 // Default constructor
1004 fContainer = new Int_t[capacity];
1005 fBegin = &fContainer[0];
1006 fEnd = &fContainer[capacity - 1];
1007 fLast = fCurrent = fBegin;
1010 //____________________________________________________________
1011 Bool_t AliAnalysisTaskHFE::LabelContainer::Append(Int_t label){
1013 // Add Label to the container
1015 if(fLast > fEnd) return kFALSE;
1020 //____________________________________________________________
1021 Bool_t AliAnalysisTaskHFE::LabelContainer::Find(Int_t label) const {
1023 // Find track in the list of labels
1025 for(Int_t *entry = fBegin; entry <= fLast; entry++)
1026 if(*entry == label) return kTRUE;
1030 //____________________________________________________________
1031 Int_t AliAnalysisTaskHFE::LabelContainer::Next(){
1035 if(fCurrent > fLast) return -1;
1039 //____________________________________________________________
1040 Int_t AliAnalysisTaskHFE::IsSignalElectron(AliVParticle *fTrack) const{
1042 // Checks whether the identified electron track is coming from heavy flavour
1043 // returns 0 in case of no signal, 1 in case of charm and 2 in case of Bottom
1050 AliMCParticle *mctrack = NULL;
1051 TString objname = fTrack->IsA()->GetName();
1052 if(!objname.CompareTo("AliESDtrack")){
1053 AliDebug(2, "Checking signal for ESD track");
1054 AliESDtrack *esdtrack = dynamic_cast<AliESDtrack *>(fTrack);
1055 mctrack = dynamic_cast<AliMCParticle *>(fMC->GetTrack(TMath::Abs(esdtrack->GetLabel())));
1057 else if(!objname.CompareTo("AliAODtrack")){
1058 AliError("AOD Analysis not implemented yet");
1061 else if(!objname.CompareTo("AliMCParticle")){
1062 AliDebug(2, "Checking signal for MC track");
1063 mctrack = dynamic_cast<AliMCParticle *>(fTrack);
1066 AliError("Input object not supported");
1069 if(!mctrack) return kNoSignal;
1070 TParticle *ecand = mctrack->Particle();
1071 if(TMath::Abs(ecand->GetPdgCode()) != 11) return kNoSignal; // electron candidate not true electron
1072 Int_t motherLabel = TMath::Abs(ecand->GetFirstMother());
1073 AliDebug(3, Form("mother label: %d\n", motherLabel));
1074 if(!motherLabel) return kNoSignal; // mother track unknown
1075 AliMCParticle *motherTrack = dynamic_cast<AliMCParticle *>(fMC->GetTrack(motherLabel));
1076 if(!motherTrack) return kNoSignal;
1077 TParticle *mparticle = motherTrack->Particle();
1078 Int_t pid = TMath::Abs(mparticle->GetPdgCode());
1079 AliDebug(3, Form("PDG code: %d\n", pid));
1081 // identify signal according to Pdg Code
1082 if((pid % 1000) / 100 == 4) return kCharm; // charmed meson, 3rd position in pdg code == 4
1083 if(pid / 1000 == 4) return kCharm; // charmed baryon, 4th position in pdg code == 4
1084 if((pid % 1000) / 100 == 5) return kBeauty; // beauty meson, 3rd position in pdg code == 5
1085 if(pid / 1000 == 5) return kBeauty; // beauty baryon, 4th position in pdg code == 5
1089 //__________________________________________
1090 Float_t AliAnalysisTaskHFE::GetRapidity(TParticle *part) const
1096 if(!((part->Energy() - part->Pz())*(part->Energy() + part->Pz())>0)) rapidity=-999;
1097 else rapidity = 0.5*(TMath::Log((part->Energy()+part->Pz()) / (part->Energy()-part->Pz())));