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 **************************************************************************/
16 // QA class for TRD PID
17 // Plot Pion Efficiency at x electron efficiency
18 // Calculate the threshold parametrisation and save
19 // them in a root file
22 // Markus Fasel <M.Fasel@gsi.de>
31 #include <TGraphErrors.h>
32 #include <THnSparse.h>
35 #include <TIterator.h>
39 #include <TObjArray.h>
42 #include "AliAODTrack.h"
43 #include "AliAODPid.h"
44 #include "AliESDtrack.h"
45 #include "AliHFEtrdPIDqa.h"
46 #include "AliHFEtools.h"
47 #include "AliHFEpidTRD.h"
50 ClassImp(AliHFEtrdPIDqa)
52 const Double_t AliHFEtrdPIDqa::fgkElectronEff[kNElectronEffs] = {0.7,0.75, 0.8, 0.85, 0.9, 0.95};
53 //_______________________________________________________________
54 // Definition of the common binning
55 const Int_t AliHFEtrdPIDqa::fgkNBinsCommon[kQuantitiesCommon] = {
56 AliPID::kSPECIES + 1, // species
58 AliESDtrack::kTRDnPlanes + 1 // tracklets including 0
60 const Double_t AliHFEtrdPIDqa::fgkMinBinCommon[kQuantitiesCommon] = {
63 0 // tracklets including 0
66 const Double_t AliHFEtrdPIDqa::fgkMaxBinCommon[kQuantitiesCommon] = {
67 AliPID::kSPECIES, // species
69 AliESDtrack::kTRDnPlanes + 1 // tracklets including 0
71 //_______________________________________________________________
73 //__________________________________________________________________
74 AliHFEtrdPIDqa::AliHFEtrdPIDqa():
75 TNamed("trdPIDqa", ""),
78 fPionEfficiencies(NULL),
79 fProtonEfficiencies(NULL),
80 fKaonEfficiencies(NULL),
83 fTotalChargeInSlice0(kFALSE)
86 // Default Constructor
90 //__________________________________________________________________
91 AliHFEtrdPIDqa::AliHFEtrdPIDqa(const Char_t *name):
95 fPionEfficiencies(NULL),
96 fProtonEfficiencies(NULL),
97 fKaonEfficiencies(NULL),
100 fTotalChargeInSlice0(kFALSE)
107 //__________________________________________________________________
108 AliHFEtrdPIDqa::AliHFEtrdPIDqa(const AliHFEtrdPIDqa &ref):
112 fPionEfficiencies(NULL),
113 fProtonEfficiencies(NULL),
114 fKaonEfficiencies(NULL),
116 fShowMessage(kFALSE),
117 fTotalChargeInSlice0(ref.fTotalChargeInSlice0)
125 //__________________________________________________________________
126 AliHFEtrdPIDqa &AliHFEtrdPIDqa::operator=(const AliHFEtrdPIDqa &ref){
128 // Assignment operator
135 //__________________________________________________________________
136 AliHFEtrdPIDqa::~AliHFEtrdPIDqa(){
140 if(fTRDpid) delete fTRDpid;
141 if(fHistos) delete fHistos;
142 if(fPionEfficiencies) delete fPionEfficiencies;
143 if(fProtonEfficiencies) delete fProtonEfficiencies;
144 if(fKaonEfficiencies) delete fKaonEfficiencies;
147 //__________________________________________________________________
148 void AliHFEtrdPIDqa::Copy(TObject &ref) const{
150 // Copies content of this object into object ref
154 AliHFEtrdPIDqa &target = dynamic_cast<AliHFEtrdPIDqa &>(ref);
155 target.fTRDpid = fTRDpid;
156 target.fHistos = dynamic_cast<AliHFEcollection *>(fHistos->Clone());
157 target.fTotalChargeInSlice0 = fTotalChargeInSlice0;
160 //__________________________________________________________________
161 Long64_t AliHFEtrdPIDqa::Merge(TCollection *coll){
166 if(coll->IsEmpty()) return 1;
168 AliHFEtrdPIDqa *refQA = NULL;
174 refQA = dynamic_cast<AliHFEtrdPIDqa *>(o);
177 listHistos.Add(refQA->fHistos);
180 fHistos->Merge(&listHistos);
184 //__________________________________________________________________
185 void AliHFEtrdPIDqa::Browse(TBrowser *b){
187 // Enable Browser functionality
190 // Add objects to the browser
191 if(fHistos) b->Add(fHistos, fHistos->GetName());
192 if(fPionEfficiencies) b->Add(fPionEfficiencies, "Pion Efficiencies");
193 if(fProtonEfficiencies) b->Add(fProtonEfficiencies, "Proton Efficiencies");
194 if(fKaonEfficiencies) b->Add(fKaonEfficiencies, "Kaon Efficiencies");
195 if(fThresholds) b->Add(fThresholds, "Thresholds");
199 //__________________________________________________________________
200 void AliHFEtrdPIDqa::Init(){
205 fHistos = new AliHFEcollection("TRDqa", "Histos for TRD QA");
207 CreateLikelihoodHistogram();
209 CreatedEdxHistogram();
210 CreateHistoTruncatedMean();
212 fTRDpid = new AliHFEpidTRD("QAtrdPID");
215 //__________________________________________________________________
216 void AliHFEtrdPIDqa::CreateLikelihoodHistogram(){
218 // Create Histogram for TRD Likelihood Studies
220 Int_t nbins[kQuantitiesLike]; memcpy(nbins, fgkNBinsCommon, sizeof(Int_t) * kQuantitiesCommon);
221 nbins[kElectronLike] = 100;
222 nbins[kNClustersLike] = 200;
223 Double_t binMin[kQuantitiesLike]; memcpy(binMin, fgkMinBinCommon, sizeof(Double_t) * kQuantitiesCommon);
224 Double_t binMax[kQuantitiesLike]; memcpy(binMax, fgkMaxBinCommon, sizeof(Double_t) * kQuantitiesCommon);
225 binMin[kElectronLike] = 0.;
226 binMin[kNClustersLike] = 0.;
227 binMax[kElectronLike] = 1.;
228 binMax[kNClustersLike] = 200.;
230 fHistos->CreateTHnSparse("fLikeTRD","TRD Likelihood Studies", kQuantitiesLike, nbins, binMin, binMax);
231 fHistos->BinLogAxis("fLikeTRD", kP);
234 //__________________________________________________________________
235 void AliHFEtrdPIDqa::CreateQAHistogram(){
237 // Create Histogram for Basic TRD PID QA
239 AliDebug(1, "Called");
240 Int_t nbins[kQuantitiesQA]; memcpy(nbins, fgkNBinsCommon, sizeof(Int_t) * kQuantitiesCommon);
241 nbins[kNonZeroTrackletCharge] = AliESDtrack::kTRDnPlanes + 1;
242 nbins[kNClusters] = 200;
243 Double_t binMin[kQuantitiesQA]; memcpy(binMin, fgkMinBinCommon, sizeof(Double_t) * kQuantitiesCommon);
244 binMin[kNonZeroTrackletCharge] = 0.;
245 binMin[kNClusters] = 0.;
246 Double_t binMax[kQuantitiesQA]; memcpy(binMax, fgkMaxBinCommon, sizeof(Double_t) * kQuantitiesCommon);
247 binMax[kNonZeroTrackletCharge] = AliESDtrack::kTRDnPlanes + 1.;
248 binMax[kNClusters] = 200.;
250 fHistos->CreateTHnSparse("fQAtrack","TRD QA Histogram", kQuantitiesQA, nbins, binMin, binMax);
251 fHistos->BinLogAxis("fQAtrack", kP);
254 //__________________________________________________________________
255 void AliHFEtrdPIDqa::CreatedEdxHistogram(){
257 // Create QA histogram for dEdx investigations
259 AliDebug(1, "Called");
260 Int_t nbins[kQuantitiesdEdx]; memcpy(nbins, fgkNBinsCommon, sizeof(Int_t) * kQuantitiesCommon);
262 nbins[kNclusters] = 261;
263 nbins[kNonZeroSlices] = 9;
264 Double_t binMin[kQuantitiesdEdx]; memcpy(binMin, fgkMinBinCommon, sizeof(Double_t) * kQuantitiesCommon);
266 binMin[kNclusters] = 0;
267 binMin[kNonZeroSlices] = 0.;
268 Double_t binMax[kQuantitiesdEdx]; memcpy(binMax, fgkMaxBinCommon, sizeof(Double_t) * kQuantitiesCommon);
269 binMax[kdEdx] = 10000.;
270 binMax[kNclusters] = 260.;
271 binMax[kNonZeroSlices] = 8.;
273 fHistos->CreateTHnSparse("fQAdEdx","TRD summed dEdx", kQuantitiesdEdx, nbins, binMin, binMax);
274 fHistos->BinLogAxis("fQAdEdx", kP);
275 fHistos->Sumw2("fQAdEdx");
278 //__________________________________________________________________
279 void AliHFEtrdPIDqa::CreateHistoTruncatedMean(){
281 // Create Histogram for Basic TRD PID QA:
283 AliDebug(1, "Called");
284 Int_t nbins[kQuantitiesTruncMean]; memcpy(nbins, fgkNBinsCommon, sizeof(Int_t) * kQuantitiesCommon);
285 nbins[kTPCdEdx] = 600;
286 nbins[kTRDdEdxMethod1] = 1000;
287 nbins[kTRDdEdxMethod2] = 1000;
288 Double_t binMin[kQuantitiesTruncMean]; memcpy(binMin, fgkMinBinCommon, sizeof(Double_t) * kQuantitiesCommon);
289 binMin[kTPCdEdx] = 0.;
290 binMin[kTRDdEdxMethod1] = 0.;
291 binMin[kTRDdEdxMethod2] = 0.;
292 Double_t binMax[kQuantitiesTruncMean]; memcpy(binMax, fgkMaxBinCommon, sizeof(Double_t) * kQuantitiesCommon);
293 binMax[kTPCdEdx] = 600;
294 binMax[kTRDdEdxMethod1] = 20000.;
295 binMax[kTRDdEdxMethod2] = 20000.;
297 fHistos->CreateTHnSparse("fTRDtruncMean","TRD TruncatedMean studies", kQuantitiesTruncMean, nbins, binMin, binMax);
298 fHistos->BinLogAxis("fTRDtruncMean", kP);
299 fHistos->CreateTH2F("fTRDslicesPions","TRD dEdx per slice for Pions", 8, 0, 8, 2000, 0, 8000);
300 fHistos->CreateTH2F("fTRDslicesElectrons","TRD dEdx per slice for Electrons", 8, 0, 8, 2000, 0, 8000);
304 //__________________________________________________________________
305 void AliHFEtrdPIDqa::ProcessTracks(const TObjArray * const tracks, Int_t species){
307 // Process Electron Tracks
309 if(species < -1 || species >= AliPID::kSPECIES) return;
311 const AliVTrack *track = NULL;
312 while((track = dynamic_cast<const AliVTrack *>(it()))){
313 if(track) ProcessTrack(track, species);
317 //__________________________________________________________________
318 void AliHFEtrdPIDqa::ProcessTrack(const AliVTrack * const track, Int_t species){
320 // Process Single Track
322 if(TString(track->IsA()->GetName()).CompareTo("AliESDtrack") == 0)
323 ProcessTrackESD(dynamic_cast<const AliESDtrack *>(track), species);
324 else if(TString(track->IsA()->GetName()).CompareTo("AliAODTrack") == 0)
325 ProcessTrackAOD(dynamic_cast<const AliAODTrack *>(track), species);
329 //__________________________________________________________________
330 void AliHFEtrdPIDqa::ProcessTrackESD(const AliESDtrack *track, Int_t species){
332 // Process single ESD track
335 if((track->GetStatus() & AliESDtrack::kTRDout) == 0) return; // require TRD track
336 FillTRDLikelihoods(track, species);
337 FillTRDQAplots(track, species);
340 //__________________________________________________________________
341 void AliHFEtrdPIDqa::ProcessTrackAOD(const AliAODTrack * const track, Int_t /*species*/){
343 // Process single AOD track
344 // AOD PID object required
347 AliAODPid *trackPID = track->GetDetPid();
348 if(!trackPID) return;
352 //__________________________________________________________________
353 void AliHFEtrdPIDqa::FillTRDLikelihoods(const AliESDtrack * const track, Int_t species){
355 // Fill TRD Likelihood Histogram
357 Double_t trdLike[AliPID::kSPECIES];
358 track->GetTRDpid(trdLike);
360 Double_t norm =trdLike[AliPID::kElectron]+trdLike[AliPID::kPion];
361 Double_t likeEle = norm == 0. ? 0. : trdLike[AliPID::kElectron]/norm;
362 const AliExternalTrackParam *outerPars = track->GetOuterParam();
364 Double_t quantities[kQuantitiesLike]; memset(quantities, 0, sizeof(Double_t) * kQuantitiesLike);
369 // Electron Likelihood
370 quantities[kSpecies] = species;
371 quantities[kP] = outerPars ? outerPars->P() : track->P();
372 quantities[kNTracklets] = track->GetTRDntrackletsPID();
373 quantities[kElectronLike] = likeEle;
374 quantities[kNClustersLike] = track->GetTRDncls();
376 fHistos->Fill("fLikeTRD", quantities);
379 //__________________________________________________________________
380 void AliHFEtrdPIDqa::FillTRDQAplots(const AliESDtrack * const track, Int_t species){
382 // Fill QA Plots containing further information
384 const AliExternalTrackParam *outerPars = track->GetOuterParam();
386 Double_t quantitiesQA[kQuantitiesQA], quantitiesdEdx[kQuantitiesdEdx], quantitiesTruncMean[kQuantitiesTruncMean];
392 // Non-zero tracklet charges
393 // Number of clusters / full track
404 quantitiesQA[kSpecies] = quantitiesdEdx[kSpecies]
405 = quantitiesTruncMean[kSpecies]
407 quantitiesQA[kP] = quantitiesTruncMean[kP]
408 = outerPars ? outerPars->P() : track->P();
409 quantitiesQA[kNTracklets] = quantitiesdEdx[kNTracklets]
410 = quantitiesTruncMean[kNTracklets]
411 = track->GetTRDntrackletsPID();
412 quantitiesQA[kNClusters] = quantitiesdEdx[kNclusters] = track->GetTRDncls();
415 Double_t dEdxSum = 0., qSlice = 0.;
416 // remove the last slice from the histogram
417 Int_t ntrackletsNonZero = 0, nSlices = track->GetNumberOfTRDslices(), nSlicesNonZero = 0;
418 TString speciesname = "pions";
419 Bool_t selectedForSlicemon = kFALSE;
422 case AliPID::kElectron: speciesname = "Electrons"; selectedForSlicemon = kTRUE; break;
423 case AliPID::kPion: speciesname = "Pions"; selectedForSlicemon = kTRUE; break;
424 default: speciesname = "undefined"; selectedForSlicemon = kFALSE; break;
426 AliDebug(1, Form("species %d, speciesname %s, momentum %f, selected %s", species, speciesname.Data(), track->P(), selectedForSlicemon ? "yes" : "no"));
427 for(Int_t iplane = 0; iplane < AliESDtrack::kTRDnPlanes; iplane++){
428 quantitiesdEdx[kP] = track->GetTRDmomentum(iplane);
430 for(Int_t islice = 0; islice < nSlices; islice++){
431 if(fTotalChargeInSlice0 && islice >= 7) break;
432 qSlice = track->GetTRDslice(iplane, fTotalChargeInSlice0 ? islice + 1 : islice); // hack by mfasel: For data with the new reconstruction, slice 0 is used to store the total charge, the total number of slices is 7 instead of 8
437 // Reweighting of the slices for the truncated mean: select all pion tracks above
438 // 1.5 GeV and monitor the dEdx as function of slice
439 if(selectedForSlicemon && track->P() > 1.5){
440 AliDebug(2, Form("Filling Histogram fTRDslices%s", speciesname.Data()));
441 fHistos->Fill(Form("fTRDslices%s", speciesname.Data()), static_cast<Double_t>(islice), qSlice);
445 quantitiesdEdx[kNonZeroSlices] = nSlicesNonZero;
446 quantitiesdEdx[kdEdx] = fTotalChargeInSlice0 ? track->GetTRDslice(iplane, 0) : dEdxSum; // hack by mfasel: In the new reconstruction, the total charge is stored in the first slice, in the old reconstruction it has to be calculated from the slice charges.
447 if(dEdxSum) ntrackletsNonZero++;
448 // Fill dEdx histogram
449 if(dEdxSum > 1e-1) fHistos->Fill("fQAdEdx", quantitiesdEdx); // Cut out 0 entries
451 quantitiesQA[kNonZeroTrackletCharge] = ntrackletsNonZero;
452 fHistos->Fill("fQAtrack", quantitiesQA);
454 quantitiesTruncMean[kTPCdEdx] = track->GetTPCsignal();
455 quantitiesTruncMean[kTRDdEdxMethod1] = fTRDpid->GetTRDSignalV1(track, 0.6);
456 quantitiesTruncMean[kTRDdEdxMethod2] = fTRDpid->GetTRDSignalV2(track, 0.6);
457 fHistos->Fill("fTRDtruncMean", quantitiesTruncMean);
460 /////////////////////////////////////////////////////////
462 // Code for Post Processing
464 // //////////////////////////////////////////////////////
466 //__________________________________________________________________
467 void AliHFEtrdPIDqa::FinishAnalysis(){
470 // Calculate Electron Efficiency for ntracklets = 4...6
471 // Calculate thresholds for ntracklets = 4...6
474 if(!fPionEfficiencies){
475 fPionEfficiencies = new TList;
476 fPionEfficiencies->SetName("pionEfficiencies");
477 fPionEfficiencies->SetOwner();
479 if(!fProtonEfficiencies){
480 fProtonEfficiencies = new TList;
481 fProtonEfficiencies->SetName("protonEfficiencies");
482 fProtonEfficiencies->SetOwner();
485 fThresholds = new TList;
486 fThresholds->SetName("thresholds");
487 fThresholds->SetOwner();
490 for(Int_t itr = 4; itr <= 6; itr++){
492 printf("========================================\n");
493 printf("Analysing %d trackltes\n", itr);
494 printf("========================================\n");
496 AnalyseNTracklets(itr);
500 //__________________________________________________________________
501 void AliHFEtrdPIDqa::StoreResults(const Char_t *filename){
503 // Store histos into a root file
505 TFile *outfile = new TFile(filename, "RECREATE");
507 fPionEfficiencies->Clone()->Write(fPionEfficiencies->GetName(), kSingleKey);
508 fProtonEfficiencies->Clone()->Write(fProtonEfficiencies->GetName(), kSingleKey);
509 fThresholds->Clone()->Write(fThresholds->GetName(), kSingleKey);
514 //__________________________________________________________________
515 void AliHFEtrdPIDqa::SaveThresholdParameters(const Char_t *name, Double_t lowerLimit, Double_t upperLimit){
517 // Fit the threshold histograms with the given parametrisation
518 // and store the TF1 in the file
522 AliError("Threshold histograms have to be created first");
527 printf("========================================\n");
528 printf("Calculating threshold parameters\n");
529 printf("========================================\n");
532 TList *outlist = new TList;
533 outlist->SetName("thresholdTRD");
535 TGraph *threshhist = NULL;
536 TF1 *threshparam = NULL;
537 TList *lHistos = NULL, *lFormulas = NULL;
538 for(Int_t itracklet = 4; itracklet <= 6; itracklet++){
541 printf("-------------------------------\n");
542 printf("Processing %d tracklets\n", itracklet);
543 printf("-------------------------------\n");
546 lHistos = dynamic_cast<TList *>(fThresholds->FindObject(Form("%dTracklets", itracklet)));
548 AliError(Form("Threshold histograms for the case %d tracklets not found", itracklet));
551 lFormulas = new TList;
552 lFormulas->SetName(Form("%dTracklets", itracklet));
553 outlist->Add(lFormulas);
555 for(Int_t ieff = 0; ieff < kNElectronEffs; ieff++){
558 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
559 printf("Processing Electron Efficiency %f\n", fgkElectronEff[ieff]);
560 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
563 threshhist = dynamic_cast<TGraph *>(lHistos->FindObject(Form("eff%d", static_cast<Int_t>(fgkElectronEff[ieff] * 100))));
564 if(!threshhist) continue;
565 threshparam = MakeThresholds(threshhist, lowerLimit, upperLimit);
566 threshparam->SetName(Form("thresh_%d_%d", itracklet, static_cast<Int_t>(fgkElectronEff[ieff] * 100)));
567 lFormulas->Add(threshparam);
572 TFile *outfile = new TFile(name, "RECREATE");
574 outlist->Write(outlist->GetName(), kSingleKey);
579 //__________________________________________________________________
580 void AliHFEtrdPIDqa::AnalyseNTracklets(Int_t nTracklets){
582 // Calculate Pion Efficiency, Proton Efficiency and Kaon Efficiency at discrete
583 // elPion Efficiency, Proton Efficiency and Kaon Efficiency at discrete
584 // electron efficiencies
586 THnSparse *hLikeTRD = dynamic_cast<THnSparseF *>(fHistos->Get("fLikeTRD"));
588 AliError("Likelihood Histogram not available");
591 Int_t binTracklets = hLikeTRD->GetAxis(kNTracklets)->FindBin(nTracklets);
592 hLikeTRD->GetAxis(kNTracklets)->SetRange(binTracklets, binTracklets);
594 Int_t binElectrons = hLikeTRD->GetAxis(kSpecies)->FindBin(AliPID::kElectron);
595 AliDebug(1, Form("BinElectrons %d", binElectrons));
596 Int_t binPions = hLikeTRD->GetAxis(kSpecies)->FindBin(AliPID::kPion);
597 AliDebug(1, Form("BinPions %d", binPions));
598 Int_t binProtons = hLikeTRD->GetAxis(kSpecies)->FindBin(AliPID::kProton);
599 AliDebug(1, Form("BinProtons %d", binProtons));
600 hLikeTRD->GetAxis(kSpecies)->SetRange(binElectrons, binElectrons);
601 TH2 *likeElectron = hLikeTRD->Projection(kElectronLike, kP);
602 likeElectron->SetName("likeElectron");
603 hLikeTRD->GetAxis(kSpecies)->SetRange(binPions, binPions);
604 TH2 *likePion = hLikeTRD->Projection(kElectronLike, kP);
605 likePion->SetName("likePion");
606 hLikeTRD->GetAxis(kSpecies)->SetRange(binProtons, binProtons);
607 TH2 *likeProton = hLikeTRD->Projection(kElectronLike, kP);
608 likeProton->SetName("likeProton");
611 hLikeTRD->GetAxis(kSpecies)->SetRange(0, hLikeTRD->GetAxis(kSpecies)->GetNbins());
612 hLikeTRD->GetAxis(kNTracklets)->SetRange(0, hLikeTRD->GetAxis(kNTracklets)->GetNbins());
614 // Prepare List for output
615 TList *listPions = new TList; listPions->SetName(Form("%dTracklets", nTracklets)); listPions->SetOwner();
616 TList *listProtons = new TList; listProtons->SetName(Form("%dTracklets", nTracklets)); listProtons->SetOwner();
617 TList *listThresholds = new TList; listThresholds->SetName(Form("%dTracklets", nTracklets)); listThresholds->SetOwner();
618 fPionEfficiencies->Add(listPions);
619 fProtonEfficiencies->Add(listProtons);
620 fThresholds->Add(listThresholds);
622 TH1 *probsEl = NULL, *probsPi = NULL, *probsPr = NULL;
623 TGraphErrors *effPi = NULL, *effPr = NULL; TGraph *thresholds = NULL;
624 Double_t p = 0, dp = 0;
626 Double_t eff, error; // value and error
627 for(Int_t ieff = 0; ieff < kNElectronEffs; ieff++){
630 printf("-----------------------------------------\n");
631 printf("Doing Electron Efficiency %f\n", fgkElectronEff[ieff]);
632 printf("-----------------------------------------\n");
634 effPi = new TGraphErrors(likeElectron->GetXaxis()->GetNbins());
635 effPi->SetName(Form("eff%d", static_cast<Int_t >(fgkElectronEff[ieff] * 100)));
636 effPr = new TGraphErrors(likeElectron->GetXaxis()->GetNbins());
637 effPr->SetName(Form("eff%d", static_cast<Int_t >(fgkElectronEff[ieff] * 100)));
638 thresholds = new TGraph(likeElectron->GetXaxis()->GetNbins());
639 thresholds->SetName(Form("eff%d", static_cast<Int_t >(fgkElectronEff[ieff] * 100)));
642 listPions->Add(effPi);
643 listProtons->Add(effPr);
644 listThresholds->Add(thresholds);
646 for(Int_t imom = 1; imom <= likeElectron->GetXaxis()->GetLast(); imom++){
647 p = likeElectron->GetXaxis()->GetBinCenter(imom);
648 dp = likeElectron->GetXaxis()->GetBinWidth(imom)/2;
650 probsEl = likeElectron->ProjectionY("el", imom, imom);
651 if(!probsEl->GetEntries()) continue;
652 probsEl->Scale(1./probsEl->Integral());
653 probsPi = likePion->ProjectionY("pi", imom, imom);
654 if(!probsPi->GetEntries()) continue;
655 probsPi->Scale(1./probsPi->Integral());
656 probsPr = likeProton->ProjectionY("pr", imom, imom);
657 if(!probsPr->GetEntries()) continue;
658 probsPr->Scale(1./probsPr->Integral());
659 AliDebug(1, Form("Calculating Values for p = %f", p));
661 // Calculate non-electronEfficiency and error
662 eff = CalculateHadronEfficiency(probsPi, probsEl, fgkElectronEff[ieff], threshbin, error);
663 thresholds->SetPoint(imom - 1, p, probsEl->GetXaxis()->GetBinCenter(threshbin));
664 AliDebug(1, Form("threshold %d|%f", threshbin, probsEl->GetXaxis()->GetBinCenter(threshbin)));
665 AliDebug(1, Form("Pion Efficiency %f +- %f", eff, error));
666 effPi->SetPoint(imom - 1, p, eff);
667 effPi->SetPointError(imom - 1, dp, error);
668 eff = CalculateHadronEfficiency(probsPr, probsEl, fgkElectronEff[ieff] , threshbin, error);
669 AliDebug(1, Form("Proton Efficiency %f", eff));
670 effPr->SetPoint(imom - 1, p, eff);
671 effPr->SetPointError(imom - 1, dp, error);
680 // remove temporary histograms
686 //__________________________________________________________________
687 Double_t AliHFEtrdPIDqa::CalculateHadronEfficiency(const TH1 * const hadron, const TH1 *const electron, Double_t eff, Int_t &threshbin, Double_t &error){
689 // Calculate non-electron efficiency
690 // optionally returns sums as second parameter
693 TArrayD sumsEl(electron->GetNbinsX()), sumsHd(electron->GetNbinsX());
695 // calculate threshold and estimated electron efficiency the threshold was taken
696 Double_t elEff = 0.; // estimated electron efficiency at the end
697 Int_t currentBin = 0, nbins = 0;
698 for(Int_t ibin = electron->GetXaxis()->GetLast(); ibin >= electron->GetXaxis()->GetFirst(); ibin--){
701 elEff += electron->GetBinContent(ibin);
702 sumsEl[electron->GetXaxis()->GetLast() - ibin] = elEff;
704 // we found the matching bin, break the loop
708 threshbin = currentBin;
711 for(Int_t ibin = hadron->GetXaxis()->GetLast(); ibin >= threshbin; ibin--) {
712 hdEff += hadron->GetBinContent(ibin);
713 sumsHd[hadron->GetXaxis()->GetLast() - ibin] = hdEff;
716 // search sums of electron efficiency for double counts, eliminate in electron and hadron array
717 TArrayD newsumsEl(100), newsumsHd(100);
719 for(Int_t ien = 0; ien < nbins; ien++){
721 newsumsEl[0] = sumsEl[0];
725 Int_t index = TMath::BinarySearch(nusable, newsumsEl.GetArray(), sumsEl[ien]);
726 if(TMath::Abs(sumsEl[ien] - newsumsEl[index]) < 1e-13){
727 // element already counted, don't add to the new arrays
730 newsumsEl[nusable] = sumsEl[ien];
731 newsumsHd[nusable] = sumsHd[ien];
735 //printf("New array\n");
736 //for(Int_t ib = 0; ib < nusable; ib++){
737 // printf("Electron Efficiency %f, Pion Efficiency %f\n", newsumsEl[ib], newsumsHd[ib]);
739 //printf("Do Fit\n");
743 if(hadron->GetEntries() > 0 && electron->GetEntries() > 0 && nusable > 2){
744 // Do error calculation in case the bins have enough statistics
745 TGraph gevh(nusable, newsumsEl.GetArray(), newsumsHd.GetArray());
746 TF1 evh("evh","pol2", eff-.05, eff+.05);
747 gevh.Fit(&evh, "Q", "", eff-.05, eff+.05);
749 // return the error of the pion efficiency
750 if(((1.-hdEff) < 0) || ((1.- elEff) < 0)){
751 AliError(" ElEffi or HdEffi > 1. Error can not be calculated. Please increase statistics!");
753 error = TMath::Sqrt(hdEff*(1-hdEff)/hadron->GetEntries()+TMath::Power(evh.Derivative(eff), 2)*elEff*(1-elEff)/electron->GetEntries());
755 AliDebug(2, Form("Pion Effi at [%f] : [%f +/- %f], Threshold[%f]", elEff, hdEff, error, electron->GetBinCenter(threshbin)));
756 AliDebug(2, Form("Derivative at %4.2f : %f\n", eff, evh.Derivative(eff)));
762 //__________________________________________________________________
763 Double_t AliHFEtrdPIDqa::CalculateIntegratedPionEfficiency(UInt_t nTracklets, Double_t electronEff, Double_t pmin, Double_t pmax, Double_t *error){
765 // Calculate Pion Efficiency for a given electron efficiency in the specified momentum range
767 if(nTracklets < 4 || nTracklets > 6){
768 AliError("Pion Efficiency calculation only available for 4, 5, and 6 tracklets");
771 if(electronEff < 0.6 || electronEff > 1.){
772 AliError("Pion Efficiency calculation only available in the electron efficiency range 0.6 to 1");
775 if(pmin < 0.1 || pmin > 10 || pmax < 0.1 || pmax > 10.){
776 AliError("Pion Efficiency calculation only available in the momentum range 0.1 to 10 GeV/c");
780 AliError("pmin is expected to be >= pmax");
784 // prerequierements fullfiled
786 THnSparse *hLikeTRD = dynamic_cast<THnSparseF *>(fHistos->Get("fLikeTRD"));
788 AliError("Likelihood Histogram not available");
791 Int_t binTracklets = hLikeTRD->GetAxis(kNTracklets)->FindBin(nTracklets);
792 hLikeTRD->GetAxis(kNTracklets)->SetRange(binTracklets, binTracklets);
793 Int_t pbinMin = hLikeTRD->GetAxis(kP)->FindBin(pmax),
794 pbinMax = hLikeTRD->GetAxis(kP)->FindBin(pmax);
795 hLikeTRD->GetAxis(kP)->SetRange(pbinMin, pbinMax);
796 Int_t binElectrons = hLikeTRD->GetAxis(kSpecies)->FindBin(AliPID::kElectron);
797 Int_t binPions = hLikeTRD->GetAxis(kSpecies)->FindBin(AliPID::kPion);
798 hLikeTRD->GetAxis(kSpecies)->SetRange(binElectrons, binElectrons);
799 TH1 *likeElectron = hLikeTRD->Projection(kElectronLike);
800 likeElectron->Scale(1./likeElectron->Integral());
801 likeElectron->SetName("likeElectron");
802 hLikeTRD->GetAxis(kSpecies)->SetRange(binPions, binPions);
803 TH1 *likePion = hLikeTRD->Projection(kElectronLike);
804 likePion->Scale(1./likePion->Integral());
805 likePion->SetName("likePion");
808 hLikeTRD->GetAxis(kSpecies)->SetRange(0, hLikeTRD->GetAxis(kSpecies)->GetNbins());
809 hLikeTRD->GetAxis(kNTracklets)->SetRange(0, hLikeTRD->GetAxis(kNTracklets)->GetNbins());
810 hLikeTRD->GetAxis(kP)->SetRange(0, hLikeTRD->GetAxis(kP)->GetNbins());
813 Int_t thresh; Double_t err;
814 Double_t effpi = CalculateHadronEfficiency(likePion, likeElectron, electronEff, thresh, err);
815 delete likePion; delete likeElectron;
816 if(error) *error = err;
820 //__________________________________________________________________
821 void AliHFEtrdPIDqa::DrawTracklet(Int_t itracklet, Double_t pmin, Double_t pmax, Bool_t doFit){
823 // Draw efficiencies and threshold as function of p
825 if(!(fPionEfficiencies && fProtonEfficiencies && fThresholds)){
826 AliError("No graphs to draw available");
830 TList *lpions = dynamic_cast<TList *>(fPionEfficiencies->FindObject(Form("%dTracklets", itracklet)));
831 TList *lprotons = dynamic_cast<TList *>(fProtonEfficiencies->FindObject(Form("%dTracklets", itracklet)));
833 TList *lthresholds = dynamic_cast<TList *>(fThresholds->FindObject(Form("%dTracklets", itracklet)));
834 if(!(lpions && lprotons && lthresholds)){
835 AliDebug(1, "Relevant lists not found. Did you forget to run FinishAnalysis()?");
839 TGraphErrors *pi, *pr;
842 TCanvas *c1 = new TCanvas(Form("tracklet%d", itracklet), Form("Tracklet %d", itracklet), 1024, 768);
844 TF1 *threshfit = NULL;
845 for(Int_t ieff = 0; ieff < kNElectronEffs; ieff++){
848 gPad->SetLeftMargin(0.12);
849 gPad->SetRightMargin(0.08);
850 pi = dynamic_cast<TGraphErrors *>(lpions->FindObject(Form("eff%d", static_cast<Int_t>(fgkElectronEff[ieff] * 100))));
851 pr = dynamic_cast<TGraphErrors *>(lprotons->FindObject(Form("eff%d", static_cast<Int_t>(fgkElectronEff[ieff] * 100))));
852 tr = dynamic_cast<TGraph *>(lthresholds->FindObject(Form("eff%d", static_cast<Int_t>(fgkElectronEff[ieff] * 100))));
853 if(!(pi && pr && tr)) continue;
855 // Define nice plot, draw
857 pi->GetXaxis()->SetTitle("p / GeV/c");
858 pi->GetYaxis()->SetTitle("Efficiency");
859 pr->GetXaxis()->SetTitle("p / GeV/c");
860 pr->GetYaxis()->SetTitle("Efficiency");
861 tr->GetXaxis()->SetTitle("p / GeV/c");
862 tr->GetYaxis()->SetTitle("Efficiency");
863 pi->GetYaxis()->SetTitleOffset(1.2);
864 pr->GetYaxis()->SetTitleOffset(1.2);
865 tr->GetYaxis()->SetTitleOffset(1.2);
866 pi->GetXaxis()->SetTitleSize(0.045);
867 pi->GetYaxis()->SetTitleSize(0.045);
868 pr->GetXaxis()->SetTitleSize(0.045);
869 pr->GetYaxis()->SetTitleSize(0.045);
870 tr->GetXaxis()->SetTitleSize(0.045);
871 tr->GetYaxis()->SetTitleSize(0.045);
873 pi->GetYaxis()->SetRangeUser(1e-3, 1.);
874 pr->GetYaxis()->SetRangeUser(1e-3, 1.);
875 tr->GetYaxis()->SetRangeUser(1e-3, 1.);
876 if(pmin >= 0 && pmax >= 0.){
877 pi->GetXaxis()->SetRangeUser(pmin, pmax);
878 pr->GetXaxis()->SetRangeUser(pmin, pmax);
879 tr->GetXaxis()->SetRangeUser(pmin, pmax);
882 pi->SetMarkerColor(kRed);
883 pi->SetMarkerStyle(20);
884 pr->SetMarkerColor(kBlue);
885 pr->SetMarkerStyle(21);
886 tr->SetMarkerColor(kBlack);
887 tr->SetMarkerStyle(22);
889 pi->SetTitle(Form ("%.2f Electron Efficiency", fgkElectronEff[ieff]));
890 pr->SetTitle(Form ("%.2f Electron Efficiency", fgkElectronEff[ieff]));
891 tr->SetTitle(Form ("%.2f Electron Efficiency", fgkElectronEff[ieff]));
893 pi->Draw("ape"); pr->Draw("pesame"); tr->Draw("psame");
897 threshfit = MakeThresholds(tr, pmin, pmax);
898 threshfit->SetLineColor(kBlack);
899 threshfit->Draw("same");
902 // Add entries to legend
904 leg = new TLegend(0.5, 0.65, 0.89, 0.85);
905 leg->SetBorderSize(0);
906 leg->SetFillStyle(0);
907 leg->AddEntry(pi, "Pion Efficiency", "lp");
908 leg->AddEntry(pr, "Proton Efficiency", "lp");
909 leg->AddEntry(tr, "Thresholds", "lp");
917 //__________________________________________________________________
918 TF1 *AliHFEtrdPIDqa::MakeThresholds(TGraph *threshist, Double_t lowerLimit, Double_t upperLimit){
920 // Create TF1 containing the threshold parametrisation
923 TF1 *threshparam = new TF1("thresh", "1-[0]-[1]*x-[2]*TMath::Exp(-[3]*x)", 0.1, 10);
924 threshist->Fit(threshparam, "NE", "", lowerLimit, upperLimit);
928 //__________________________________________________________________
929 void AliHFEtrdPIDqa::ClearLists(){
931 // Clear lists for particle efficiencies and thresholds
933 if(fPionEfficiencies){
934 fPionEfficiencies->Delete();
935 delete fPionEfficiencies;
936 fPionEfficiencies = NULL;
938 if(fProtonEfficiencies){
939 fProtonEfficiencies->Delete();
940 delete fProtonEfficiencies;
941 fProtonEfficiencies = NULL;
944 fThresholds->Delete();
950 //__________________________________________________________________
951 Double_t AliHFEtrdPIDqa::EvalPionEfficiency(Int_t ntls, Int_t eEff, Double_t p){
953 // calculate pion efficiency
955 // Number of tracklets
956 // Electron Efficiency
959 TGraphErrors *measurement = GetPionEfficiency(ntls, eEff);
960 if(!measurement) return -1.;
961 return measurement->Eval(p);
964 //__________________________________________________________________
965 Double_t AliHFEtrdPIDqa::EvalProtonEfficiency(Int_t ntls, Int_t eEff, Double_t p){
967 // calculate proton efficiency
969 // Number of tracklets
970 // Electron Efficiency
973 TGraphErrors *measurement = GetProtonEfficiency(ntls, eEff);
974 if(!measurement) return -1.;
975 return measurement->Eval(p);
978 //__________________________________________________________________
979 Double_t AliHFEtrdPIDqa::EvalThreshold(Int_t ntls, Int_t eEff, Double_t p){
981 // Get the threshold to reach a certain electron efficiency
983 // Number of tracklets
984 // Electron Efficiency
987 TGraph *measurement = GetThreshold(ntls, eEff);
988 if(!measurement) return -1.;
989 return measurement->Eval(p);
992 //__________________________________________________________________
993 TGraphErrors *AliHFEtrdPIDqa::GetPionEfficiency(Int_t ntracklets, Int_t eleffpercent){
995 // Get Graph with pion efficiencies
997 TList *graphs = dynamic_cast<TList *>(fPionEfficiencies->FindObject(Form("%dTracklets", ntracklets)));
998 if(!graphs) return NULL;
999 return dynamic_cast<TGraphErrors *>(graphs->FindObject(Form("eff%d", eleffpercent)));
1002 //__________________________________________________________________
1003 TGraphErrors *AliHFEtrdPIDqa::GetProtonEfficiency(Int_t ntracklets, Int_t eleffpercent){
1005 // Get Graph with proton efficiencies
1007 TList *graphs = dynamic_cast<TList *>(fProtonEfficiencies->FindObject(Form("%dTracklets", ntracklets)));
1008 if(!graphs) return NULL;
1009 return dynamic_cast<TGraphErrors *>(graphs->FindObject(Form("eff%d", eleffpercent)));
1012 //__________________________________________________________________
1013 TGraph *AliHFEtrdPIDqa::GetThreshold(Int_t ntracklets, Int_t eleffpercent){
1015 // Get Graph with threshols
1017 TList *graphs = dynamic_cast<TList *>(fThresholds->FindObject(Form("%dTracklets", ntracklets)));
1018 if(!graphs) return NULL;
1019 return dynamic_cast<TGraph *>(graphs->FindObject(Form("eff%d", eleffpercent)));