7 #include "TFitResultPtr.h"
8 #include "TFitResult.h"
10 #include "AliMCParticle.h"
12 #include "AliAnalysisTask.h"
13 #include "AliAnalysisManager.h"
15 #include "AliESDEvent.h"
16 #include "AliMCEvent.h"
17 #include "AliESDInputHandler.h"
18 #include "AliInputEventHandler.h"
20 #include "AliVVertex.h"
21 #include "AliAnalysisFilter.h"
23 #include "AliPIDCombined.h"
24 #include "AliPIDResponse.h"
25 #include "AliTPCPIDResponse.h"
27 #include "AliAnalysisTaskPID.h"
30 This task collects PID output from different detectors.
31 Only tracks fulfilling some standard quality cuts are taken into account.
32 At the moment, only data from TPC and TOF is collected. But in future,
33 data from e.g. HMPID is also foreseen.
35 Contact: bhess@cern.ch
38 ClassImp(AliAnalysisTaskPID)
40 const Int_t AliAnalysisTaskPID::fgkNumJetAxes = 3; // Number of additional axes for jets
41 const Double_t AliAnalysisTaskPID::fgkEpsilon = 1e-8; // Double_t threshold above zero
42 const Int_t AliAnalysisTaskPID::fgkMaxNumGenEntries = 500; // Maximum number of generated detector responses per track and delta(Prime) and associated species
44 const Double_t AliAnalysisTaskPID::fgkOneOverSqrt2 = 0.707106781186547462; // = 1. / TMath::Sqrt2();
46 const Double_t AliAnalysisTaskPID::fgkSigmaReferenceForTransitionPars = 0.05; // Reference sigma chosen to calculate transition
48 //________________________________________________________________________
49 AliAnalysisTaskPID::AliAnalysisTaskPID()
50 : AliAnalysisTaskPIDV0base()
52 , fPIDcombined(new AliPIDCombined())
53 , fInputFromOtherTask(kFALSE)
55 , fDoEfficiency(kTRUE)
56 , fDoPtResolution(kTRUE)
57 , fStoreCentralityPercentile(kFALSE)
58 , fStoreAdditionalJetInformation(kFALSE)
59 , fTakeIntoAccountMuons(kFALSE)
63 , fTPCDefaultPriors(kFALSE)
64 , fUseMCidForGeneration(kTRUE)
65 , fUseConvolutedGaus(kFALSE)
66 , fkConvolutedGausNPar(3)
67 , fAccuracyNonGaussianTail(1e-8)
68 , fkDeltaPrimeLowLimit(0.02)
69 , fkDeltaPrimeUpLimit(40.0)
70 , fConvolutedGausDeltaPrime(0x0)
74 , fDoAnySystematicStudiesOnTheExpectedSignal(kFALSE)
75 , fSystematicScalingSplinesThreshold(50.)
76 , fSystematicScalingSplinesBelowThreshold(1.0)
77 , fSystematicScalingSplinesAboveThreshold(1.0)
78 , fSystematicScalingEtaCorrectionMomentumThr(0.35)
79 , fSystematicScalingEtaCorrectionLowMomenta(1.0)
80 , fSystematicScalingEtaCorrectionHighMomenta(1.0)
81 , fSystematicScalingEtaSigmaParaThreshold(250.)
82 , fSystematicScalingEtaSigmaParaBelowThreshold(1.0)
83 , fSystematicScalingEtaSigmaParaAboveThreshold(1.0)
84 , fSystematicScalingMultCorrection(1.0)
85 , fCentralityEstimator("V0M")
92 , fGenRespElDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
93 , fGenRespElDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
94 , fGenRespElDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
95 , fGenRespElDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
96 , fGenRespKaDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
97 , fGenRespKaDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
98 , fGenRespKaDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
99 , fGenRespKaDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
100 , fGenRespPiDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
101 , fGenRespPiDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
102 , fGenRespPiDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
103 , fGenRespPiDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
104 , fGenRespMuDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
105 , fGenRespMuDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
106 , fGenRespMuDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
107 , fGenRespMuDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
108 , fGenRespPrDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
109 , fGenRespPrDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
110 , fGenRespPrDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
111 , fGenRespPrDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
113 , fGenRespElDeltaEl(new Double_t[fgkMaxNumGenEntries])
114 , fGenRespElDeltaKa(new Double_t[fgkMaxNumGenEntries])
115 , fGenRespElDeltaPi(new Double_t[fgkMaxNumGenEntries])
116 , fGenRespElDeltaPr(new Double_t[fgkMaxNumGenEntries])
117 , fGenRespKaDeltaEl(new Double_t[fgkMaxNumGenEntries])
118 , fGenRespKaDeltaKa(new Double_t[fgkMaxNumGenEntries])
119 , fGenRespKaDeltaPi(new Double_t[fgkMaxNumGenEntries])
120 , fGenRespKaDeltaPr(new Double_t[fgkMaxNumGenEntries])
121 , fGenRespPiDeltaEl(new Double_t[fgkMaxNumGenEntries])
122 , fGenRespPiDeltaKa(new Double_t[fgkMaxNumGenEntries])
123 , fGenRespPiDeltaPi(new Double_t[fgkMaxNumGenEntries])
124 , fGenRespPiDeltaPr(new Double_t[fgkMaxNumGenEntries])
125 , fGenRespMuDeltaEl(new Double_t[fgkMaxNumGenEntries])
126 , fGenRespMuDeltaKa(new Double_t[fgkMaxNumGenEntries])
127 , fGenRespMuDeltaPi(new Double_t[fgkMaxNumGenEntries])
128 , fGenRespMuDeltaPr(new Double_t[fgkMaxNumGenEntries])
129 , fGenRespPrDeltaEl(new Double_t[fgkMaxNumGenEntries])
130 , fGenRespPrDeltaKa(new Double_t[fgkMaxNumGenEntries])
131 , fGenRespPrDeltaPi(new Double_t[fgkMaxNumGenEntries])
132 , fGenRespPrDeltaPr(new Double_t[fgkMaxNumGenEntries])
134 , fhMaxEtaVariation(0x0)
135 , fhEventsProcessed(0x0)
136 , fhEventsTriggerSel(0x0)
137 , fhEventsTriggerSelVtxCut(0x0)
138 , fhSkippedTracksForSignalGeneration(0x0)
139 , fhMCgeneratedYieldsPrimaries(0x0)
145 , fOutputContainer(0x0)
146 , fPtResolutionContainer(0x0)
148 // default Constructor
150 AliLog::SetClassDebugLevel("AliAnalysisTaskPID", AliLog::kInfo);
152 fConvolutedGausDeltaPrime = new TF1("convolutedGausDeltaPrime", this, &AliAnalysisTaskPID::ConvolutedGaus,
153 fkDeltaPrimeLowLimit, fkDeltaPrimeUpLimit,
154 fkConvolutedGausNPar, "AliAnalysisTaskPID", "ConvolutedGaus");
156 // Set some arbitrary parameteres, such that the function call will not crash
157 // (although it should not be called with these parameters...)
158 fConvolutedGausDeltaPrime->SetParameter(0, 0);
159 fConvolutedGausDeltaPrime->SetParameter(1, 1);
160 fConvolutedGausDeltaPrime->SetParameter(2, 2);
163 // Initialisation of translation parameters is time consuming.
164 // Therefore, default values will only be initialised if they are really needed.
165 // Otherwise, it is left to the user to set the parameter properly.
166 fConvolutedGaussTransitionPars[0] = -999;
167 fConvolutedGaussTransitionPars[1] = -999;
168 fConvolutedGaussTransitionPars[2] = -999;
171 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
172 fFractionHists[i] = 0x0;
173 fFractionSysErrorHists[i] = 0x0;
175 fPtResolution[i] = 0x0;
179 //________________________________________________________________________
180 AliAnalysisTaskPID::AliAnalysisTaskPID(const char *name)
181 : AliAnalysisTaskPIDV0base(name)
183 , fPIDcombined(new AliPIDCombined())
184 , fInputFromOtherTask(kFALSE)
186 , fDoEfficiency(kTRUE)
187 , fDoPtResolution(kTRUE)
188 , fStoreCentralityPercentile(kFALSE)
189 , fStoreAdditionalJetInformation(kFALSE)
190 , fTakeIntoAccountMuons(kFALSE)
194 , fTPCDefaultPriors(kFALSE)
195 , fUseMCidForGeneration(kTRUE)
196 , fUseConvolutedGaus(kFALSE)
197 , fkConvolutedGausNPar(3)
198 , fAccuracyNonGaussianTail(1e-8)
199 , fkDeltaPrimeLowLimit(0.02)
200 , fkDeltaPrimeUpLimit(40.0)
201 , fConvolutedGausDeltaPrime(0x0)
205 , fDoAnySystematicStudiesOnTheExpectedSignal(kFALSE)
206 , fSystematicScalingSplinesThreshold(50.)
207 , fSystematicScalingSplinesBelowThreshold(1.0)
208 , fSystematicScalingSplinesAboveThreshold(1.0)
209 , fSystematicScalingEtaCorrectionMomentumThr(0.35)
210 , fSystematicScalingEtaCorrectionLowMomenta(1.0)
211 , fSystematicScalingEtaCorrectionHighMomenta(1.0)
212 , fSystematicScalingEtaSigmaParaThreshold(250.)
213 , fSystematicScalingEtaSigmaParaBelowThreshold(1.0)
214 , fSystematicScalingEtaSigmaParaAboveThreshold(1.0)
215 , fSystematicScalingMultCorrection(1.0)
216 , fCentralityEstimator("V0M")
223 , fGenRespElDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
224 , fGenRespElDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
225 , fGenRespElDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
226 , fGenRespElDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
227 , fGenRespKaDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
228 , fGenRespKaDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
229 , fGenRespKaDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
230 , fGenRespKaDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
231 , fGenRespPiDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
232 , fGenRespPiDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
233 , fGenRespPiDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
234 , fGenRespPiDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
235 , fGenRespMuDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
236 , fGenRespMuDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
237 , fGenRespMuDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
238 , fGenRespMuDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
239 , fGenRespPrDeltaPrimeEl(new Double_t[fgkMaxNumGenEntries])
240 , fGenRespPrDeltaPrimeKa(new Double_t[fgkMaxNumGenEntries])
241 , fGenRespPrDeltaPrimePi(new Double_t[fgkMaxNumGenEntries])
242 , fGenRespPrDeltaPrimePr(new Double_t[fgkMaxNumGenEntries])
244 , fGenRespElDeltaEl(new Double_t[fgkMaxNumGenEntries])
245 , fGenRespElDeltaKa(new Double_t[fgkMaxNumGenEntries])
246 , fGenRespElDeltaPi(new Double_t[fgkMaxNumGenEntries])
247 , fGenRespElDeltaPr(new Double_t[fgkMaxNumGenEntries])
248 , fGenRespKaDeltaEl(new Double_t[fgkMaxNumGenEntries])
249 , fGenRespKaDeltaKa(new Double_t[fgkMaxNumGenEntries])
250 , fGenRespKaDeltaPi(new Double_t[fgkMaxNumGenEntries])
251 , fGenRespKaDeltaPr(new Double_t[fgkMaxNumGenEntries])
252 , fGenRespPiDeltaEl(new Double_t[fgkMaxNumGenEntries])
253 , fGenRespPiDeltaKa(new Double_t[fgkMaxNumGenEntries])
254 , fGenRespPiDeltaPi(new Double_t[fgkMaxNumGenEntries])
255 , fGenRespPiDeltaPr(new Double_t[fgkMaxNumGenEntries])
256 , fGenRespMuDeltaEl(new Double_t[fgkMaxNumGenEntries])
257 , fGenRespMuDeltaKa(new Double_t[fgkMaxNumGenEntries])
258 , fGenRespMuDeltaPi(new Double_t[fgkMaxNumGenEntries])
259 , fGenRespMuDeltaPr(new Double_t[fgkMaxNumGenEntries])
260 , fGenRespPrDeltaEl(new Double_t[fgkMaxNumGenEntries])
261 , fGenRespPrDeltaKa(new Double_t[fgkMaxNumGenEntries])
262 , fGenRespPrDeltaPi(new Double_t[fgkMaxNumGenEntries])
263 , fGenRespPrDeltaPr(new Double_t[fgkMaxNumGenEntries])
265 , fhMaxEtaVariation(0x0)
266 , fhEventsProcessed(0x0)
267 , fhEventsTriggerSel(0x0)
268 , fhEventsTriggerSelVtxCut(0x0)
269 , fhSkippedTracksForSignalGeneration(0x0)
270 , fhMCgeneratedYieldsPrimaries(0x0)
276 , fOutputContainer(0x0)
277 , fPtResolutionContainer(0x0)
281 AliLog::SetClassDebugLevel("AliAnalysisTaskPID", AliLog::kInfo);
283 fConvolutedGausDeltaPrime = new TF1("convolutedGausDeltaPrime", this, &AliAnalysisTaskPID::ConvolutedGaus,
284 fkDeltaPrimeLowLimit, fkDeltaPrimeUpLimit,
285 fkConvolutedGausNPar, "AliAnalysisTaskPID", "ConvolutedGaus");
287 // Set some arbitrary parameteres, such that the function call will not crash
288 // (although it should not be called with these parameters...)
289 fConvolutedGausDeltaPrime->SetParameter(0, 0);
290 fConvolutedGausDeltaPrime->SetParameter(1, 1);
291 fConvolutedGausDeltaPrime->SetParameter(2, 2);
294 // Initialisation of translation parameters is time consuming.
295 // Therefore, default values will only be initialised if they are really needed.
296 // Otherwise, it is left to the user to set the parameter properly.
297 fConvolutedGaussTransitionPars[0] = -999;
298 fConvolutedGaussTransitionPars[1] = -999;
299 fConvolutedGaussTransitionPars[2] = -999;
302 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
303 fFractionHists[i] = 0x0;
304 fFractionSysErrorHists[i] = 0x0;
306 fPtResolution[i] = 0x0;
309 // Define input and output slots here
310 // Input slot #0 works with a TChain
311 DefineInput(0, TChain::Class());
313 DefineOutput(1, TObjArray::Class());
315 DefineOutput(2, AliCFContainer::Class());
317 DefineOutput(3, TObjArray::Class());
321 //________________________________________________________________________
322 AliAnalysisTaskPID::~AliAnalysisTaskPID()
326 CleanupParticleFractionHistos();
328 delete fOutputContainer;
329 fOutputContainer = 0x0;
331 delete fPtResolutionContainer;
332 fPtResolutionContainer = 0x0;
334 delete fConvolutedGausDeltaPrime;
335 fConvolutedGausDeltaPrime = 0x0;
337 delete [] fGenRespElDeltaPrimeEl;
338 delete [] fGenRespElDeltaPrimeKa;
339 delete [] fGenRespElDeltaPrimePi;
340 delete [] fGenRespElDeltaPrimePr;
342 fGenRespElDeltaPrimeEl = 0x0;
343 fGenRespElDeltaPrimeKa = 0x0;
344 fGenRespElDeltaPrimePi = 0x0;
345 fGenRespElDeltaPrimePr = 0x0;
347 delete [] fGenRespKaDeltaPrimeEl;
348 delete [] fGenRespKaDeltaPrimeKa;
349 delete [] fGenRespKaDeltaPrimePi;
350 delete [] fGenRespKaDeltaPrimePr;
352 fGenRespKaDeltaPrimeEl = 0x0;
353 fGenRespKaDeltaPrimeKa = 0x0;
354 fGenRespKaDeltaPrimePi = 0x0;
355 fGenRespKaDeltaPrimePr = 0x0;
357 delete [] fGenRespPiDeltaPrimeEl;
358 delete [] fGenRespPiDeltaPrimeKa;
359 delete [] fGenRespPiDeltaPrimePi;
360 delete [] fGenRespPiDeltaPrimePr;
362 fGenRespPiDeltaPrimeEl = 0x0;
363 fGenRespPiDeltaPrimeKa = 0x0;
364 fGenRespPiDeltaPrimePi = 0x0;
365 fGenRespPiDeltaPrimePr = 0x0;
367 delete [] fGenRespMuDeltaPrimeEl;
368 delete [] fGenRespMuDeltaPrimeKa;
369 delete [] fGenRespMuDeltaPrimePi;
370 delete [] fGenRespMuDeltaPrimePr;
372 fGenRespMuDeltaPrimeEl = 0x0;
373 fGenRespMuDeltaPrimeKa = 0x0;
374 fGenRespMuDeltaPrimePi = 0x0;
375 fGenRespMuDeltaPrimePr = 0x0;
377 delete [] fGenRespPrDeltaPrimeEl;
378 delete [] fGenRespPrDeltaPrimeKa;
379 delete [] fGenRespPrDeltaPrimePi;
380 delete [] fGenRespPrDeltaPrimePr;
382 fGenRespPrDeltaPrimeEl = 0x0;
383 fGenRespPrDeltaPrimeKa = 0x0;
384 fGenRespPrDeltaPrimePi = 0x0;
385 fGenRespPrDeltaPrimePr = 0x0;
387 delete fhMaxEtaVariation;
388 fhMaxEtaVariation = 0x0;
390 /*OLD with deltaSpecies
391 delete [] fGenRespElDeltaEl;
392 delete [] fGenRespElDeltaKa;
393 delete [] fGenRespElDeltaPi;
394 delete [] fGenRespElDeltaPr;
396 fGenRespElDeltaEl = 0x0;
397 fGenRespElDeltaKa = 0x0;
398 fGenRespElDeltaPi = 0x0;
399 fGenRespElDeltaPr = 0x0;
401 delete [] fGenRespKaDeltaEl;
402 delete [] fGenRespKaDeltaKa;
403 delete [] fGenRespKaDeltaPi;
404 delete [] fGenRespKaDeltaPr;
406 fGenRespKaDeltaEl = 0x0;
407 fGenRespKaDeltaKa = 0x0;
408 fGenRespKaDeltaPi = 0x0;
409 fGenRespKaDeltaPr = 0x0;
411 delete [] fGenRespPiDeltaEl;
412 delete [] fGenRespPiDeltaKa;
413 delete [] fGenRespPiDeltaPi;
414 delete [] fGenRespPiDeltaPr;
416 fGenRespPiDeltaEl = 0x0;
417 fGenRespPiDeltaKa = 0x0;
418 fGenRespPiDeltaPi = 0x0;
419 fGenRespPiDeltaPr = 0x0;
421 delete [] fGenRespMuDeltaEl;
422 delete [] fGenRespMuDeltaKa;
423 delete [] fGenRespMuDeltaPi;
424 delete [] fGenRespMuDeltaPr;
426 fGenRespMuDeltaEl = 0x0;
427 fGenRespMuDeltaKa = 0x0;
428 fGenRespMuDeltaPi = 0x0;
429 fGenRespMuDeltaPr = 0x0;
431 delete [] fGenRespPrDeltaEl;
432 delete [] fGenRespPrDeltaKa;
433 delete [] fGenRespPrDeltaPi;
434 delete [] fGenRespPrDeltaPr;
436 fGenRespPrDeltaEl = 0x0;
437 fGenRespPrDeltaKa = 0x0;
438 fGenRespPrDeltaPi = 0x0;
439 fGenRespPrDeltaPr = 0x0;
444 //________________________________________________________________________
445 void AliAnalysisTaskPID::SetUpPIDcombined()
447 // Initialise the PIDcombined object
453 printf("File: %s, Line: %d: SetUpPIDcombined\n", (char*)__FILE__, __LINE__);
456 AliFatal("No PIDcombined object!\n");
460 fPIDcombined->SetSelectedSpecies(AliPID::kSPECIESC);
461 fPIDcombined->SetEnablePriors(fUsePriors);
463 if (fTPCDefaultPriors)
464 fPIDcombined->SetDefaultTPCPriors();
466 //TODO use individual priors...
468 // Change detector mask (TPC,TOF,ITS)
469 Int_t detectorMask = AliPIDResponse::kDetTPC;
471 // Reject mismatch mask - mismatch only relevant for TOF at the moment - other detectors do not use it
472 Int_t rejectMismatchMask = AliPIDResponse::kDetTPC;
476 detectorMask = detectorMask | AliPIDResponse::kDetITS;
477 rejectMismatchMask = rejectMismatchMask | AliPIDResponse::kDetITS;
480 detectorMask = detectorMask | AliPIDResponse::kDetTOF;
481 rejectMismatchMask = rejectMismatchMask | AliPIDResponse::kDetTOF;
484 fPIDcombined->SetDetectorMask(detectorMask);
485 fPIDcombined->SetRejectMismatchMask(rejectMismatchMask);
488 printf("File: %s, Line: %d: SetUpPIDcombined done\n", (char*)__FILE__, __LINE__);
492 //________________________________________________________________________
493 Bool_t AliAnalysisTaskPID::CalculateMaxEtaVariationMapFromPIDResponse()
495 // Calculate the maximum deviation from unity of the eta correction factors for each row in 1/dEdx(splines)
496 // from the eta correction map of the TPCPIDResponse. The result is stored in fhMaxEtaVariation.
499 AliError("No PID response!");
503 delete fhMaxEtaVariation;
505 const TH2D* hEta = fPIDResponse->GetTPCResponse().GetEtaCorrMap();
507 AliError("No eta correction map!");
511 // Take binning from hEta in Y for fhMaxEtaVariation
512 fhMaxEtaVariation = hEta->ProjectionY("hMaxEtaVariation");
513 fhMaxEtaVariation->SetDirectory(0);
514 fhMaxEtaVariation->Reset();
516 // For each bin in 1/dEdx, loop of all tanTheta bins and find the maximum deviation from unity.
517 // Store the result in fhMaxEtaVariation
519 for (Int_t binY = 1; binY <= fhMaxEtaVariation->GetNbinsX(); binY++) {
520 Double_t maxAbs = -1;
521 for (Int_t binX = 1; binX <= hEta->GetNbinsX(); binX++) {
522 Double_t curr = TMath::Abs(hEta->GetBinContent(binX, binY) - 1.);
527 if (maxAbs < 1e-12) {
528 AliError(Form("Maximum deviation from unity is zero for 1/dEdx = %f (bin %d)", hEta->GetYaxis()->GetBinCenter(binY), binY));
529 delete fhMaxEtaVariation;
533 fhMaxEtaVariation->SetBinContent(binY, maxAbs);
536 printf("AliAnalysisTaskPID: Calculated max eta variation.\n");
542 //________________________________________________________________________
543 void AliAnalysisTaskPID::UserCreateOutputObjects()
549 printf("File: %s, Line: %d: UserCreateOutputObjects\n", (char*)__FILE__, __LINE__);
554 AliAnalysisManager* man = AliAnalysisManager::GetAnalysisManager();
555 AliInputEventHandler* inputHandler = dynamic_cast<AliInputEventHandler*>(man->GetInputEventHandler());
558 AliFatal("Input handler needed");
560 // PID response object
561 fPIDResponse = inputHandler->GetPIDResponse();
563 AliFatal("PIDResponse object was not created");
567 printf("File: %s, Line: %d: UserCreateOutputObjects -> Retrieved PIDresponse object\n", (char*)__FILE__, __LINE__);
572 printf("File: %s, Line: %d: UserCreateOutputObjects -> OpenFile(1) successful\n", (char*)__FILE__, __LINE__);
574 fOutputContainer = new TObjArray(1);
575 fOutputContainer->SetName(GetName());
576 fOutputContainer->SetOwner(kTRUE);
578 const Int_t nPtBins = 68;
579 Double_t binsPt[nPtBins+1] = {0. , 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45,
580 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95,
581 1.0, 1.1 , 1.2, 1.3 , 1.4, 1.5 , 1.6, 1.7 , 1.8, 1.9 ,
582 2.0, 2.2 , 2.4, 2.6 , 2.8, 3.0 , 3.2, 3.4 , 3.6, 3.8 ,
583 4.0, 4.5 , 5.0, 5.5 , 6.0, 6.5 , 7.0, 8.0 , 9.0, 10.0,
584 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0,
585 26.0, 28.0, 30.0, 32.0, 34.0, 36.0, 40.0, 45.0, 50.0 };
587 const Int_t nCentBins = 12;
588 //-1 for pp; 90-100 has huge electro-magnetic impurities
589 Double_t binsCent[nCentBins+1] = {-1, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
591 const Int_t nJetPtBins = 11;
592 Double_t binsJetPt[nJetPtBins+1] = {0, 2, 5, 10, 15, 20, 30, 40, 60, 80, 120, 200};
594 const Int_t nChargeBins = 2;
595 const Double_t binsCharge[nChargeBins+1] = { -1.0 - 1e-4, 0.0, 1.0 + 1e-4 };
597 const Int_t nBinsJets = kDataNumAxes;
598 const Int_t nBinsNoJets = nBinsJets - fgkNumJetAxes;
600 const Int_t nBins = fStoreAdditionalJetInformation ? nBinsJets : nBinsNoJets;
602 // deltaPrimeSpecies binning
603 const Int_t deltaPrimeNBins = 600;
604 Double_t deltaPrimeBins[deltaPrimeNBins + 1];
606 const Double_t fromLow = fkDeltaPrimeLowLimit;
607 const Double_t toHigh = fkDeltaPrimeUpLimit;
608 const Double_t factor = TMath::Power(toHigh/fromLow, 1./deltaPrimeNBins);
610 // Log binning for whole deltaPrime range
611 deltaPrimeBins[0] = fromLow;
612 for (Int_t i = 0 + 1; i <= deltaPrimeNBins; i++) {
613 deltaPrimeBins[i] = factor * deltaPrimeBins[i - 1];
616 const Int_t nMCPIDbins = 5;
617 const Double_t mcPIDmin = 0.;
618 const Double_t mcPIDmax = 5.;
620 const Int_t nSelSpeciesBins = 4;
621 const Double_t selSpeciesMin = 0.;
622 const Double_t selSpeciesMax = 4.;
624 const Int_t nZBins = 20;
625 const Double_t zMin = 0.;
626 const Double_t zMax = 1.;
628 const Int_t nXiBins = 70;
629 const Double_t xiMin = 0.;
630 const Double_t xiMax = 7.;
632 const Int_t nTOFpidInfoBins = kNumTOFpidInfoBins;
633 const Double_t tofPIDinfoMin = kNoTOFinfo;
634 const Double_t tofPIDinfoMax = kNoTOFinfo + kNumTOFpidInfoBins;
636 // MC PID, SelectSpecies, pT, deltaPrimeSpecies, centrality percentile, jet pT, z = track_pT/jet_pT, xi = log(1/z)
637 Int_t binsNoJets[nBinsNoJets] = { nMCPIDbins,
645 Int_t binsJets[nBinsJets] = { nMCPIDbins,
656 Int_t *bins = fStoreAdditionalJetInformation ? &binsJets[0] : &binsNoJets[0];
658 Double_t xminNoJets[nBinsNoJets] = { mcPIDmin,
666 Double_t xminJets[nBinsJets] = { mcPIDmin,
677 Double_t *xmin = fStoreAdditionalJetInformation? &xminJets[0] : &xminNoJets[0];
679 Double_t xmaxNoJets[nBinsNoJets] = { mcPIDmax,
682 deltaPrimeBins[deltaPrimeNBins],
684 binsCharge[nChargeBins],
687 Double_t xmaxJets[nBinsJets] = { mcPIDmax,
690 deltaPrimeBins[deltaPrimeNBins],
692 binsJetPt[nJetPtBins],
695 binsCharge[nChargeBins],
698 Double_t *xmax = fStoreAdditionalJetInformation? &xmaxJets[0] : &xmaxNoJets[0];
700 fConvolutedGausDeltaPrime->SetNpx(deltaPrimeNBins);
703 fhPIDdataAll = new THnSparseD("hPIDdataAll","", nBins, bins, xmin, xmax);
704 SetUpHist(fhPIDdataAll, binsPt, deltaPrimeBins, binsCent, binsJetPt);
705 fOutputContainer->Add(fhPIDdataAll);
708 // Generated histograms (so far, bins are the same as for primary THnSparse)
709 const Int_t nGenBins = fStoreAdditionalJetInformation ? nBinsJets : nBinsNoJets;
710 // MC PID, SelectSpecies, Pt, deltaPrimeSpecies, jet pT, z = track_pT/jet_pT, xi = log(1/z)
712 Int_t *genBins = fStoreAdditionalJetInformation ? &binsJets[0] : &binsNoJets[0];
713 Double_t *genXmin = fStoreAdditionalJetInformation? &xminJets[0] : &xminNoJets[0];
714 Double_t *genXmax = fStoreAdditionalJetInformation? &xmaxJets[0] : &xmaxNoJets[0];
717 fhGenEl = new THnSparseD("hGenEl", "", nGenBins, genBins, genXmin, genXmax);
718 SetUpGenHist(fhGenEl, binsPt, deltaPrimeBins, binsCent, binsJetPt);
719 fOutputContainer->Add(fhGenEl);
721 fhGenKa = new THnSparseD("hGenKa", "", nGenBins, genBins, genXmin, genXmax);
722 SetUpGenHist(fhGenKa, binsPt, deltaPrimeBins, binsCent, binsJetPt);
723 fOutputContainer->Add(fhGenKa);
725 fhGenPi = new THnSparseD("hGenPi", "", nGenBins, genBins, genXmin, genXmax);
726 SetUpGenHist(fhGenPi, binsPt, deltaPrimeBins, binsCent, binsJetPt);
727 fOutputContainer->Add(fhGenPi);
729 if (fTakeIntoAccountMuons) {
730 fhGenMu = new THnSparseD("hGenMu", "", nGenBins, genBins, genXmin, genXmax);
731 SetUpGenHist(fhGenMu, binsPt, deltaPrimeBins, binsCent, binsJetPt);
732 fOutputContainer->Add(fhGenMu);
735 fhGenPr = new THnSparseD("hGenPr", "", nGenBins, genBins, genXmin, genXmax);
736 SetUpGenHist(fhGenPr, binsPt, deltaPrimeBins, binsCent, binsJetPt);
737 fOutputContainer->Add(fhGenPr);
739 fhSkippedTracksForSignalGeneration = new TH2D("fhSkippedTracksForSignalGeneration",
740 "Number of tracks skipped for the signal generation;p_{T}^{gen} (GeV/c);TPC signal N",
741 nPtBins, binsPt, 161, -0.5, 160.5);
742 fhSkippedTracksForSignalGeneration->Sumw2();
743 fOutputContainer->Add(fhSkippedTracksForSignalGeneration);
747 fhEventsProcessed = new TH1D("fhEventsProcessed",
748 "Number of events passing trigger selection, vtx and zvtx cuts;Centrality percentile",
749 nCentBins, binsCent);
750 fhEventsProcessed->Sumw2();
751 fOutputContainer->Add(fhEventsProcessed);
753 fhEventsTriggerSelVtxCut = new TH1D("fhEventsTriggerSelVtxCut",
754 "Number of events passing trigger selection and vtx cut;Centrality percentile",
755 nCentBins, binsCent);
756 fhEventsTriggerSelVtxCut->Sumw2();
757 fOutputContainer->Add(fhEventsTriggerSelVtxCut);
759 fhEventsTriggerSel = new TH1D("fhEventsTriggerSel",
760 "Number of events passing trigger selection;Centrality percentile",
761 nCentBins, binsCent);
762 fOutputContainer->Add(fhEventsTriggerSel);
763 fhEventsTriggerSel->Sumw2();
766 // Generated yields within acceptance
767 const Int_t nBinsGenYields = fStoreAdditionalJetInformation ? kGenYieldNumAxes : kGenYieldNumAxes - 3;
768 Int_t genYieldsBins[kGenYieldNumAxes] = { nMCPIDbins, nPtBins, nCentBins, nJetPtBins, nZBins, nXiBins,
770 genYieldsBins[GetIndexOfChargeAxisGenYield()] = nChargeBins;
771 Double_t genYieldsXmin[kGenYieldNumAxes] = { mcPIDmin, binsPt[0], binsCent[0], binsJetPt[0], zMin, xiMin,
773 genYieldsXmin[GetIndexOfChargeAxisGenYield()] = binsCharge[0];
774 Double_t genYieldsXmax[kGenYieldNumAxes] = { mcPIDmax, binsPt[nPtBins], binsCent[nCentBins], binsJetPt[nJetPtBins], zMax, xiMax,
775 binsCharge[nChargeBins] };
776 genYieldsXmax[GetIndexOfChargeAxisGenYield()] = binsCharge[nChargeBins];
779 fhMCgeneratedYieldsPrimaries = new THnSparseD("fhMCgeneratedYieldsPrimaries",
780 "Generated yields w/o reco and cuts inside acceptance (physical primaries)",
781 nBinsGenYields, genYieldsBins, genYieldsXmin, genYieldsXmax);
782 SetUpGenYieldHist(fhMCgeneratedYieldsPrimaries, binsPt, binsCent, binsJetPt);
783 fOutputContainer->Add(fhMCgeneratedYieldsPrimaries);
786 // Container with several process steps (generated and reconstructed level with some variations)
791 printf("File: %s, Line: %d: UserCreateOutputObjects -> OpenFile(2) successful\n", (char*)__FILE__, __LINE__);
793 // Array for the number of bins in each dimension
794 // Dimensions: MC-ID, trackPt, trackEta, trackCharge, cenrality percentile, jetPt, z, xi TODO phi???
795 const Int_t nEffDims = fStoreAdditionalJetInformation ? kEffNumAxes : kEffNumAxes - 3; // Number of dimensions for the efficiency
797 const Int_t nMCIDbins = AliPID::kSPECIES;
798 Double_t binsMCID[nMCIDbins + 1];
800 for(Int_t i = 0; i <= nMCIDbins; i++) {
804 const Int_t nEtaBins = 18;
805 const Double_t binsEta[nEtaBins+1] = {-0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1,
806 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 };
808 const Int_t nEffBins[kEffNumAxes] = { nMCIDbins, nPtBins, nEtaBins, nChargeBins, nCentBins, nJetPtBins, nZBins, nXiBins };
810 fContainerEff = new AliCFContainer("containerEff", "Reconstruction Efficiency x Acceptance x Resolution and Secondary Correction",
811 kNumSteps, nEffDims, nEffBins);
813 // Setting the bin limits
814 fContainerEff->SetBinLimits(kEffMCID, binsMCID);
815 fContainerEff->SetBinLimits(kEffTrackPt, binsPt);
816 fContainerEff->SetBinLimits(kEffTrackEta, binsEta);
817 fContainerEff->SetBinLimits(kEffTrackCharge, binsCharge);
818 fContainerEff->SetBinLimits(kEffCentrality, binsCent);
819 if (fStoreAdditionalJetInformation) {
820 fContainerEff->SetBinLimits(kEffJetPt, binsJetPt);
821 fContainerEff->SetBinLimits(kEffZ, zMin, zMax);
822 fContainerEff->SetBinLimits(kEffXi, xiMin, xiMax);
825 fContainerEff->SetVarTitle(kEffMCID,"MC ID");
826 fContainerEff->SetVarTitle(kEffTrackPt,"p_{T} (GeV/c)");
827 fContainerEff->SetVarTitle(kEffTrackEta,"#eta");
828 fContainerEff->SetVarTitle(kEffTrackCharge,"Charge (e_{0})");
829 fContainerEff->SetVarTitle(kEffCentrality, "Centrality Percentile");
830 if (fStoreAdditionalJetInformation) {
831 fContainerEff->SetVarTitle(kEffJetPt, "p_{T}^{jet} (GeV/c)");
832 fContainerEff->SetVarTitle(kEffZ, "z = p_{T}^{track} / p_{T}^{jet}");
833 fContainerEff->SetVarTitle(kEffXi, "#xi = ln(p_{T}^{jet} / p_{T}^{track})");
836 // Define clean MC sample
837 fContainerEff->SetStepTitle(kStepGenWithGenCuts, "Particle level, cuts on particle level");
838 // For Acceptance x Efficiency correction of primaries
839 fContainerEff->SetStepTitle(kStepRecWithGenCuts, "Detector level (rec) with cuts on particle level");
840 // For (pT) resolution correction
841 fContainerEff->SetStepTitle(kStepRecWithGenCutsMeasuredObs,
842 "Detector level (rec) with cuts on particle level with measured observables");
843 // For secondary correction
844 fContainerEff->SetStepTitle(kStepRecWithRecCutsMeasuredObs,
845 "Detector level, all cuts on detector level with measured observables");
846 fContainerEff->SetStepTitle(kStepRecWithRecCutsPrimaries,
847 "Detector level, all cuts on detector level, only MC primaries");
848 fContainerEff->SetStepTitle(kStepRecWithRecCutsMeasuredObsPrimaries,
849 "Detector level, all cuts on detector level with measured observables, only MC primaries");
850 fContainerEff->SetStepTitle(kStepRecWithRecCutsMeasuredObsStrangenessScaled,
851 "Detector level (strangeness scaled), all cuts on detector level with measured observables");
854 if (fDoPID || fDoEfficiency) {
856 fh2FFJetPtRec = new TH2D("fh2FFJetPtRec", "Number of reconstructed jets;Centrality Percentile;p_{T}^{jet} (GeV/c)",
857 nCentBins, binsCent, nJetPtBins, binsJetPt);
858 fh2FFJetPtRec->Sumw2();
859 fOutputContainer->Add(fh2FFJetPtRec);
860 fh2FFJetPtGen = new TH2D("fh2FFJetPtGen", "Number of generated jets;Centrality Percentile;p_{T}^{jet} (GeV/c)",
861 nCentBins, binsCent, nJetPtBins, binsJetPt);
862 fh2FFJetPtGen->Sumw2();
863 fOutputContainer->Add(fh2FFJetPtGen);
866 // Pythia information
867 fh1Xsec = new TProfile("fh1Xsec", "xsec from pyxsec.root", 1, 0, 1);
869 fh1Xsec->GetXaxis()->SetBinLabel(1, "<#sigma>");
870 fh1Trials = new TH1D("fh1Trials", "trials from pyxsec.root", 1, 0, 1);
872 fh1Trials->GetXaxis()->SetBinLabel(1, "#sum{ntrials}");
874 fOutputContainer->Add(fh1Xsec);
875 fOutputContainer->Add(fh1Trials);
877 if (fDoPtResolution) {
881 printf("File: %s, Line: %d: UserCreateOutputObjects -> OpenFile(3) successful\n", (char*)__FILE__, __LINE__);
883 fPtResolutionContainer = new TObjArray(1);
884 fPtResolutionContainer->SetName(Form("%s_PtResolution", GetName()));
885 fPtResolutionContainer->SetOwner(kTRUE);
887 const Int_t nPtBinsRes = 100;
888 Double_t pTbinsRes[nPtBinsRes + 1];
890 const Double_t fromLowPtRes = 0.15;
891 const Double_t toHighPtRes = 50.;
892 const Double_t factorPtRes = TMath::Power(toHighPtRes/fromLowPtRes, 1./nPtBinsRes);
893 // Log binning for whole pT range
894 pTbinsRes[0] = fromLowPtRes;
895 for (Int_t i = 0 + 1; i <= nPtBinsRes; i++) {
896 pTbinsRes[i] = factorPtRes * pTbinsRes[i - 1];
899 const Int_t nBinsPtResolution = kPtResNumAxes;
900 Int_t ptResolutionBins[kPtResNumAxes] = { nJetPtBins, nPtBinsRes, nPtBinsRes,
901 nChargeBins, nCentBins };
902 Double_t ptResolutionXmin[kPtResNumAxes] = { binsJetPt[0], pTbinsRes[0], pTbinsRes[0],
903 binsCharge[0], binsCent[0] };
904 Double_t ptResolutionXmax[kPtResNumAxes] = { binsJetPt[nJetPtBins], pTbinsRes[nPtBinsRes], pTbinsRes[nPtBinsRes],
905 binsCharge[nChargeBins], binsCent[nCentBins] };
907 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
908 fPtResolution[i] = new THnSparseD(Form("fPtResolution_%s", AliPID::ParticleShortName(i)),
909 Form("Pt resolution for primaries, %s", AliPID::ParticleLatexName(i)),
910 nBinsPtResolution, ptResolutionBins, ptResolutionXmin, ptResolutionXmax);
911 SetUpPtResHist(fPtResolution[i], pTbinsRes, binsJetPt, binsCent);
912 fPtResolutionContainer->Add(fPtResolution[i]);
917 printf("File: %s, Line: %d: UserCreateOutputObjects -> Posting output data\n", (char*)__FILE__, __LINE__);
919 PostData(1, fOutputContainer);
920 PostData(2, fContainerEff);
921 PostData(3, fPtResolutionContainer);
924 printf("File: %s, Line: %d: UserCreateOutputObjects -> Done\n", (char*)__FILE__, __LINE__);
928 //________________________________________________________________________
929 void AliAnalysisTaskPID::UserExec(Option_t *)
932 // Called for each event
935 printf("File: %s, Line: %d: UserExec\n", (char*)__FILE__, __LINE__);
937 Int_t run = InputEvent()->GetRunNumber();
940 // If systematics on eta is investigated, need to calculate the maxEtaVariationMap
941 if ((TMath::Abs(fSystematicScalingEtaCorrectionLowMomenta - 1.0) > fgkEpsilon) ||
942 (TMath::Abs(fSystematicScalingEtaCorrectionHighMomenta - 1.0) > fgkEpsilon)) {
943 if (!CalculateMaxEtaVariationMapFromPIDResponse())
944 AliFatal("Systematics on eta correction requested, but failed to calculate max eta varation map!");
950 // No processing of event, if input is fed in directly from another task
951 if (fInputFromOtherTask)
955 printf("File: %s, Line: %d: UserExec -> Processing started\n", (char*)__FILE__, __LINE__);
957 fEvent = dynamic_cast<AliVEvent*>(InputEvent());
959 Printf("ERROR: fEvent not available");
963 fMC = dynamic_cast<AliMCEvent*>(MCEvent());
965 if (!fPIDResponse || !fPIDcombined)
968 Double_t centralityPercentile = -1;
969 if (fStoreCentralityPercentile)
970 centralityPercentile = fEvent->GetCentrality()->GetCentralityPercentile(fCentralityEstimator.Data());
972 IncrementEventCounter(centralityPercentile, kTriggerSel);
974 // Check if vertex is ok, but don't apply cut on z position
975 if (!GetVertexIsOk(fEvent, kFALSE))
978 fESD = dynamic_cast<AliESDEvent*>(fEvent);
979 const AliVVertex* primaryVertex = fESD ? fESD->GetPrimaryVertexTracks() : fEvent->GetPrimaryVertex();
983 if(primaryVertex->GetNContributors() <= 0)
986 IncrementEventCounter(centralityPercentile, kTriggerSelAndVtxCut);
988 // Now check again, but also require z position to be in desired range
989 if (!GetVertexIsOk(fEvent, kTRUE))
992 IncrementEventCounter(centralityPercentile, kTriggerSelAndVtxCutAndZvtxCut);
994 Double_t magField = fEvent->GetMagneticField();
997 if (fDoPID || fDoEfficiency) {
998 for (Int_t iPart = 0; iPart < fMC->GetNumberOfTracks(); iPart++) {
999 AliMCParticle *mcPart = dynamic_cast<AliMCParticle*>(fMC->GetTrack(iPart));
1004 // Define clean MC sample with corresponding particle level track cuts:
1005 // - MC-track must be in desired eta range
1006 // - MC-track must be physical primary
1007 // - Species must be one of those in question (everything else goes to the overflow bin of mcID)
1009 // Geometrie should be the same as on the reconstructed level -> By definition analysis within this eta interval
1010 if (!IsInAcceptedEtaRange(TMath::Abs(mcPart->Eta()))) continue;
1012 Int_t mcID = PDGtoMCID(mcPart->PdgCode());
1014 // AliMCParticle->Charge() calls TParticlePDG->Charge(), which returns the charge in units of e0 / 3
1015 Double_t chargeMC = mcPart->Charge() / 3.;
1017 if (TMath::Abs(chargeMC) < 0.01)
1018 continue; // Reject neutral particles (only relevant, if mcID is not used)
1020 if (!fMC->IsPhysicalPrimary(iPart))
1024 Double_t valuesGenYield[kGenYieldNumAxes] = { mcID, mcPart->Pt(), centralityPercentile, -1, -1, -1, -1 };
1025 valuesGenYield[GetIndexOfChargeAxisGenYield()] = chargeMC;
1027 fhMCgeneratedYieldsPrimaries->Fill(valuesGenYield);
1031 if (fDoEfficiency) {
1032 Double_t valueEff[kEffNumAxes] = { mcID, mcPart->Pt(), mcPart->Eta(), chargeMC, centralityPercentile,
1035 fContainerEff->Fill(valueEff, kStepGenWithGenCuts);
1041 // Track loop to fill a Train spectrum
1042 for (Int_t iTracks = 0; iTracks < fEvent->GetNumberOfTracks(); iTracks++) {
1043 AliVTrack* track = dynamic_cast<AliVTrack*>(fEvent->GetTrack(iTracks));
1045 Printf("ERROR: Could not retrieve track %d", iTracks);
1050 // Apply detector level track cuts
1051 const Bool_t tuneOnDataTPC = fPIDResponse->IsTunedOnData() &&
1052 ((fPIDResponse->GetTunedOnDataMask() & AliPIDResponse::kDetTPC) == AliPIDResponse::kDetTPC);
1053 Double_t dEdxTPC = tuneOnDataTPC ? fPIDResponse->GetTPCsignalTunedOnData(track) : track->GetTPCsignal();
1057 if(fTrackFilter && !fTrackFilter->IsSelected(track))
1060 if (GetUseTPCCutMIGeo()) {
1061 if (!TPCCutMIGeo(track, fEvent))
1064 else if (GetUseTPCnclCut()) {
1065 if (!TPCnclCut(track))
1070 if (!PhiPrimeCut(track, magField))
1071 continue; // reject track
1074 Int_t pdg = 0; // = 0 indicates data for the moment
1075 AliMCParticle* mcTrack = 0x0;
1076 Int_t mcID = AliPID::kUnknown;
1080 label = track->GetLabel();
1085 mcTrack = dynamic_cast<AliMCParticle*>(fMC->GetTrack(TMath::Abs(label)));
1087 Printf("ERROR: Could not retrieve mcTrack with label %d for track %d", label, iTracks);
1091 pdg = mcTrack->PdgCode();
1092 mcID = PDGtoMCID(mcTrack->PdgCode());
1094 if (fDoEfficiency) {
1095 // For efficiency: Reconstructed track has survived all cuts on the detector level (excluding acceptance)
1096 // and has an associated MC track which is a physical primary and was generated inside the acceptance
1097 if (fMC->IsPhysicalPrimary(TMath::Abs(label)) &&
1098 IsInAcceptedEtaRange(TMath::Abs(mcTrack->Eta()))) {
1100 // AliMCParticle->Charge() calls TParticlePDG->Charge(), which returns the charge in units of e0 / 3
1101 Double_t value[kEffNumAxes] = { mcID, mcTrack->Pt(), mcTrack->Eta(), mcTrack->Charge() / 3., centralityPercentile,
1103 fContainerEff->Fill(value, kStepRecWithGenCuts);
1105 Double_t valueMeas[kEffNumAxes] = { mcID, track->Pt(), track->Eta(), track->Charge(), centralityPercentile,
1107 fContainerEff->Fill(valueMeas, kStepRecWithGenCutsMeasuredObs);
1112 // Only process tracks inside the desired eta window
1113 if (!IsInAcceptedEtaRange(TMath::Abs(track->Eta()))) continue;
1116 ProcessTrack(track, pdg, centralityPercentile, -1); // No jet information in this case -> Set jet pT to -1
1118 if (fDoPtResolution) {
1119 if (mcTrack && fMC->IsPhysicalPrimary(TMath::Abs(label))) {
1120 // AliMCParticle->Charge() calls TParticlePDG->Charge(), which returns the charge in units of e0 / 3
1121 Double_t valuePtRes[kPtResNumAxes] = { -1, mcTrack->Pt(), track->Pt(), mcTrack->Charge() / 3., centralityPercentile };
1122 FillPtResolution(mcID, valuePtRes);
1126 if (fDoEfficiency) {
1128 Double_t valueRecAllCuts[kEffNumAxes] = { mcID, track->Pt(), track->Eta(), track->Charge(), centralityPercentile,
1130 fContainerEff->Fill(valueRecAllCuts, kStepRecWithRecCutsMeasuredObs);
1132 Double_t weight = IsSecondaryWithStrangeMotherMC(fMC, TMath::Abs(label)) ?
1133 GetMCStrangenessFactorCMS(fMC, mcTrack) : 1.0;
1134 fContainerEff->Fill(valueRecAllCuts, kStepRecWithRecCutsMeasuredObsStrangenessScaled, weight);
1136 // AliMCParticle->Charge() calls TParticlePDG->Charge(), which returns the charge in units of e0 / 3
1137 Double_t valueGenAllCuts[kEffNumAxes] = { mcID, mcTrack->Pt(), mcTrack->Eta(), mcTrack->Charge() / 3.,
1138 centralityPercentile, -1, -1, -1 };
1139 if (fMC->IsPhysicalPrimary(TMath::Abs(label))) {
1140 fContainerEff->Fill(valueRecAllCuts, kStepRecWithRecCutsMeasuredObsPrimaries);
1141 fContainerEff->Fill(valueGenAllCuts, kStepRecWithRecCutsPrimaries);
1148 printf("File: %s, Line: %d: UserExec -> Processing done\n", (char*)__FILE__, __LINE__);
1153 printf("File: %s, Line: %d: UserExec -> Done\n", (char*)__FILE__, __LINE__);
1156 //________________________________________________________________________
1157 void AliAnalysisTaskPID::Terminate(const Option_t *)
1159 // Draw result to the screen
1160 // Called once at the end of the query
1164 //_____________________________________________________________________________
1165 void AliAnalysisTaskPID::CheckDoAnyStematicStudiesOnTheExpectedSignal()
1167 // Check whether at least one scale factor indicates the ussage of systematic studies
1168 // and set internal flag accordingly.
1170 fDoAnySystematicStudiesOnTheExpectedSignal = kFALSE;
1173 if ((TMath::Abs(fSystematicScalingSplinesBelowThreshold - 1.0) > fgkEpsilon) ||
1174 (TMath::Abs(fSystematicScalingSplinesAboveThreshold - 1.0) > fgkEpsilon)) {
1175 fDoAnySystematicStudiesOnTheExpectedSignal = kTRUE;
1179 if ((TMath::Abs(fSystematicScalingEtaCorrectionLowMomenta - 1.0) > fgkEpsilon) ||
1180 (TMath::Abs(fSystematicScalingEtaCorrectionHighMomenta - 1.0) > fgkEpsilon)) {
1181 fDoAnySystematicStudiesOnTheExpectedSignal = kTRUE;
1185 if ((TMath::Abs(fSystematicScalingEtaSigmaParaBelowThreshold - 1.0) > fgkEpsilon) ||
1186 (TMath::Abs(fSystematicScalingEtaSigmaParaAboveThreshold - 1.0) > fgkEpsilon)) {
1187 fDoAnySystematicStudiesOnTheExpectedSignal = kTRUE;
1191 if (TMath::Abs(fSystematicScalingMultCorrection - 1.0) > fgkEpsilon) {
1192 fDoAnySystematicStudiesOnTheExpectedSignal = kTRUE;
1198 //_____________________________________________________________________________
1199 Int_t AliAnalysisTaskPID::PDGtoMCID(Int_t pdg)
1201 // Returns the corresponding AliPID index to the given pdg code.
1202 // Returns AliPID::kUnkown if pdg belongs to a not considered species.
1204 Int_t absPDGcode = TMath::Abs(pdg);
1205 if (absPDGcode == 211) {//Pion
1206 return AliPID::kPion;
1208 else if (absPDGcode == 321) {//Kaon
1209 return AliPID::kKaon;
1211 else if (absPDGcode == 2212) {//Proton
1212 return AliPID::kProton;
1214 else if (absPDGcode == 11) {//Electron
1215 return AliPID::kElectron;
1217 else if (absPDGcode == 13) {//Muon
1218 return AliPID::kMuon;
1221 return AliPID::kUnknown;
1225 //_____________________________________________________________________________
1226 void AliAnalysisTaskPID::GetJetTrackObservables(Double_t trackPt, Double_t jetPt, Double_t& z, Double_t& xi)
1228 // Uses trackPt and jetPt to obtain z and xi.
1230 z = (jetPt > 0 && trackPt >= 0) ? (trackPt / jetPt) : -1;
1231 xi = (z > 0) ? TMath::Log(1. / z) : -1;
1233 if(trackPt > (1. - 1e-06) * jetPt && trackPt < (1. + 1e-06) * jetPt) { // case z=1 : move entry to last histo bin <1
1240 //_____________________________________________________________________________
1241 void AliAnalysisTaskPID::CleanupParticleFractionHistos()
1243 // Delete histos with particle fractions
1245 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1246 delete fFractionHists[i];
1247 fFractionHists[i] = 0x0;
1249 delete fFractionSysErrorHists[i];
1250 fFractionSysErrorHists[i] = 0x0;
1255 //_____________________________________________________________________________
1256 Double_t AliAnalysisTaskPID::ConvolutedGaus(const Double_t* xx, const Double_t* par) const
1258 // Convolutes gauss with an exponential tail which describes dEdx-response better than pure gaussian
1260 const Double_t mean = par[0];
1261 const Double_t sigma = par[1];
1262 const Double_t lambda = par[2];
1265 printf("File: %s, Line: %d: ConvolutedGaus: mean %e, sigma %e, lambda %e\n", (char*)__FILE__, __LINE__, mean, sigma, lambda);
1267 return lambda/sigma*TMath::Exp(-lambda/sigma*(xx[0]-mean)+lambda*lambda*0.5)*0.5*TMath::Erfc((-xx[0]+mean+sigma*lambda)/sigma*fgkOneOverSqrt2);
1271 //_____________________________________________________________________________
1272 inline Double_t AliAnalysisTaskPID::FastGaus(Double_t x, Double_t mean, Double_t sigma) const
1274 // Calculate an unnormalised gaussian function with mean and sigma.
1276 if (sigma < fgkEpsilon)
1279 const Double_t arg = (x - mean) / sigma;
1280 return exp(-0.5 * arg * arg);
1284 //_____________________________________________________________________________
1285 inline Double_t AliAnalysisTaskPID::FastNormalisedGaus(Double_t x, Double_t mean, Double_t sigma) const
1287 // Calculate a normalised (divided by sqrt(2*Pi)*sigma) gaussian function with mean and sigma.
1289 if (sigma < fgkEpsilon)
1292 const Double_t arg = (x - mean) / sigma;
1293 const Double_t res = exp(-0.5 * arg * arg);
1294 return res / (2.50662827463100024 * sigma); //sqrt(2*Pi)=2.50662827463100024
1298 //_____________________________________________________________________________
1299 Int_t AliAnalysisTaskPID::FindBinWithinRange(TAxis* axis, Double_t value) const
1301 // Find the corresponding bin of the axis. Values outside the range (also under and overflow) will be set to the first/last
1304 Int_t bin = axis->FindFixBin(value);
1308 if (bin > axis->GetNbins())
1309 bin = axis->GetNbins();
1315 //_____________________________________________________________________________
1316 Int_t AliAnalysisTaskPID::FindFirstBinAboveIn3dSubset(const TH3* hist, Double_t threshold, Int_t yBin,
1319 // Kind of projects a TH3 to 1 bin combination in y and z
1320 // and looks for the first x bin above a threshold for this projection.
1321 // If no such bin is found, -1 is returned.
1326 Int_t nBinsX = hist->GetNbinsX();
1327 for (Int_t xBin = 1; xBin <= nBinsX; xBin++) {
1328 if (hist->GetBinContent(xBin, yBin, zBin) > threshold)
1336 //_____________________________________________________________________________
1337 Int_t AliAnalysisTaskPID::FindLastBinAboveIn3dSubset(const TH3* hist, Double_t threshold, Int_t yBin,
1340 // Kind of projects a TH3 to 1 bin combination in y and z
1341 // and looks for the last x bin above a threshold for this projection.
1342 // If no such bin is found, -1 is returned.
1347 Int_t nBinsX = hist->GetNbinsX();
1348 for (Int_t xBin = nBinsX; xBin >= 1; xBin--) {
1349 if (hist->GetBinContent(xBin, yBin, zBin) > threshold)
1357 //_____________________________________________________________________________
1358 Bool_t AliAnalysisTaskPID::GetParticleFraction(Double_t trackPt, Double_t jetPt, Double_t centralityPercentile,
1359 AliPID::EParticleType species,
1360 Double_t& fraction, Double_t& fractionErrorStat, Double_t& fractionErrorSys) const
1362 // Computes the particle fraction for the corresponding species for the given trackPt, jetPt and centrality.
1363 // Use jetPt = -1 for inclusive spectra and centralityPercentile = -1 for pp.
1364 // On success (return value kTRUE), fraction contains the particle fraction, fractionErrorStat(Sys) the sigma of its
1365 // statistical (systematic) error
1368 fractionErrorStat = 999.;
1369 fractionErrorSys = 999.;
1371 if (species > AliPID::kProton || species < AliPID::kElectron) {
1372 AliError(Form("Only fractions for species index %d to %d availabe, but not for the requested one: %d", 0, AliPID::kProton, species));
1376 if (!fFractionHists[species]) {
1377 AliError(Form("Histo with particle fractions for species %d not loaded!", species));
1382 Int_t jetPtBin = FindBinWithinRange(fFractionHists[species]->GetYaxis(), jetPt);
1383 Int_t centBin = FindBinWithinRange(fFractionHists[species]->GetZaxis(), centralityPercentile);
1385 // The following interpolation takes the bin content of the first/last available bin,
1386 // if requested point lies beyond bin center of first/last bin.
1387 // The interpolation is only done for the x-axis (track pT), i.e. jetPtBin and centBin are fix,
1388 // because the analysis will anyhow be run in bins of jetPt and centrality and
1389 // it is not desired to correlate different jetPt bins via interpolation.
1391 // The same procedure is used for the error of the fraction
1392 TAxis* xAxis = fFractionHists[species]->GetXaxis();
1394 // No interpolation to values beyond the centers of the first/last bins (we don't know exactly where the spectra start or stop,
1395 // thus, search for the first and last bin above 0.0 to constrain the range
1396 Int_t firstBin = TMath::Max(1, FindFirstBinAboveIn3dSubset(fFractionHists[species], 0.0, jetPtBin, centBin));
1397 Int_t lastBin = TMath::Min(fFractionHists[species]->GetNbinsX(),
1398 FindLastBinAboveIn3dSubset(fFractionHists[species], 0.0, jetPtBin, centBin));
1400 if (trackPt <= xAxis->GetBinCenter(firstBin)) {
1401 fraction = fFractionHists[species]->GetBinContent(firstBin, jetPtBin, centBin);
1402 fractionErrorStat = fFractionHists[species]->GetBinError(firstBin, jetPtBin, centBin);
1403 fractionErrorSys = fFractionSysErrorHists[species] ? fFractionSysErrorHists[species]->GetBinError(firstBin, jetPtBin, centBin) : 0.;
1405 else if (trackPt >= xAxis->GetBinCenter(lastBin)) {
1406 fraction = fFractionHists[species]->GetBinContent(lastBin, jetPtBin, centBin);
1407 fractionErrorStat = fFractionHists[species]->GetBinError(lastBin, jetPtBin, centBin);
1408 fractionErrorSys = fFractionSysErrorHists[species] ? fFractionSysErrorHists[species]->GetBinError(lastBin, jetPtBin, centBin) : 0.;
1411 Double_t x0 = 0., x1 = 0., y0 = 0., y1 = 0.;
1412 Double_t y0errStat = 0., y1errStat = 0., y0errSys = 0., y1errSys = 0.;
1413 Int_t trackPtBin = xAxis->FindBin(trackPt);
1415 // Linear interpolation between nearest neighbours in trackPt
1416 if (trackPt <= xAxis->GetBinCenter(trackPtBin)) {
1417 y0 = fFractionHists[species]->GetBinContent(trackPtBin - 1, jetPtBin, centBin);
1418 y0errStat = fFractionHists[species]->GetBinError(trackPtBin - 1, jetPtBin, centBin);
1419 y0errSys = fFractionSysErrorHists[species] ? fFractionSysErrorHists[species]->GetBinError(trackPtBin - 1, jetPtBin, centBin)
1421 x0 = xAxis->GetBinCenter(trackPtBin - 1);
1422 y1 = fFractionHists[species]->GetBinContent(trackPtBin, jetPtBin, centBin);
1423 y1errStat = fFractionHists[species]->GetBinError(trackPtBin, jetPtBin, centBin);
1424 y1errSys = fFractionSysErrorHists[species] ? fFractionSysErrorHists[species]->GetBinError(trackPtBin, jetPtBin, centBin)
1426 x1 = xAxis->GetBinCenter(trackPtBin);
1429 y0 = fFractionHists[species]->GetBinContent(trackPtBin, jetPtBin, centBin);
1430 y0errStat = fFractionHists[species]->GetBinError(trackPtBin, jetPtBin, centBin);
1431 y0errSys = fFractionSysErrorHists[species] ? fFractionSysErrorHists[species]->GetBinError(trackPtBin, jetPtBin, centBin)
1433 x0 = xAxis->GetBinCenter(trackPtBin);
1434 y1 = fFractionHists[species]->GetBinContent(trackPtBin + 1, jetPtBin, centBin);
1435 y1errStat = fFractionHists[species]->GetBinError(trackPtBin + 1, jetPtBin, centBin);
1436 y1errSys = fFractionSysErrorHists[species] ? fFractionSysErrorHists[species]->GetBinError(trackPtBin + 1, jetPtBin, centBin)
1438 x1 = xAxis->GetBinCenter(trackPtBin + 1);
1441 // Per construction: x0 < trackPt < x1
1442 fraction = y0 + (trackPt - x0) * ((y1 - y0) / (x1 - x0));
1443 fractionErrorStat = y0errStat + (trackPt - x0) * ((y1errStat - y0errStat) / (x1 - x0));
1444 fractionErrorSys = fFractionSysErrorHists[species] ? (y0errSys + (trackPt - x0) * ((y1errSys - y0errSys) / (x1 - x0))) : 0.;
1451 //_____________________________________________________________________________
1452 Bool_t AliAnalysisTaskPID::GetParticleFractions(Double_t trackPt, Double_t jetPt, Double_t centralityPercentile,
1453 Double_t* prob, Int_t smearSpeciesByError,
1454 Int_t takeIntoAccountSpeciesSysError, Bool_t uniformSystematicError) const
1456 // Fills the particle fractions for the given trackPt, jetPt and centrality into "prob".
1457 // Use jetPt = -1 for inclusive spectra and centralityPercentile = -1 for pp.
1458 // If smearSpeciesByError is >= 0 && < AliPID::kSPECIES, the returned fractions will be a random number distributed
1459 // with a gauss with mean being the corresponding particle fraction and sigma it's error for the considered species
1460 // "smearSpeciesByError".
1461 // Note that in this case the fractions for all species will NOT sum up to 1!
1462 // Thus, all other species fractions will be re-scaled weighted with their corresponding statistical error.
1463 // A similar procedure is used for "takeIntoAccountSpeciesSysError": The systematic error of the corresponding species
1464 // is used to generate a random number with uniform distribution in [mean - sysError, mean + sysError] for the new mean
1465 // (in cace of uniformSystematicError = kTRUE, otherwise it will be a gaus(mean, sysError)),
1466 // then the other species will be re-scaled according to their systematic errors.
1467 // First, the systematic error uncertainty procedure will be performed (that is including re-scaling), then the statistical
1468 // uncertainty procedure.
1469 // On success, kTRUE is returned.
1471 if (!prob || smearSpeciesByError >= AliPID::kSPECIES || takeIntoAccountSpeciesSysError >= AliPID::kSPECIES)
1474 Double_t probTemp[AliPID::kSPECIES];
1475 Double_t probErrorStat[AliPID::kSPECIES];
1476 Double_t probErrorSys[AliPID::kSPECIES];
1478 Bool_t success = kTRUE;
1479 success = success && GetParticleFraction(trackPt, jetPt, centralityPercentile, AliPID::kElectron,
1480 probTemp[AliPID::kElectron], probErrorStat[AliPID::kElectron],
1481 probErrorSys[AliPID::kElectron]);
1482 success = success && GetParticleFraction(trackPt, jetPt, centralityPercentile, AliPID::kMuon,
1483 probTemp[AliPID::kMuon], probErrorStat[AliPID::kMuon], probErrorSys[AliPID::kMuon]);
1484 success = success && GetParticleFraction(trackPt, jetPt, centralityPercentile, AliPID::kPion,
1485 probTemp[AliPID::kPion], probErrorStat[AliPID::kPion], probErrorSys[AliPID::kPion]);
1486 success = success && GetParticleFraction(trackPt, jetPt, centralityPercentile, AliPID::kKaon,
1487 probTemp[AliPID::kKaon], probErrorStat[AliPID::kKaon], probErrorSys[AliPID::kKaon]);
1488 success = success && GetParticleFraction(trackPt, jetPt, centralityPercentile, AliPID::kProton,
1489 probTemp[AliPID::kProton], probErrorStat[AliPID::kProton], probErrorSys[AliPID::kProton]);
1494 // If desired, take into account the systematic error of the corresponding species and re-generate probTemp accordingly
1495 if (takeIntoAccountSpeciesSysError >= 0) {
1496 // Generate random fraction of the considered species "smearSpeciesByError" according to mean and sigma
1497 Double_t generatedFraction = uniformSystematicError
1498 ? fRandom->Rndm() * 2. * probErrorSys[takeIntoAccountSpeciesSysError]
1499 - probErrorSys[takeIntoAccountSpeciesSysError]
1500 + probTemp[takeIntoAccountSpeciesSysError]
1501 : fRandom->Gaus(probTemp[takeIntoAccountSpeciesSysError],
1502 probErrorSys[takeIntoAccountSpeciesSysError]);
1504 // Catch cases with invalid fraction (can happen for large errors), i.e. fraction < 0 or > 1
1505 if (generatedFraction < 0.)
1506 generatedFraction = 0.;
1507 else if (generatedFraction > 1.)
1508 generatedFraction = 1.;
1510 // Calculate difference from original fraction (original fractions sum up to 1!)
1511 Double_t deltaFraction = generatedFraction - probTemp[takeIntoAccountSpeciesSysError];
1513 // Fractions must (including errors) lie inside [0,1] -> Adapt weights accordingly by setting the errors
1514 if (deltaFraction > 0) {
1515 // Some part will be SUBTRACTED from the other fractions
1516 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1517 if (probTemp[i] - probErrorSys[i] < 0)
1518 probErrorSys[i] = probTemp[i];
1522 // Some part will be ADDED to the other fractions
1523 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1524 if (probTemp[i] + probErrorSys[i] > 1)
1525 probErrorSys[i] = 1. - probTemp[i];
1529 // Compute summed weight of all fractions except for the considered one
1530 Double_t summedWeight = 0.;
1531 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1532 if (i != takeIntoAccountSpeciesSysError)
1533 summedWeight += probErrorSys[i];
1536 // Compute the weight for the other species
1538 if (summedWeight <= 1e-13) {
1539 // If this happens for some reason (it should not!), just assume flat weight
1540 printf("Error: summedWeight (sys error) ~ 0 for trackPt %f, jetPt %f, centralityPercentile %f. Setting flat weight!\n",
1541 trackPt, jetPt, centralityPercentile);
1544 Double_t weight[AliPID::kSPECIES];
1545 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1546 if (i != takeIntoAccountSpeciesSysError) {
1547 if (summedWeight > 1e-13)
1548 weight[i] = probErrorSys[i] / summedWeight;
1550 weight[i] = probErrorSys[i] / (AliPID::kSPECIES - 1);
1554 // For the final generated fractions, set the generated value for the considered species
1555 // and the generated value minus delta times statistical weight
1556 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1557 if (i != takeIntoAccountSpeciesSysError)
1558 probTemp[i] = probTemp[i] - weight[i] * deltaFraction;
1560 probTemp[i] = generatedFraction;
1564 // Using the values of probTemp (either the original ones or those after taking into account the systematic error),
1565 // calculate the final fractions - if the statistical error is to be taken into account, smear the corresponding
1566 // fraction. If not, just write probTemp to the final result array.
1567 if (smearSpeciesByError >= 0) {
1568 // Generate random fraction of the considered species "smearSpeciesByError" according to mean and sigma
1569 Double_t generatedFraction = fRandom->Gaus(probTemp[smearSpeciesByError], probErrorStat[smearSpeciesByError]);
1571 // Catch cases with invalid fraction (can happen for large errors), i.e. fraction < 0 or > 1
1572 if (generatedFraction < 0.)
1573 generatedFraction = 0.;
1574 else if (generatedFraction > 1.)
1575 generatedFraction = 1.;
1577 // Calculate difference from original fraction (original fractions sum up to 1!)
1578 Double_t deltaFraction = generatedFraction - probTemp[smearSpeciesByError];
1580 // Fractions must (including errors) lie inside [0,1] -> Adapt weights accordingly by setting the errors
1581 if (deltaFraction > 0) {
1582 // Some part will be SUBTRACTED from the other fractions
1583 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1584 if (probTemp[i] - probErrorStat[i] < 0)
1585 probErrorStat[i] = probTemp[i];
1589 // Some part will be ADDED to the other fractions
1590 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1591 if (probTemp[i] + probErrorStat[i] > 1)
1592 probErrorStat[i] = 1. - probTemp[i];
1596 // Compute summed weight of all fractions except for the considered one
1597 Double_t summedWeight = 0.;
1598 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1599 if (i != smearSpeciesByError)
1600 summedWeight += probErrorStat[i];
1603 // Compute the weight for the other species
1605 if (summedWeight <= 1e-13) {
1606 // If this happens for some reason (it should not!), just assume flat weight
1607 printf("Error: summedWeight (stat error) ~ 0 for trackPt %f, jetPt %f, centralityPercentile %f. Setting flat weight!\n",
1608 trackPt, jetPt, centralityPercentile);
1611 Double_t weight[AliPID::kSPECIES];
1612 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1613 if (i != smearSpeciesByError) {
1614 if (summedWeight > 1e-13)
1615 weight[i] = probErrorStat[i] / summedWeight;
1617 weight[i] = probErrorStat[i] / (AliPID::kSPECIES - 1);
1621 // For the final generated fractions, set the generated value for the considered species
1622 // and the generated value minus delta times statistical weight
1623 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1624 if (i != smearSpeciesByError)
1625 prob[i] = probTemp[i] - weight[i] * deltaFraction;
1627 prob[i] = generatedFraction;
1631 // Just take the generated values
1632 for (Int_t i = 0; i < AliPID::kSPECIES; i++)
1633 prob[i] = probTemp[i];
1637 // Should already be normalised, but make sure that it really is:
1638 Double_t probSum = 0.;
1639 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1646 if (TMath::Abs(probSum - 1.0) > 1e-4) {
1647 printf("Warning: Re-normalising sum of fractions: Sum is %e\n", probSum);
1648 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1657 //_____________________________________________________________________________
1658 const TH3D* AliAnalysisTaskPID::GetParticleFractionHisto(Int_t species, Bool_t sysError) const
1660 if (species < AliPID::kElectron || species > AliPID::kProton)
1663 return sysError ? fFractionSysErrorHists[species] : fFractionHists[species];
1667 //_____________________________________________________________________________
1668 Double_t AliAnalysisTaskPID::GetMCStrangenessFactorCMS(Int_t motherPDG, Double_t motherGenPt)
1670 // Strangeness ratio MC/data as function of mother pt from CMS data in |eta|<2.0
1671 // -> Based on function in PWGJE/AliAnalysisTaskFragmentationFunction, which uses
1672 // the following data from CMS pp @ 7 TeV inclusive (JHEP 05 (2011) 064)
1676 const Int_t absMotherPDG = TMath::Abs(motherPDG);
1678 if (absMotherPDG == 310 || absMotherPDG == 321) { // K0s / K+ / K-
1679 if (0.00 <= motherGenPt && motherGenPt < 0.20) fac = 0.768049;
1680 else if(0.20 <= motherGenPt && motherGenPt < 0.40) fac = 0.732933;
1681 else if(0.40 <= motherGenPt && motherGenPt < 0.60) fac = 0.650298;
1682 else if(0.60 <= motherGenPt && motherGenPt < 0.80) fac = 0.571332;
1683 else if(0.80 <= motherGenPt && motherGenPt < 1.00) fac = 0.518734;
1684 else if(1.00 <= motherGenPt && motherGenPt < 1.20) fac = 0.492543;
1685 else if(1.20 <= motherGenPt && motherGenPt < 1.40) fac = 0.482704;
1686 else if(1.40 <= motherGenPt && motherGenPt < 1.60) fac = 0.488056;
1687 else if(1.60 <= motherGenPt && motherGenPt < 1.80) fac = 0.488861;
1688 else if(1.80 <= motherGenPt && motherGenPt < 2.00) fac = 0.492862;
1689 else if(2.00 <= motherGenPt && motherGenPt < 2.20) fac = 0.504332;
1690 else if(2.20 <= motherGenPt && motherGenPt < 2.40) fac = 0.501858;
1691 else if(2.40 <= motherGenPt && motherGenPt < 2.60) fac = 0.512970;
1692 else if(2.60 <= motherGenPt && motherGenPt < 2.80) fac = 0.524131;
1693 else if(2.80 <= motherGenPt && motherGenPt < 3.00) fac = 0.539130;
1694 else if(3.00 <= motherGenPt && motherGenPt < 3.20) fac = 0.554101;
1695 else if(3.20 <= motherGenPt && motherGenPt < 3.40) fac = 0.560348;
1696 else if(3.40 <= motherGenPt && motherGenPt < 3.60) fac = 0.568869;
1697 else if(3.60 <= motherGenPt && motherGenPt < 3.80) fac = 0.583310;
1698 else if(3.80 <= motherGenPt && motherGenPt < 4.00) fac = 0.604818;
1699 else if(4.00 <= motherGenPt && motherGenPt < 5.00) fac = 0.632630;
1700 else if(5.00 <= motherGenPt && motherGenPt < 6.00) fac = 0.710070;
1701 else if(6.00 <= motherGenPt && motherGenPt < 8.00) fac = 0.736365;
1702 else if(8.00 <= motherGenPt && motherGenPt < 10.00) fac = 0.835865;
1705 if (absMotherPDG == 3122) { // Lambda
1706 if (0.00 <= motherGenPt && motherGenPt < 0.20) fac = 0.645162;
1707 else if(0.20 <= motherGenPt && motherGenPt < 0.40) fac = 0.627431;
1708 else if(0.40 <= motherGenPt && motherGenPt < 0.60) fac = 0.457136;
1709 else if(0.60 <= motherGenPt && motherGenPt < 0.80) fac = 0.384369;
1710 else if(0.80 <= motherGenPt && motherGenPt < 1.00) fac = 0.330597;
1711 else if(1.00 <= motherGenPt && motherGenPt < 1.20) fac = 0.309571;
1712 else if(1.20 <= motherGenPt && motherGenPt < 1.40) fac = 0.293620;
1713 else if(1.40 <= motherGenPt && motherGenPt < 1.60) fac = 0.283709;
1714 else if(1.60 <= motherGenPt && motherGenPt < 1.80) fac = 0.282047;
1715 else if(1.80 <= motherGenPt && motherGenPt < 2.00) fac = 0.277261;
1716 else if(2.00 <= motherGenPt && motherGenPt < 2.20) fac = 0.275772;
1717 else if(2.20 <= motherGenPt && motherGenPt < 2.40) fac = 0.280726;
1718 else if(2.40 <= motherGenPt && motherGenPt < 2.60) fac = 0.288540;
1719 else if(2.60 <= motherGenPt && motherGenPt < 2.80) fac = 0.288315;
1720 else if(2.80 <= motherGenPt && motherGenPt < 3.00) fac = 0.296619;
1721 else if(3.00 <= motherGenPt && motherGenPt < 3.20) fac = 0.302993;
1722 else if(3.20 <= motherGenPt && motherGenPt < 3.40) fac = 0.338121;
1723 else if(3.40 <= motherGenPt && motherGenPt < 3.60) fac = 0.349800;
1724 else if(3.60 <= motherGenPt && motherGenPt < 3.80) fac = 0.356802;
1725 else if(3.80 <= motherGenPt && motherGenPt < 4.00) fac = 0.391202;
1726 else if(4.00 <= motherGenPt && motherGenPt < 5.00) fac = 0.422573;
1727 else if(5.00 <= motherGenPt && motherGenPt < 6.00) fac = 0.573815;
1728 else if(6.00 <= motherGenPt && motherGenPt < 8.00) fac = 0.786984;
1729 else if(8.00 <= motherGenPt && motherGenPt < 10.00) fac = 1.020021;
1732 if (absMotherPDG == 3312 || absMotherPDG == 3322) { // xi
1733 if (0.00 <= motherGenPt && motherGenPt < 0.20) fac = 0.666620;
1734 else if(0.20 <= motherGenPt && motherGenPt < 0.40) fac = 0.575908;
1735 else if(0.40 <= motherGenPt && motherGenPt < 0.60) fac = 0.433198;
1736 else if(0.60 <= motherGenPt && motherGenPt < 0.80) fac = 0.340901;
1737 else if(0.80 <= motherGenPt && motherGenPt < 1.00) fac = 0.290896;
1738 else if(1.00 <= motherGenPt && motherGenPt < 1.20) fac = 0.236074;
1739 else if(1.20 <= motherGenPt && motherGenPt < 1.40) fac = 0.218681;
1740 else if(1.40 <= motherGenPt && motherGenPt < 1.60) fac = 0.207763;
1741 else if(1.60 <= motherGenPt && motherGenPt < 1.80) fac = 0.222848;
1742 else if(1.80 <= motherGenPt && motherGenPt < 2.00) fac = 0.208806;
1743 else if(2.00 <= motherGenPt && motherGenPt < 2.20) fac = 0.197275;
1744 else if(2.20 <= motherGenPt && motherGenPt < 2.40) fac = 0.183645;
1745 else if(2.40 <= motherGenPt && motherGenPt < 2.60) fac = 0.188788;
1746 else if(2.60 <= motherGenPt && motherGenPt < 2.80) fac = 0.188282;
1747 else if(2.80 <= motherGenPt && motherGenPt < 3.00) fac = 0.207442;
1748 else if(3.00 <= motherGenPt && motherGenPt < 3.20) fac = 0.240388;
1749 else if(3.20 <= motherGenPt && motherGenPt < 3.40) fac = 0.241916;
1750 else if(3.40 <= motherGenPt && motherGenPt < 3.60) fac = 0.208276;
1751 else if(3.60 <= motherGenPt && motherGenPt < 3.80) fac = 0.234550;
1752 else if(3.80 <= motherGenPt && motherGenPt < 4.00) fac = 0.251689;
1753 else if(4.00 <= motherGenPt && motherGenPt < 5.00) fac = 0.310204;
1754 else if(5.00 <= motherGenPt && motherGenPt < 6.00) fac = 0.343492;
1757 const Double_t weight = 1. / fac;
1763 //_____________________________________________________________________________
1764 Double_t AliAnalysisTaskPID::GetMCStrangenessFactorCMS(AliMCEvent* mcEvent, AliMCParticle* daughter)
1766 // Strangeness ratio MC/data as function of mother pt from CMS data in |eta|<2.0
1767 // -> Based on function in PWGJE/AliAnalysisTaskFragmentationFunction
1772 AliMCParticle* currentMother = daughter;
1773 AliMCParticle* currentDaughter = daughter;
1776 // find first primary mother K0s, Lambda or Xi
1778 Int_t daughterPDG = currentDaughter->PdgCode();
1780 Int_t motherLabel = currentDaughter->GetMother();
1781 if(motherLabel >= mcEvent->GetNumberOfTracks()){ // protection
1782 currentMother = currentDaughter;
1786 currentMother = (AliMCParticle*)mcEvent->GetTrack(motherLabel);
1788 if (!currentMother) {
1789 currentMother = currentDaughter;
1793 Int_t motherPDG = currentMother->PdgCode();
1795 // phys. primary found ?
1796 if (mcEvent->IsPhysicalPrimary(motherLabel))
1799 if (TMath::Abs(daughterPDG) == 321) {
1800 // K+/K- e.g. from phi (ref data not feeddown corrected)
1801 currentMother = currentDaughter;
1804 if (TMath::Abs(motherPDG) == 310) {
1805 // K0s e.g. from phi (ref data not feeddown corrected)
1808 if (TMath::Abs(motherPDG) == 3212 && TMath::Abs(daughterPDG) == 3122) {
1809 // Mother Sigma0, daughter Lambda (this case not included in feeddown corr.)
1810 currentMother = currentDaughter;
1814 currentDaughter = currentMother;
1818 Int_t motherPDG = currentMother->PdgCode();
1819 Double_t motherGenPt = currentMother->Pt();
1821 return GetMCStrangenessFactorCMS(motherPDG, motherGenPt);
1825 // _________________________________________________________________________________
1826 AliAnalysisTaskPID::TOFpidInfo AliAnalysisTaskPID::GetTOFType(const AliVTrack* track, Int_t tofMode) const
1828 // Get the (locally defined) particle type judged by TOF
1830 if (!fPIDResponse) {
1831 Printf("ERROR: fEvent not available -> Cannot determine TOF type!");
1835 // Check kTOFout, kTIME, mismatch
1836 const AliPIDResponse::EDetPidStatus tofStatus = fPIDResponse->CheckPIDStatus(AliPIDResponse::kTOF, track);
1837 if (tofStatus != AliPIDResponse::kDetPidOk)
1840 Double_t nsigma[kNumTOFspecies + 1] = { -999., -999., -999., -999. };
1841 nsigma[kTOFpion] = fPIDResponse->NumberOfSigmasTOF(track, AliPID::kPion);
1842 nsigma[kTOFkaon] = fPIDResponse->NumberOfSigmasTOF(track, AliPID::kKaon);
1843 nsigma[kTOFproton] = fPIDResponse->NumberOfSigmasTOF(track, AliPID::kProton);
1845 Double_t inclusion = -999;
1846 Double_t exclusion = -999;
1852 else if (tofMode == 1) { // default
1856 else if (tofMode == 2) {
1861 Printf("ERROR: Bad TOF mode: %d!", tofMode);
1865 // Do not cut on nSigma electron because this would also remove pions in a large pT range.
1866 // The electron contamination of the pion sample can be treated by TPC dEdx fits afterwards.
1867 if (TMath::Abs(nsigma[kTOFpion]) < inclusion && TMath::Abs(nsigma[kTOFkaon]) > exclusion && TMath::Abs(nsigma[kTOFproton]) > exclusion)
1869 if (TMath::Abs(nsigma[kTOFpion]) > exclusion && TMath::Abs(nsigma[kTOFkaon]) < inclusion && TMath::Abs(nsigma[kTOFproton]) > exclusion)
1871 if (TMath::Abs(nsigma[kTOFpion]) > exclusion && TMath::Abs(nsigma[kTOFkaon]) > exclusion && TMath::Abs(nsigma[kTOFproton]) < inclusion)
1874 // There are no TOF electrons selected because the purity is rather bad, even for small momenta
1875 // (also a small mismatch probability significantly affects electrons because their fraction
1876 // is small). There is no need for TOF electrons anyway, since the dEdx distribution of kaons and
1877 // protons in a given pT bin (also at the dEdx crossings) is very different from that of electrons.
1878 // This is due to the steeply falling dEdx of p and K with momentum, whereas the electron dEdx stays
1880 // As a result, the TPC fit yields a more accurate electron fraction than the TOF selection can do.
1886 // _________________________________________________________________________________
1887 Bool_t AliAnalysisTaskPID::IsSecondaryWithStrangeMotherMC(AliMCEvent* mcEvent, Int_t partLabel)
1889 // Check whether particle is a secondary with strange mother, i.e. returns kTRUE if a strange mother is found
1890 // and the particle is NOT a physical primary. In all other cases kFALSE is returned
1892 if (!mcEvent || partLabel < 0)
1895 AliMCParticle* part = (AliMCParticle*)mcEvent->GetTrack(partLabel);
1900 if (mcEvent->IsPhysicalPrimary(partLabel))
1903 Int_t iMother = part->GetMother();
1908 AliMCParticle* partM = (AliMCParticle*)mcEvent->GetTrack(iMother);
1912 Int_t codeM = TMath::Abs(partM->PdgCode());
1913 Int_t mfl = Int_t(codeM / TMath::Power(10, Int_t(TMath::Log10(codeM))));
1914 if (mfl == 3 && codeM != 3) // codeM = 3 is for s quark
1921 //_____________________________________________________________________________
1922 Bool_t AliAnalysisTaskPID::SetParticleFractionHisto(const TH3D* hist, Int_t species, Bool_t sysError)
1924 // Store a clone of hist (containing the particle fractions of the corresponding species with statistical error (sysError = kFALSE)
1925 // or systematic error (sysError = kTRUE), respectively), internally
1927 if (species < AliPID::kElectron || species > AliPID::kProton) {
1928 AliError(Form("Only fractions for species index %d to %d can be set, but not for the requested one: %d", 0,
1929 AliPID::kProton, species));
1934 delete fFractionSysErrorHists[species];
1936 fFractionSysErrorHists[species] = new TH3D(*hist);
1939 delete fFractionHists[species];
1941 fFractionHists[species] = new TH3D(*hist);
1948 //_____________________________________________________________________________
1949 Bool_t AliAnalysisTaskPID::SetParticleFractionHistosFromFile(const TString filePathName, Bool_t sysError)
1951 // Loads particle fractions for all species from the desired file and returns kTRUE on success.
1952 // The maps are assumed to be of Type TH3D, to sit in the main directory and to have names
1953 // Form("hFraction_%e", AliPID::ParticleName(i)) for sysError = kFALSE and
1954 // Form("hFractionSysError_%e", AliPID::ParticleName(i)) for sysError = kTRUE.
1956 TFile* f = TFile::Open(filePathName.Data());
1958 std::cout << "Failed to open file with particle fractions \"" << filePathName.Data() << "\"!" << std::endl;
1963 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
1964 TString histName = Form("hFraction%s_%s", sysError ? "SysError" : "", AliPID::ParticleName(i));
1965 hist = dynamic_cast<TH3D*>(f->Get(histName.Data()));
1967 std::cout << "Failed to load particle fractions for " << histName.Data() << "!";
1968 std::cout << std::endl << "Cleaning up particle fraction histos!" << std::endl;
1969 CleanupParticleFractionHistos();
1973 if (!SetParticleFractionHisto(hist, i, sysError)) {
1974 std::cout << "Failed to load particle fractions for " << histName.Data() << "!";
1975 std::cout << std::endl << "Cleaning up particle fraction histos!" << std::endl;
1976 CleanupParticleFractionHistos();
1988 //_____________________________________________________________________________
1989 Double_t AliAnalysisTaskPID::GetMaxEtaVariation(Double_t dEdxSplines)
1991 // Returns the maximum eta variation (i.e. deviation of eta correction factor from unity) for the
1992 // given (spline) dEdx
1994 if (dEdxSplines < 1. || !fhMaxEtaVariation) {
1995 Printf("Error GetMaxEtaVariation: No map or invalid dEdxSplines (%f)!", dEdxSplines);
1999 Int_t bin = fhMaxEtaVariation->GetXaxis()->FindFixBin(1. / dEdxSplines);
2003 if (bin > fhMaxEtaVariation->GetXaxis()->GetNbins())
2004 bin = fhMaxEtaVariation->GetXaxis()->GetNbins();
2006 return fhMaxEtaVariation->GetBinContent(bin);
2010 //_____________________________________________________________________________
2011 Int_t AliAnalysisTaskPID::GetRandomParticleTypeAccordingToParticleFractions(Double_t trackPt, Double_t jetPt,
2012 Double_t centralityPercentile,
2013 Bool_t smearByError,
2014 Bool_t takeIntoAccountSysError) const
2016 // Uses the stored histograms with the particle fractions to generate a random particle type according to these fractions.
2017 // In case of problems (e.g. histo missing), AliPID::kUnknown is returned.
2018 // If smearByError is kTRUE, the used fractions will be random numbers distributed with a gauss with mean
2019 // being the corresponding particle fraction and sigma it's error.
2020 // Note that in this case only the fraction of a random species is varied in this way. The other fractions
2021 // will be re-normalised according their statistical errors.
2022 // The same holds for the systematic error of species "takeIntoAccountSpeciesSysError", but the random number will be
2023 // uniformly distributed within [mean - sys, mean + sys] and the re-normalisation will be weighted with the systematic errors.
2024 // Note that the fractions will be calculated first with only the systematic error taken into account (if desired), including
2025 // re-normalisation. Then, the resulting fractions will be used to calculate the final fractions - either with statistical error
2026 // or without. The species, for which the error will be used for smearing, is the same for sys and stat error.
2028 Double_t prob[AliPID::kSPECIES];
2029 Int_t randomSpecies = (smearByError || takeIntoAccountSysError) ? (Int_t)(fRandom->Rndm() * AliPID::kSPECIES) : -1;
2030 Bool_t success = GetParticleFractions(trackPt, jetPt, centralityPercentile, prob, randomSpecies, randomSpecies);
2033 return AliPID::kUnknown;
2035 Double_t rnd = fRandom->Rndm(); // Produce uniformly distributed floating point in ]0, 1]
2037 if (rnd <= prob[AliPID::kPion])
2038 return AliPID::kPion;
2039 else if (rnd <= prob[AliPID::kPion] + prob[AliPID::kKaon])
2040 return AliPID::kKaon;
2041 else if (rnd <= prob[AliPID::kPion] + prob[AliPID::kKaon] + prob[AliPID::kProton])
2042 return AliPID::kProton;
2043 else if (rnd <= prob[AliPID::kPion] + prob[AliPID::kKaon] + prob[AliPID::kProton] + prob[AliPID::kElectron])
2044 return AliPID::kElectron;
2046 return AliPID::kMuon; //else it must be a muon (only species left)
2050 //_____________________________________________________________________________
2051 AliAnalysisTaskPID::ErrorCode AliAnalysisTaskPID::GenerateDetectorResponse(AliAnalysisTaskPID::ErrorCode errCode,
2052 Double_t mean, Double_t sigma,
2053 Double_t* responses, Int_t nResponses,
2056 // Generate detector response. If a previous generation was not successful or there is something wrong with this signal generation,
2057 // the function will return kFALSE
2061 // Reset response array
2062 for (Int_t i = 0; i < nResponses; i++)
2063 responses[i] = -999;
2065 if (errCode == kError)
2068 ErrorCode ownErrCode = kNoErrors;
2070 if (fUseConvolutedGaus && !usePureGaus) {
2071 // In case of convoluted gauss, calculate the probability density only once to save a lot of time!
2073 TH1* hProbDensity = 0x0;
2074 ownErrCode = SetParamsForConvolutedGaus(mean, sigma);
2075 if (ownErrCode == kError)
2078 hProbDensity = fConvolutedGausDeltaPrime->GetHistogram();
2080 for (Int_t i = 0; i < nResponses; i++) {
2081 responses[i] = hProbDensity->GetRandom();
2082 //responses[i] fConvolutedGausDeltaPrime->GetRandom(); // MUCH slower than using the binned version via the histogram
2086 for (Int_t i = 0; i < nResponses; i++) {
2087 responses[i] = fRandom->Gaus(mean, sigma);
2091 // If forwarded error code was a warning (error case has been handled before), return a warning
2092 if (errCode == kWarning)
2095 return ownErrCode; // Forward success/warning
2099 //_____________________________________________________________________________
2100 void AliAnalysisTaskPID::PrintSettings(Bool_t printSystematicsSettings) const
2102 // Print current settings.
2104 printf("\n\nSettings for task %s:\n", GetName());
2105 printf("Is pPb/Pbp: %d -> %s\n", GetIsPbpOrpPb(), GetIsPbpOrpPb() ? "Adapting vertex cuts" : "Using standard vertex cuts");
2106 printf("Track cuts: %s\n", fTrackFilter ? fTrackFilter->GetTitle() : "-");
2107 printf("Eta cut: %.2f <= |eta| <= %.2f\n", GetEtaAbsCutLow(), GetEtaAbsCutUp());
2108 printf("Phi' cut: %d\n", GetUsePhiCut());
2109 printf("TPCCutMIGeo: %d\n", GetUseTPCCutMIGeo());
2110 if (GetUseTPCCutMIGeo()) {
2111 printf("GetCutGeo: %f\n", GetCutGeo());
2112 printf("GetCutNcr: %f\n", GetCutNcr());
2113 printf("GetCutNcl: %f\n", GetCutNcl());
2115 printf("TPCnclCut: %d\n", GetUseTPCnclCut());
2116 if (GetUseTPCnclCut()) {
2117 printf("GetCutPureNcl: %d\n", GetCutPureNcl());
2122 printf("Centrality estimator: %s\n", GetCentralityEstimator().Data());
2126 printf("Use MC-ID for signal generation: %d\n", GetUseMCidForGeneration());
2127 printf("Use ITS: %d\n", GetUseITS());
2128 printf("Use TOF: %d\n", GetUseTOF());
2129 printf("Use priors: %d\n", GetUsePriors());
2130 printf("Use TPC default priors: %d\n", GetUseTPCDefaultPriors());
2131 printf("Use convoluted Gauss: %d\n", GetUseConvolutedGaus());
2132 printf("Accuracy of non-Gaussian tail: %e\n", GetAccuracyNonGaussianTail());
2133 printf("Take into account muons: %d\n", GetTakeIntoAccountMuons());
2134 printf("TOF mode: %d\n", GetTOFmode());
2135 printf("\nParams for transition from gauss to asymmetric shape:\n");
2136 printf("[0]: %e\n", GetConvolutedGaussTransitionPar(0));
2137 printf("[1]: %e\n", GetConvolutedGaussTransitionPar(1));
2138 printf("[2]: %e\n", GetConvolutedGaussTransitionPar(2));
2142 printf("Do PID: %d\n", fDoPID);
2143 printf("Do Efficiency: %d\n", fDoEfficiency);
2144 printf("Do PtResolution: %d\n", fDoPtResolution);
2148 printf("Input from other task: %d\n", GetInputFromOtherTask());
2149 printf("Store additional jet information: %d\n", GetStoreAdditionalJetInformation());
2150 printf("Store centrality percentile: %d", GetStoreCentralityPercentile());
2152 if (printSystematicsSettings)
2153 PrintSystematicsSettings();
2159 //_____________________________________________________________________________
2160 void AliAnalysisTaskPID::PrintSystematicsSettings() const
2162 // Print current settings for systematic studies.
2164 printf("\n\nSettings for systematics for task %s:\n", GetName());
2165 printf("SplinesThr:\t%f\n", GetSystematicScalingSplinesThreshold());
2166 printf("SplinesBelowThr:\t%f\n", GetSystematicScalingSplinesBelowThreshold());
2167 printf("SplinesAboveThr:\t%f\n", GetSystematicScalingSplinesAboveThreshold());
2168 printf("EtaCorrMomThr:\t%f\n", GetSystematicScalingEtaCorrectionMomentumThr());
2169 printf("EtaCorrLowP:\t%f\n", GetSystematicScalingEtaCorrectionLowMomenta());
2170 printf("EtaCorrHighP:\t%f\n", GetSystematicScalingEtaCorrectionHighMomenta());
2171 printf("SigmaParaThr:\t%f\n", GetSystematicScalingEtaSigmaParaThreshold());
2172 printf("SigmaParaBelowThr:\t%f\n", GetSystematicScalingEtaSigmaParaBelowThreshold());
2173 printf("SigmaParaAboveThr:\t%f\n", GetSystematicScalingEtaSigmaParaAboveThreshold());
2174 printf("MultCorr:\t%f\n", GetSystematicScalingMultCorrection());
2175 printf("TOF mode: %d\n", GetTOFmode());
2181 //_____________________________________________________________________________
2182 Bool_t AliAnalysisTaskPID::ProcessTrack(const AliVTrack* track, Int_t particlePDGcode, Double_t centralityPercentile,
2185 // Process the track (generate expected response, fill histos, etc.).
2186 // particlePDGcode == 0 means data. Otherwise, the corresponding MC ID will be assumed.
2188 //Printf("Debug: Task %s is starting to process track: dEdx %f, pTPC %f, eta %f, ncl %d\n", GetName(), track->GetTPCsignal(), track->GetTPCmomentum(),
2189 // track->Eta(), track->GetTPCsignalN());
2192 printf("File: %s, Line: %d: ProcessTrack\n", (char*)__FILE__, __LINE__);
2198 printf("File: %s, Line: %d: ProcessTrack -> Processing started\n", (char*)__FILE__, __LINE__);
2200 const Bool_t isMC = (particlePDGcode == 0) ? kFALSE : kTRUE;
2205 if (TMath::Abs(particlePDGcode) == 211) {//Pion
2208 else if (TMath::Abs(particlePDGcode) == 321) {//Kaon
2211 else if (TMath::Abs(particlePDGcode) == 2212) {//Proton
2214 else if (TMath::Abs(particlePDGcode) == 11) {//Electron
2217 else if (TMath::Abs(particlePDGcode) == 13) {//Muon
2220 else // In MC-ID case, set to underflow bin such that the response from this track is only used for unidentified signal generation
2221 // or signal generation with PID response and the track is still there (as in data) - e.g. relevant w.r.t. deuterons.
2222 // This is important to be as much as possible consistent with data. And the tracks can still be removed by disabling the
2223 // underflow bin for the projections
2228 //Double_t p = track->GetP();
2229 const Double_t pTPC = track->GetTPCmomentum();
2230 Double_t pT = track->Pt();
2232 Double_t z = -1, xi = -1;
2233 GetJetTrackObservables(pT, jetPt, z, xi);
2236 Double_t trackCharge = track->Charge();
2239 const Bool_t tuneOnDataTPC = fPIDResponse->IsTunedOnData() &&
2240 ((fPIDResponse->GetTunedOnDataMask() & AliPIDResponse::kDetTPC) == AliPIDResponse::kDetTPC);
2241 Double_t dEdxTPC = tuneOnDataTPC ? fPIDResponse->GetTPCsignalTunedOnData(track) : track->GetTPCsignal();
2244 Printf("Skipping track with strange dEdx value: dEdx %f, pTPC %f, eta %f, ncl %d\n", track->GetTPCsignal(), pTPC,
2245 track->Eta(), track->GetTPCsignalN());
2249 // Completely remove tracks from light nuclei defined by el and pr <dEdx> as function of pT.
2250 // A very loose cut to be sure not to throw away electrons and/or protons
2251 Double_t nSigmaPr = fPIDResponse->NumberOfSigmasTPC(track, AliPID::kProton);
2252 Double_t nSigmaEl = fPIDResponse->NumberOfSigmasTPC(track, AliPID::kElectron);
2254 if ((pTPC >= 0.3 && (nSigmaPr > 10 && nSigmaEl > 10)) ||
2255 (pTPC < 0.3 && (nSigmaPr > 15 && nSigmaEl > 15))) {
2256 Printf("Skipping track which seems to be a light nuclei: dEdx %f, pTPC %f, pT %f, eta %f, ncl %d, nSigmaPr %f, nSigmaEl %f\n",
2257 track->GetTPCsignal(), pTPC, pT, track->Eta(), track->GetTPCsignalN(), nSigmaPr, nSigmaEl);
2262 Double_t dEdxEl, dEdxKa, dEdxPi, dEdxMu, dEdxPr;
2263 Double_t sigmaEl, sigmaKa, sigmaPi, sigmaMu, sigmaPr;
2265 if (fDoAnySystematicStudiesOnTheExpectedSignal) {
2266 // Get the uncorrected signal first and the corresponding correction factors.
2267 // Then modify the correction factors and properly recalculate the corrected dEdx
2269 // Get pure spline values for dEdx_expected, without any correction
2270 dEdxEl = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault, kFALSE, kFALSE);
2271 dEdxKa = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kKaon, AliTPCPIDResponse::kdEdxDefault, kFALSE, kFALSE);
2272 dEdxPi = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault, kFALSE, kFALSE);
2273 dEdxMu = !fTakeIntoAccountMuons ? -1 :
2274 fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kMuon, AliTPCPIDResponse::kdEdxDefault, kFALSE, kFALSE);
2275 dEdxPr = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault, kFALSE, kFALSE);
2277 // Scale splines, if desired
2278 if ((TMath::Abs(fSystematicScalingSplinesBelowThreshold - 1.0) > fgkEpsilon) ||
2279 (TMath::Abs(fSystematicScalingSplinesAboveThreshold - 1.0) > fgkEpsilon)) {
2281 // Tune turn-on of correction for pions (not so relevant for the other species, since at very large momenta)
2283 Double_t scaleFactor = 1.;
2284 Double_t usedSystematicScalingSplines = 1.;
2286 bg = pTPC / AliPID::ParticleMass(AliPID::kElectron);
2287 scaleFactor = 0.5 * (1. + TMath::Erf((bg - fSystematicScalingSplinesThreshold) / 4.));
2288 usedSystematicScalingSplines = fSystematicScalingSplinesBelowThreshold * (1 - scaleFactor)
2289 + fSystematicScalingSplinesAboveThreshold * scaleFactor;
2290 dEdxEl *= usedSystematicScalingSplines;
2292 bg = pTPC / AliPID::ParticleMass(AliPID::kKaon);
2293 scaleFactor = 0.5 * (1. + TMath::Erf((bg - fSystematicScalingSplinesThreshold) / 4.));
2294 usedSystematicScalingSplines = fSystematicScalingSplinesBelowThreshold * (1 - scaleFactor)
2295 + fSystematicScalingSplinesAboveThreshold * scaleFactor;
2296 dEdxKa *= usedSystematicScalingSplines;
2298 bg = pTPC / AliPID::ParticleMass(AliPID::kPion);
2299 scaleFactor = 0.5 * (1. + TMath::Erf((bg - fSystematicScalingSplinesThreshold) / 4.));
2300 usedSystematicScalingSplines = fSystematicScalingSplinesBelowThreshold * (1 - scaleFactor)
2301 + fSystematicScalingSplinesAboveThreshold * scaleFactor;
2302 dEdxPi *= usedSystematicScalingSplines;
2304 if (fTakeIntoAccountMuons) {
2305 bg = pTPC / AliPID::ParticleMass(AliPID::kMuon);
2306 scaleFactor = 0.5 * (1. + TMath::Erf((bg - fSystematicScalingSplinesThreshold) / 4.));
2307 usedSystematicScalingSplines = fSystematicScalingSplinesBelowThreshold * (1 - scaleFactor)
2308 + fSystematicScalingSplinesAboveThreshold * scaleFactor;
2309 dEdxMu *= usedSystematicScalingSplines;
2313 bg = pTPC / AliPID::ParticleMass(AliPID::kProton);
2314 scaleFactor = 0.5 * (1. + TMath::Erf((bg - fSystematicScalingSplinesThreshold) / 4.));
2315 usedSystematicScalingSplines = fSystematicScalingSplinesBelowThreshold * (1 - scaleFactor)
2316 + fSystematicScalingSplinesAboveThreshold * scaleFactor;
2317 dEdxPr *= usedSystematicScalingSplines;
2320 // Get the eta correction factors for the (modified) expected dEdx
2321 Double_t etaCorrEl = fPIDResponse->UseTPCEtaCorrection() ? fPIDResponse->GetTPCResponse().GetEtaCorrectionFast(track, dEdxEl) : 1.;
2322 Double_t etaCorrKa = fPIDResponse->UseTPCEtaCorrection() ? fPIDResponse->GetTPCResponse().GetEtaCorrectionFast(track, dEdxKa) : 1.;
2323 Double_t etaCorrPi = fPIDResponse->UseTPCEtaCorrection() ? fPIDResponse->GetTPCResponse().GetEtaCorrectionFast(track, dEdxPi) : 1.;
2324 Double_t etaCorrMu = fTakeIntoAccountMuons && fPIDResponse->UseTPCEtaCorrection() ?
2325 fPIDResponse->GetTPCResponse().GetEtaCorrectionFast(track, dEdxMu) : 1.;
2326 Double_t etaCorrPr = fPIDResponse->UseTPCEtaCorrection() ? fPIDResponse->GetTPCResponse().GetEtaCorrectionFast(track, dEdxPr) : 1.;
2328 // Scale eta correction factors, if desired (and eta correction maps are to be used, otherwise it is not possible!)
2329 if (fPIDResponse->UseTPCEtaCorrection() &&
2330 (TMath::Abs(fSystematicScalingEtaCorrectionHighMomenta - 1.0) > fgkEpsilon ||
2331 TMath::Abs(fSystematicScalingEtaCorrectionLowMomenta - 1.0) > fgkEpsilon)) {
2332 // Since we do not want to scale the splines with this, but only the eta variation, only scale the deviation of the correction factor!
2333 // E.g. if we would have a flat eta depence fixed at 1.0, we would shift the whole thing equal to shifting the splines by the same factor!
2336 // Due to additional azimuthal effects, there is an additional eta dependence for low momenta which is not corrected successfully so far.
2337 // One can assign a different (higher) systematic scale factor for this low-p region and a threshold which separates low- and high-p.
2338 // An ERF will be used to get (as a function of p_TPC) from one correction factor to the other within roughly 0.2 GeV/c
2339 Double_t usedSystematicScalingEtaCorrection = fSystematicScalingEtaCorrectionHighMomenta;
2341 if (TMath::Abs(fSystematicScalingEtaCorrectionHighMomenta - fSystematicScalingEtaCorrectionLowMomenta) > fgkEpsilon) {
2342 const Double_t fractionHighMomentumScaleFactor = 0.5 * (1. + TMath::Erf((pTPC - fSystematicScalingEtaCorrectionMomentumThr) / 0.1));
2343 usedSystematicScalingEtaCorrection = fSystematicScalingEtaCorrectionLowMomenta * (1 - fractionHighMomentumScaleFactor)
2344 + fSystematicScalingEtaCorrectionHighMomenta * fractionHighMomentumScaleFactor;
2347 Double_t maxEtaVariationEl = GetMaxEtaVariation(dEdxEl);
2348 etaCorrEl = etaCorrEl * (1.0 + (usedSystematicScalingEtaCorrection - 1.) * (etaCorrEl - 1.0) / maxEtaVariationEl);
2350 Double_t maxEtaVariationKa = GetMaxEtaVariation(dEdxKa);
2351 etaCorrKa = etaCorrKa * (1.0 + (usedSystematicScalingEtaCorrection - 1.) * (etaCorrKa - 1.0) / maxEtaVariationKa);
2353 Double_t maxEtaVariationPi = GetMaxEtaVariation(dEdxPi);
2354 etaCorrPi = etaCorrPi * (1.0 + (usedSystematicScalingEtaCorrection - 1.) * (etaCorrPi - 1.0) / maxEtaVariationPi);
2356 if (fTakeIntoAccountMuons) {
2357 Double_t maxEtaVariationMu = GetMaxEtaVariation(dEdxMu);
2358 etaCorrMu = etaCorrMu * (1.0 + (usedSystematicScalingEtaCorrection - 1.) * (etaCorrMu - 1.0) / maxEtaVariationMu);
2363 Double_t maxEtaVariationPr = GetMaxEtaVariation(dEdxPr);
2364 etaCorrPr = etaCorrPr * (1.0 + (usedSystematicScalingEtaCorrection - 1.) * (etaCorrPr - 1.0) / maxEtaVariationPr);
2368 etaCorrEl = 1.0 + usedSystematicScalingEtaCorrection * (etaCorrEl - 1.0);
2369 etaCorrKa = 1.0 + usedSystematicScalingEtaCorrection * (etaCorrKa - 1.0);
2370 etaCorrPi = 1.0 + usedSystematicScalingEtaCorrection * (etaCorrPi - 1.0);
2371 etaCorrMu = fTakeIntoAccountMuons ? (1.0 + usedSystematicScalingEtaCorrection * (etaCorrMu - 1.0)) : 1.0;
2372 etaCorrPr = 1.0 + usedSystematicScalingEtaCorrection * (etaCorrPr - 1.0);
2376 // Get the multiplicity correction factors for the (modified) expected dEdx
2377 const Int_t currEvtMultiplicity = fPIDResponse->GetTPCResponse().GetCurrentEventMultiplicity();
2379 Double_t multiplicityCorrEl = fPIDResponse->UseTPCMultiplicityCorrection() ? fPIDResponse->GetTPCResponse().GetMultiplicityCorrectionFast(track,
2380 dEdxEl * etaCorrEl, currEvtMultiplicity) : 1.;
2381 Double_t multiplicityCorrKa = fPIDResponse->UseTPCMultiplicityCorrection() ? fPIDResponse->GetTPCResponse().GetMultiplicityCorrectionFast(track,
2382 dEdxKa * etaCorrKa, currEvtMultiplicity) : 1.;
2383 Double_t multiplicityCorrPi = fPIDResponse->UseTPCMultiplicityCorrection() ? fPIDResponse->GetTPCResponse().GetMultiplicityCorrectionFast(track,
2384 dEdxPi * etaCorrPi, currEvtMultiplicity) : 1.;
2385 Double_t multiplicityCorrMu = fTakeIntoAccountMuons && fPIDResponse->UseTPCMultiplicityCorrection() ?
2386 fPIDResponse->GetTPCResponse().GetMultiplicityCorrectionFast(track, dEdxMu * etaCorrMu, currEvtMultiplicity) : 1.;
2387 Double_t multiplicityCorrPr = fPIDResponse->UseTPCMultiplicityCorrection() ? fPIDResponse->GetTPCResponse().GetMultiplicityCorrectionFast(track,
2388 dEdxPr * etaCorrPr, currEvtMultiplicity) : 1.;
2390 Double_t multiplicityCorrSigmaEl = fPIDResponse->UseTPCMultiplicityCorrection() ?
2391 fPIDResponse->GetTPCResponse().GetMultiplicitySigmaCorrectionFast(dEdxEl * etaCorrEl, currEvtMultiplicity) : 1.;
2392 Double_t multiplicityCorrSigmaKa = fPIDResponse->UseTPCMultiplicityCorrection() ?
2393 fPIDResponse->GetTPCResponse().GetMultiplicitySigmaCorrectionFast(dEdxKa * etaCorrKa, currEvtMultiplicity) : 1.;
2394 Double_t multiplicityCorrSigmaPi = fPIDResponse->UseTPCMultiplicityCorrection() ?
2395 fPIDResponse->GetTPCResponse().GetMultiplicitySigmaCorrectionFast(dEdxPi * etaCorrPi, currEvtMultiplicity) : 1.;
2396 Double_t multiplicityCorrSigmaMu = fTakeIntoAccountMuons && fPIDResponse->UseTPCMultiplicityCorrection() ?
2397 fPIDResponse->GetTPCResponse().GetMultiplicitySigmaCorrectionFast(dEdxMu * etaCorrMu, currEvtMultiplicity) : 1.;
2398 Double_t multiplicityCorrSigmaPr = fPIDResponse->UseTPCMultiplicityCorrection() ?
2399 fPIDResponse->GetTPCResponse().GetMultiplicitySigmaCorrectionFast(dEdxPr * etaCorrPr, currEvtMultiplicity) : 1.;
2401 // Scale multiplicity correction factors, if desired (and multiplicity correction functions are to be used, otherwise it is not possible!)
2402 if (fPIDResponse->UseTPCMultiplicityCorrection() && TMath::Abs(fSystematicScalingMultCorrection - 1.0) > fgkEpsilon) {
2403 // Since we do not want to scale the splines with this, but only the multiplicity variation, only scale the deviation of the correction factor!
2404 // E.g. if we would have a flat mult depence fix at 1.0, we would shift the whole thing equal to shifting the splines by the same factor!
2406 multiplicityCorrEl = 1.0 + fSystematicScalingMultCorrection * (multiplicityCorrEl - 1.0);
2407 multiplicityCorrKa = 1.0 + fSystematicScalingMultCorrection * (multiplicityCorrKa - 1.0);
2408 multiplicityCorrPi = 1.0 + fSystematicScalingMultCorrection * (multiplicityCorrPi - 1.0);
2409 multiplicityCorrMu = fTakeIntoAccountMuons ? (1.0 + fSystematicScalingMultCorrection * (multiplicityCorrMu - 1.0)) : 1.0;
2410 multiplicityCorrPr = 1.0 + fSystematicScalingMultCorrection * (multiplicityCorrPr - 1.0);
2413 // eta correction must be enabled in order to use the new sigma parametrisation maps. Since this is the absolute sigma
2414 // for a track calculated with the unscaled paramaters, we have to devide out dEdxExpectedEtaCorrected and then need
2415 // to scale with the multiplicitySigmaCorrFactor * fSystematicScalingEtaSigmaPara. In the end, one has to scale with the
2416 // (modified) dEdx to get the absolute sigma
2417 // This means there is no extra parameter for the multiplicitySigmaCorrFactor, but only for the sigma map itself.
2418 // This is valid, since it appears only as a product. One has to assume a larger systematic shift in case of additional
2419 // multiplicity dependence....
2421 Bool_t doSigmaSystematics = (TMath::Abs(fSystematicScalingEtaSigmaParaBelowThreshold - 1.0) > fgkEpsilon) ||
2422 (TMath::Abs(fSystematicScalingEtaSigmaParaAboveThreshold - 1.0) > fgkEpsilon);
2425 Double_t dEdxElExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault,
2427 Double_t systematicScalingEtaSigmaParaEl = 1.;
2428 if (doSigmaSystematics) {
2429 Double_t scaleFactor = 0.5 * (1. + TMath::Erf((dEdxElExpected - fSystematicScalingEtaSigmaParaThreshold) / 25.));
2430 systematicScalingEtaSigmaParaEl = fSystematicScalingEtaSigmaParaBelowThreshold * (1 - scaleFactor)
2431 + fSystematicScalingEtaSigmaParaAboveThreshold * scaleFactor;
2433 Double_t sigmaRelEl = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault,
2435 / dEdxElExpected * systematicScalingEtaSigmaParaEl * multiplicityCorrSigmaEl;
2438 Double_t dEdxKaExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kKaon, AliTPCPIDResponse::kdEdxDefault,
2440 Double_t systematicScalingEtaSigmaParaKa = 1.;
2441 if (doSigmaSystematics) {
2442 Double_t scaleFactor = 0.5 * (1. + TMath::Erf((dEdxKaExpected - fSystematicScalingEtaSigmaParaThreshold) / 25.));
2443 systematicScalingEtaSigmaParaKa = fSystematicScalingEtaSigmaParaBelowThreshold * (1 - scaleFactor)
2444 + fSystematicScalingEtaSigmaParaAboveThreshold * scaleFactor;
2446 Double_t sigmaRelKa = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kKaon, AliTPCPIDResponse::kdEdxDefault,
2448 / dEdxKaExpected * systematicScalingEtaSigmaParaKa * multiplicityCorrSigmaKa;
2451 Double_t dEdxPiExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault,
2453 Double_t systematicScalingEtaSigmaParaPi = 1.;
2454 if (doSigmaSystematics) {
2455 Double_t scaleFactor = 0.5 * (1. + TMath::Erf((dEdxPiExpected - fSystematicScalingEtaSigmaParaThreshold) / 25.));
2456 systematicScalingEtaSigmaParaPi = fSystematicScalingEtaSigmaParaBelowThreshold * (1 - scaleFactor)
2457 + fSystematicScalingEtaSigmaParaAboveThreshold * scaleFactor;
2459 Double_t sigmaRelPi = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault,
2461 / dEdxPiExpected * systematicScalingEtaSigmaParaPi * multiplicityCorrSigmaPi;
2464 Double_t sigmaRelMu = 999.;
2465 if (fTakeIntoAccountMuons) {
2466 Double_t dEdxMuExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kMuon, AliTPCPIDResponse::kdEdxDefault,
2468 Double_t systematicScalingEtaSigmaParaMu = 1.;
2469 if (doSigmaSystematics) {
2470 Double_t scaleFactor = 0.5 * (1. + TMath::Erf((dEdxMuExpected - fSystematicScalingEtaSigmaParaThreshold) / 25.));
2471 systematicScalingEtaSigmaParaMu = fSystematicScalingEtaSigmaParaBelowThreshold * (1 - scaleFactor)
2472 + fSystematicScalingEtaSigmaParaAboveThreshold * scaleFactor;
2474 sigmaRelMu = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kMuon, AliTPCPIDResponse::kdEdxDefault, kTRUE, kFALSE)
2475 / dEdxMuExpected * systematicScalingEtaSigmaParaMu * multiplicityCorrSigmaMu;
2479 Double_t dEdxPrExpected = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault,
2481 Double_t systematicScalingEtaSigmaParaPr = 1.;
2482 if (doSigmaSystematics) {
2483 Double_t scaleFactor = 0.5 * (1. + TMath::Erf((dEdxPrExpected - fSystematicScalingEtaSigmaParaThreshold) / 25.));
2484 systematicScalingEtaSigmaParaPr = fSystematicScalingEtaSigmaParaBelowThreshold * (1 - scaleFactor)
2485 + fSystematicScalingEtaSigmaParaAboveThreshold * scaleFactor;
2487 Double_t sigmaRelPr = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault,
2489 / dEdxPrExpected * systematicScalingEtaSigmaParaPr * multiplicityCorrSigmaPr;
2491 // Now scale the (possibly modified) spline values with the (possibly modified) correction factors
2492 dEdxEl *= etaCorrEl * multiplicityCorrEl;
2493 dEdxKa *= etaCorrKa * multiplicityCorrKa;
2494 dEdxPi *= etaCorrPi * multiplicityCorrPi;
2495 dEdxMu *= etaCorrMu * multiplicityCorrMu;
2496 dEdxPr *= etaCorrPr * multiplicityCorrPr;
2498 // Finally, get the absolute sigma
2499 sigmaEl = sigmaRelEl * dEdxEl;
2500 sigmaKa = sigmaRelKa * dEdxKa;
2501 sigmaPi = sigmaRelPi * dEdxPi;
2502 sigmaMu = sigmaRelMu * dEdxMu;
2503 sigmaPr = sigmaRelPr * dEdxPr;
2507 // No systematic studies on expected signal - just take it as it comve from the TPCPIDResponse
2508 dEdxEl = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault,
2509 fPIDResponse->UseTPCEtaCorrection(),
2510 fPIDResponse->UseTPCMultiplicityCorrection());
2511 dEdxKa = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kKaon, AliTPCPIDResponse::kdEdxDefault,
2512 fPIDResponse->UseTPCEtaCorrection(),
2513 fPIDResponse->UseTPCMultiplicityCorrection());
2514 dEdxPi = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault,
2515 fPIDResponse->UseTPCEtaCorrection(),
2516 fPIDResponse->UseTPCMultiplicityCorrection());
2517 dEdxMu = !fTakeIntoAccountMuons ? -1 :
2518 fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kMuon, AliTPCPIDResponse::kdEdxDefault,
2519 fPIDResponse->UseTPCEtaCorrection(),
2520 fPIDResponse->UseTPCMultiplicityCorrection());
2521 dEdxPr = fPIDResponse->GetTPCResponse().GetExpectedSignal(track, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault,
2522 fPIDResponse->UseTPCEtaCorrection(),
2523 fPIDResponse->UseTPCMultiplicityCorrection());
2525 sigmaEl = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault,
2526 fPIDResponse->UseTPCEtaCorrection(),
2527 fPIDResponse->UseTPCMultiplicityCorrection());
2528 sigmaKa = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kKaon, AliTPCPIDResponse::kdEdxDefault,
2529 fPIDResponse->UseTPCEtaCorrection(),
2530 fPIDResponse->UseTPCMultiplicityCorrection());
2531 sigmaPi = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault,
2532 fPIDResponse->UseTPCEtaCorrection(),
2533 fPIDResponse->UseTPCMultiplicityCorrection());
2534 sigmaMu = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kMuon, AliTPCPIDResponse::kdEdxDefault,
2535 fPIDResponse->UseTPCEtaCorrection(),
2536 fPIDResponse->UseTPCMultiplicityCorrection());
2537 sigmaPr = fPIDResponse->GetTPCResponse().GetExpectedSigma(track, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault,
2538 fPIDResponse->UseTPCEtaCorrection(),
2539 fPIDResponse->UseTPCMultiplicityCorrection());
2542 Double_t deltaPrimeElectron = (dEdxEl > 0) ? dEdxTPC / dEdxEl : -1;
2544 Printf("Error: Expected TPC signal <= 0 for electron hypothesis");
2548 Double_t deltaPrimeKaon = (dEdxKa > 0) ? dEdxTPC / dEdxKa : -1;
2550 Printf("Error: Expected TPC signal <= 0 for kaon hypothesis");
2554 Double_t deltaPrimePion = (dEdxPi > 0) ? dEdxTPC / dEdxPi : -1;
2556 Printf("Error: Expected TPC signal <= 0 for pion hypothesis");
2560 Double_t deltaPrimeProton = (dEdxPr > 0) ? dEdxTPC / dEdxPr : -1;
2562 Printf("Error: Expected TPC signal <= 0 for proton hypothesis");
2567 printf("File: %s, Line: %d: ProcessTrack -> Compute probabilities\n", (char*)__FILE__, __LINE__);
2570 // Use probabilities to weigh the response generation for the different species.
2571 // Also determine the most probable particle type.
2572 Double_t prob[AliPID::kSPECIESC];
2573 for (Int_t i = 0; i < AliPID::kSPECIESC; i++)
2576 fPIDcombined->ComputeProbabilities(track, fPIDResponse, prob);
2578 // If muons are not to be taken into account, just set their probability to zero and normalise the remaining probabilities later
2579 if (!fTakeIntoAccountMuons)
2580 prob[AliPID::kMuon] = 0;
2582 // Priors might cause problems in case of mismatches, i.e. mismatch particles will be identified as pions.
2583 // Can be easily caught for low p_TPC by just setting pion (and muon) probs to zero, if dEdx is larger than
2584 // expected dEdx of electrons and kaons
2585 if (pTPC < 1. && dEdxTPC > dEdxEl && dEdxTPC > dEdxKa) {
2586 prob[AliPID::kMuon] = 0;
2587 prob[AliPID::kPion] = 0;
2591 // Bug: One can set the number of species for PIDcombined, but PIDcombined will call PIDresponse, which writes without testing
2592 // the probs for kSPECIESC (including light nuclei) into the array.
2593 // In this case, when only kSPECIES are considered, the probabilities have to be rescaled!
2596 // 1. If the most probable PID is a light nucleus and above expected dEdx + 5 sigma of el to be sure not to mix up things in the
2597 // high-pT region (also contribution there completely negligable!)
2598 // 2. If dEdx is larger than the expected dEdx + 5 sigma of el and pr, it is most likely a light nucleus
2599 // (if dEdx is more than 5 sigma away from expectation, flat TPC probs are set... and the light nuclei splines are not
2602 // The highest expected dEdx is either for pr or for el. Assign 100% probability to the species with highest expected dEdx then.
2603 // In all other cases: Throw away light nuclei probs and rescale other probs to 100%.
2605 // Find most probable species for the ID
2606 Int_t maxIndex = TMath::LocMax(AliPID::kSPECIESC, prob);
2608 if ((prob[maxIndex] > 0 && maxIndex >= AliPID::kSPECIES && dEdxTPC > dEdxEl + 5. * sigmaEl) ||
2609 (dEdxTPC > dEdxEl + 5. * sigmaEl && dEdxTPC > dEdxPr + 5. * sigmaPr)) {
2610 for (Int_t i = 0; i < AliPID::kSPECIESC; i++)
2613 if (dEdxEl > dEdxPr) {
2614 prob[AliPID::kElectron] = 1.;
2615 maxIndex = AliPID::kElectron;
2618 prob[AliPID::kProton] = 1.;
2619 maxIndex = AliPID::kProton;
2623 for (Int_t i = AliPID::kSPECIES; i < AliPID::kSPECIESC; i++)
2626 Double_t probSum = 0.;
2627 for (Int_t i = 0; i < AliPID::kSPECIES; i++)
2631 for (Int_t i = 0; i < AliPID::kSPECIES; i++)
2635 // If all probabilities are equal (should only happen if no priors are used), set most probable PID to pion
2636 // because LocMax returns just the first maximal value (i.e. AliPID::kElectron)
2637 if (TMath::Abs(prob[maxIndex] - 1. / AliPID::kSPECIES) < 1e-5)
2638 maxIndex = AliPID::kPion;
2640 // In all other cases, the maximum remains untouched from the scaling (and is < AliPID::kSPECIES by construction)
2644 // Clean up the most probable PID for low momenta (not an issue for the probabilities, since fractions small,
2645 // but to get clean (and nice looking) templates (if most probable PID is used instead of generated responses), it should be done).
2646 // Problem: If more than 5 sigma away (and since priors also included), most probable PID for dEdx around protons could be pions.
2647 // Idea: Only clean selection for K and p possible. So, just take for the most probable PID the probs from TPC only calculated
2648 // by hand without restriction to 5 sigma and without priors. This will not affect the template generation, but afterwards one
2649 // can replace the K and p templates with the most probable PID distributions, so all other species templates remain the same.
2650 // I.e. it doesn't hurt if the most probable PID is distributed incorrectly between el, pi, mu.
2651 Bool_t maxIndexSetManually = kFALSE;
2654 Double_t probManualTPC[AliPID::kSPECIES];
2655 for (Int_t i = 0; i < AliPID::kSPECIES; i++)
2656 probManualTPC[i] = 0;
2658 probManualTPC[AliPID::kElectron] = TMath::Exp(-0.5*(dEdxTPC-dEdxEl)*(dEdxTPC-dEdxEl)/(sigmaEl*sigmaEl))/sigmaEl;
2659 // Muons are not important here, just ignore and save processing time
2660 probManualTPC[AliPID::kMuon] = 0.;//TMath::Exp(-0.5*(dEdxTPC-dEdxMu)*(dEdxTPC-dEdxMu)/(sigmaMu*sigmaMu))/sigmaMu;
2661 probManualTPC[AliPID::kPion] = TMath::Exp(-0.5*(dEdxTPC-dEdxPi)*(dEdxTPC-dEdxPi)/(sigmaPi*sigmaPi))/sigmaPi;
2662 probManualTPC[AliPID::kKaon] = TMath::Exp(-0.5*(dEdxTPC-dEdxKa)*(dEdxTPC-dEdxKa)/(sigmaKa*sigmaKa))/sigmaKa;
2663 probManualTPC[AliPID::kProton] = TMath::Exp(-0.5*(dEdxTPC-dEdxPr)*(dEdxTPC-dEdxPr)/(sigmaPr*sigmaPr))/sigmaPr;
2665 const Int_t maxIndexManualTPC = TMath::LocMax(AliPID::kSPECIES, probManualTPC);
2666 // Should always be > 0, but in case the dEdx is far off such that the machine accuracy sets every prob to zero,
2667 // better take the "old" result
2668 if (probManualTPC[maxIndexManualTPC] > 0.)
2669 maxIndex = maxIndexManualTPC;
2671 maxIndexSetManually = kTRUE;
2675 // Translate from AliPID numbering to numbering of this class
2676 if (prob[maxIndex] > 0 || maxIndexSetManually) {
2677 if (maxIndex == AliPID::kElectron)
2679 else if (maxIndex == AliPID::kKaon)
2681 else if (maxIndex == AliPID::kMuon)
2683 else if (maxIndex == AliPID::kPion)
2685 else if (maxIndex == AliPID::kProton)
2691 // Only take track into account for expectation values, if valid pid response is available.. Otherwise: Set to underflow bin.
2697 //For testing: Swap p<->pT to analyse pure p-dependence => Needs to be removed later
2703 TOFpidInfo tofPIDinfo = GetTOFType(track, fTOFmode);
2705 Double_t entry[fStoreAdditionalJetInformation ? kDataNumAxes : kDataNumAxes - fgkNumJetAxes];
2706 entry[kDataMCID] = binMC;
2707 entry[kDataSelectSpecies] = 0;
2708 entry[kDataPt] = pT;
2709 entry[kDataDeltaPrimeSpecies] = deltaPrimeElectron;
2710 entry[kDataCentrality] = centralityPercentile;
2712 if (fStoreAdditionalJetInformation) {
2713 entry[kDataJetPt] = jetPt;
2715 entry[kDataXi] = xi;
2718 entry[GetIndexOfChargeAxisData()] = trackCharge;
2719 entry[GetIndexOfTOFpidInfoAxisData()] = tofPIDinfo;
2721 fhPIDdataAll->Fill(entry);
2723 entry[kDataSelectSpecies] = 1;
2724 entry[kDataDeltaPrimeSpecies] = deltaPrimeKaon;
2725 fhPIDdataAll->Fill(entry);
2727 entry[kDataSelectSpecies] = 2;
2728 entry[kDataDeltaPrimeSpecies] = deltaPrimePion;
2729 fhPIDdataAll->Fill(entry);
2731 entry[kDataSelectSpecies] = 3;
2732 entry[kDataDeltaPrimeSpecies] = deltaPrimeProton;
2733 fhPIDdataAll->Fill(entry);
2736 // Construct the expected shape for the transition p -> pT
2738 Double_t genEntry[fStoreAdditionalJetInformation ? kGenNumAxes : kGenNumAxes - fgkNumJetAxes];
2739 genEntry[kGenMCID] = binMC;
2740 genEntry[kGenSelectSpecies] = 0;
2741 genEntry[kGenPt] = pT;
2742 genEntry[kGenDeltaPrimeSpecies] = -999;
2743 genEntry[kGenCentrality] = centralityPercentile;
2745 if (fStoreAdditionalJetInformation) {
2746 genEntry[kGenJetPt] = jetPt;
2747 genEntry[kGenZ] = z;
2748 genEntry[kGenXi] = xi;
2751 genEntry[GetIndexOfChargeAxisGen()] = trackCharge;
2752 genEntry[GetIndexOfTOFpidInfoAxisGen()] = tofPIDinfo;
2754 // Generate numGenEntries "responses" with fluctuations around the expected values.
2755 // fgkMaxNumGenEntries = 500 turned out to give reasonable templates even for highest track pT in 15-20 GeV/c jet pT bin.
2756 Int_t numGenEntries = fgkMaxNumGenEntries; // fgkMaxNumGenEntries = 500
2758 /*OLD: Different number of responses depending on pT and jet pT for fgkMaxNumGenEntries = 1000
2759 * => Problem: If threshold to higher number of responses inside a bin (or after rebinning), then the template
2760 * is biased to the higher pT.
2761 // Generate numGenEntries "responses" with fluctuations around the expected values.
2762 // The higher the (transverse) momentum, the more "responses" will be generated in order not to run out of statistics too fast.
2763 Int_t numGenEntries = 10;
2765 // Jets have even worse statistics, therefore, scale numGenEntries further
2767 numGenEntries *= 20;
2768 else if (jetPt >= 20)
2769 numGenEntries *= 10;
2770 else if (jetPt >= 10)
2775 // Do not generate more entries than available in memory!
2776 if (numGenEntries > fgkMaxNumGenEntries)// fgkMaxNumGenEntries = 1000
2777 numGenEntries = fgkMaxNumGenEntries;
2781 ErrorCode errCode = kNoErrors;
2784 printf("File: %s, Line: %d: ProcessTrack -> Generate Responses\n", (char*)__FILE__, __LINE__);
2787 errCode = GenerateDetectorResponse(errCode, 1., sigmaEl / dEdxEl, fGenRespElDeltaPrimeEl, numGenEntries);
2788 errCode = GenerateDetectorResponse(errCode, dEdxEl / dEdxKa, sigmaEl / dEdxKa, fGenRespElDeltaPrimeKa, numGenEntries);
2789 errCode = GenerateDetectorResponse(errCode, dEdxEl / dEdxPi, sigmaEl / dEdxPi, fGenRespElDeltaPrimePi, numGenEntries);
2790 errCode = GenerateDetectorResponse(errCode, dEdxEl / dEdxPr, sigmaEl / dEdxPr, fGenRespElDeltaPrimePr, numGenEntries);
2793 errCode = GenerateDetectorResponse(errCode, dEdxKa / dEdxEl, sigmaKa / dEdxEl, fGenRespKaDeltaPrimeEl, numGenEntries);
2794 errCode = GenerateDetectorResponse(errCode, 1., sigmaKa / dEdxKa, fGenRespKaDeltaPrimeKa, numGenEntries);
2795 errCode = GenerateDetectorResponse(errCode, dEdxKa / dEdxPi, sigmaKa / dEdxPi, fGenRespKaDeltaPrimePi, numGenEntries);
2796 errCode = GenerateDetectorResponse(errCode, dEdxKa / dEdxPr, sigmaKa / dEdxPr, fGenRespKaDeltaPrimePr, numGenEntries);
2799 errCode = GenerateDetectorResponse(errCode, dEdxPi / dEdxEl, sigmaPi / dEdxEl, fGenRespPiDeltaPrimeEl, numGenEntries);
2800 errCode = GenerateDetectorResponse(errCode, dEdxPi / dEdxKa, sigmaPi / dEdxKa, fGenRespPiDeltaPrimeKa, numGenEntries);
2801 errCode = GenerateDetectorResponse(errCode, 1., sigmaPi / dEdxPi, fGenRespPiDeltaPrimePi, numGenEntries);
2802 errCode = GenerateDetectorResponse(errCode, dEdxPi / dEdxPr, sigmaPi / dEdxPr, fGenRespPiDeltaPrimePr, numGenEntries);
2804 // Muons, if desired
2805 if (fTakeIntoAccountMuons) {
2806 errCode = GenerateDetectorResponse(errCode, dEdxMu / dEdxEl, sigmaMu / dEdxEl, fGenRespMuDeltaPrimeEl, numGenEntries);
2807 errCode = GenerateDetectorResponse(errCode, dEdxMu / dEdxKa, sigmaMu / dEdxKa, fGenRespMuDeltaPrimeKa, numGenEntries);
2808 errCode = GenerateDetectorResponse(errCode, dEdxMu / dEdxPi, sigmaMu / dEdxPi, fGenRespMuDeltaPrimePi, numGenEntries);
2809 errCode = GenerateDetectorResponse(errCode, dEdxMu / dEdxPr, sigmaMu / dEdxPr, fGenRespMuDeltaPrimePr, numGenEntries);
2813 errCode = GenerateDetectorResponse(errCode, dEdxPr / dEdxEl, sigmaPr / dEdxEl, fGenRespPrDeltaPrimeEl, numGenEntries);
2814 errCode = GenerateDetectorResponse(errCode, dEdxPr / dEdxKa, sigmaPr / dEdxKa, fGenRespPrDeltaPrimeKa, numGenEntries);
2815 errCode = GenerateDetectorResponse(errCode, dEdxPr / dEdxPi, sigmaPr / dEdxPi, fGenRespPrDeltaPrimePi, numGenEntries);
2816 errCode = GenerateDetectorResponse(errCode, 1., sigmaPr / dEdxPr, fGenRespPrDeltaPrimePr, numGenEntries);
2818 if (errCode != kNoErrors) {
2819 if (errCode == kWarning && fDebug > 1) {
2820 Printf("Warning: Questionable detector response for track, most likely due to very low number of PID clusters! Debug output (dEdx_expected, sigma_expected):");
2823 Printf("Error: Failed to generate detector response for track - skipped! Debug output (dEdx_expected, sigma_expected):");
2826 Printf("Pr: %e, %e", dEdxPr, sigmaPr);
2827 Printf("Pi: %e, %e", dEdxPi, sigmaPi);
2828 Printf("El: %e, %e", dEdxEl, sigmaEl);
2829 Printf("Mu: %e, %e", dEdxMu, sigmaMu);
2830 Printf("Ka: %e, %e", dEdxKa, sigmaKa);
2831 Printf("track: dEdx %f, pTPC %f, eta %f, ncl %d\n", track->GetTPCsignal(), track->GetTPCmomentum(), track->Eta(),
2832 track->GetTPCsignalN());
2835 if (errCode != kWarning) {
2836 fhSkippedTracksForSignalGeneration->Fill(track->GetTPCmomentum(), track->GetTPCsignalN());
2837 return kFALSE;// Skip generated response in case of error
2841 for (Int_t n = 0; n < numGenEntries; n++) {
2842 if (!isMC || !fUseMCidForGeneration) {
2843 // If no MC info is available or shall not be used, use weighting with priors to generate entries for the different species
2844 Double_t rnd = fRandom->Rndm(); // Produce uniformly distributed floating point in ]0, 1]
2846 // Consider generated response as originating from...
2847 if (rnd <= prob[AliPID::kElectron])
2848 genEntry[kGenMCID] = 0; // ... an electron
2849 else if (rnd <= prob[AliPID::kElectron] + prob[AliPID::kKaon])
2850 genEntry[kGenMCID] = 1; // ... a kaon
2851 else if (rnd <= prob[AliPID::kElectron] + prob[AliPID::kKaon] + prob[AliPID::kMuon])
2852 genEntry[kGenMCID] = 2; // ... a muon -> NOTE: prob[AliPID::kMuon] = 0 in case of fTakeIntoAccountMuons = kFALSE
2853 else if (rnd <= prob[AliPID::kElectron] + prob[AliPID::kKaon] + prob[AliPID::kMuon] + prob[AliPID::kPion])
2854 genEntry[kGenMCID] = 3; // ... a pion
2856 genEntry[kGenMCID] = 4; // ... a proton
2860 genEntry[kGenSelectSpecies] = 0;
2861 genEntry[kGenDeltaPrimeSpecies] = fGenRespElDeltaPrimeEl[n];
2862 fhGenEl->Fill(genEntry);
2864 genEntry[kGenSelectSpecies] = 1;
2865 genEntry[kGenDeltaPrimeSpecies] = fGenRespElDeltaPrimeKa[n];
2866 fhGenEl->Fill(genEntry);
2868 genEntry[kGenSelectSpecies] = 2;
2869 genEntry[kGenDeltaPrimeSpecies] = fGenRespElDeltaPrimePi[n];
2870 fhGenEl->Fill(genEntry);
2872 genEntry[kGenSelectSpecies] = 3;
2873 genEntry[kGenDeltaPrimeSpecies] = fGenRespElDeltaPrimePr[n];
2874 fhGenEl->Fill(genEntry);
2877 genEntry[kGenSelectSpecies] = 0;
2878 genEntry[kGenDeltaPrimeSpecies] = fGenRespKaDeltaPrimeEl[n];
2879 fhGenKa->Fill(genEntry);
2881 genEntry[kGenSelectSpecies] = 1;
2882 genEntry[kGenDeltaPrimeSpecies] = fGenRespKaDeltaPrimeKa[n];
2883 fhGenKa->Fill(genEntry);
2885 genEntry[kGenSelectSpecies] = 2;
2886 genEntry[kGenDeltaPrimeSpecies] = fGenRespKaDeltaPrimePi[n];
2887 fhGenKa->Fill(genEntry);
2889 genEntry[kGenSelectSpecies] = 3;
2890 genEntry[kGenDeltaPrimeSpecies] = fGenRespKaDeltaPrimePr[n];
2891 fhGenKa->Fill(genEntry);
2894 genEntry[kGenSelectSpecies] = 0;
2895 genEntry[kGenDeltaPrimeSpecies] = fGenRespPiDeltaPrimeEl[n];
2896 fhGenPi->Fill(genEntry);
2898 genEntry[kGenSelectSpecies] = 1;
2899 genEntry[kGenDeltaPrimeSpecies] = fGenRespPiDeltaPrimeKa[n];
2900 fhGenPi->Fill(genEntry);
2902 genEntry[kGenSelectSpecies] = 2;
2903 genEntry[kGenDeltaPrimeSpecies] = fGenRespPiDeltaPrimePi[n];
2904 fhGenPi->Fill(genEntry);
2906 genEntry[kGenSelectSpecies] = 3;
2907 genEntry[kGenDeltaPrimeSpecies] = fGenRespPiDeltaPrimePr[n];
2908 fhGenPi->Fill(genEntry);
2910 if (fTakeIntoAccountMuons) {
2911 // Muons, if desired
2912 genEntry[kGenSelectSpecies] = 0;
2913 genEntry[kGenDeltaPrimeSpecies] = fGenRespMuDeltaPrimeEl[n];
2914 fhGenMu->Fill(genEntry);
2916 genEntry[kGenSelectSpecies] = 1;
2917 genEntry[kGenDeltaPrimeSpecies] = fGenRespMuDeltaPrimeKa[n];
2918 fhGenMu->Fill(genEntry);
2920 genEntry[kGenSelectSpecies] = 2;
2921 genEntry[kGenDeltaPrimeSpecies] = fGenRespMuDeltaPrimePi[n];
2922 fhGenMu->Fill(genEntry);
2924 genEntry[kGenSelectSpecies] = 3;
2925 genEntry[kGenDeltaPrimeSpecies] = fGenRespMuDeltaPrimePr[n];
2926 fhGenMu->Fill(genEntry);
2930 genEntry[kGenSelectSpecies] = 0;
2931 genEntry[kGenDeltaPrimeSpecies] = fGenRespPrDeltaPrimeEl[n];
2932 fhGenPr->Fill(genEntry);
2934 genEntry[kGenSelectSpecies] = 1;
2935 genEntry[kGenDeltaPrimeSpecies] = fGenRespPrDeltaPrimeKa[n];
2936 fhGenPr->Fill(genEntry);
2938 genEntry[kGenSelectSpecies] = 2;
2939 genEntry[kGenDeltaPrimeSpecies] = fGenRespPrDeltaPrimePi[n];
2940 fhGenPr->Fill(genEntry);
2942 genEntry[kGenSelectSpecies] = 3;
2943 genEntry[kGenDeltaPrimeSpecies] = fGenRespPrDeltaPrimePr[n];
2944 fhGenPr->Fill(genEntry);
2948 printf("File: %s, Line: %d: ProcessTrack -> Done\n", (char*)__FILE__, __LINE__);
2954 //_____________________________________________________________________________
2955 Bool_t AliAnalysisTaskPID::SetConvolutedGaussLambdaParameter(Double_t lambda)
2957 // Set the lambda parameter of the convolution to the desired value. Automatically
2958 // calculates the parameters for the transition (restricted) gauss -> convoluted gauss.
2959 fConvolutedGaussTransitionPars[2] = lambda;
2961 // Save old parameters and settings of function to restore them later:
2962 Double_t* oldFuncParams = new Double_t[fkConvolutedGausNPar];
2963 for (Int_t i = 0; i < fkConvolutedGausNPar; i++)
2964 oldFuncParams[i] = fConvolutedGausDeltaPrime->GetParameter(i);
2965 Int_t oldFuncNpx = fConvolutedGausDeltaPrime->GetNpx();
2966 Double_t oldFuncRangeLow = 0, oldFuncRangeUp = 100;
2967 fConvolutedGausDeltaPrime->GetRange(oldFuncRangeLow, oldFuncRangeUp);
2969 // Choose some sufficiently large range
2970 const Double_t rangeStart = 0.5;
2971 const Double_t rangeEnd = 2.0;
2973 // To get the parameters for the transition, just choose arbitrarily input parameters for mu and sigma
2974 // (it makes sense to choose typical values). The ratio sigma_gauss / sigma_convolution is independent
2975 // of mu and as well the difference mu_gauss - mu_convolution.
2976 Double_t muInput = 1.0;
2977 Double_t sigmaInput = fgkSigmaReferenceForTransitionPars;
2980 // Step 1: Generate distribution with input parameters
2981 const Int_t nPar = 3;
2982 Double_t inputPar[nPar] = { muInput, sigmaInput, lambda };
2984 TH1D* hInput = new TH1D("hInput", "Input distribution", 2000, rangeStart, rangeEnd);
2986 fConvolutedGausDeltaPrime->SetParameters(inputPar);
2987 fConvolutedGausDeltaPrime->SetRange(rangeStart, rangeEnd);
2988 fConvolutedGausDeltaPrime->SetNpx(2000);
2991 // The resolution and mean of the AliPIDResponse are determined in finite intervals
2992 // of ncl (also second order effects due to finite dEdx and tanTheta).
2993 // Take this into account for the transition parameters via assuming an approximately flat
2994 // distritubtion in ncl in this interval.
2995 // NOTE: The ncl interval should be the same as the one used for the sigma map creation!
2996 const Int_t nclStart = 151;
2997 const Int_t nclEnd = 160;
2998 const Int_t nclSteps = (nclEnd - nclStart) + 1;
2999 for (Int_t ncl = nclStart; ncl <= nclEnd; ncl++) {
3000 // Resolution scales with 1/sqrt(ncl)
3001 fConvolutedGausDeltaPrime->SetParameter(1, inputPar[1] * sqrt(nclEnd) / sqrt(ncl));
3002 TH1* hProbDensity = fConvolutedGausDeltaPrime->GetHistogram();
3004 for (Int_t i = 0; i < 50000000 / nclSteps; i++)
3005 hInput->Fill(hProbDensity->GetRandom());
3009 TH1* hProbDensity = fConvolutedGausDeltaPrime->GetHistogram();
3011 for (Int_t i = 0; i < 50000000; i++)
3012 hInput->Fill(hProbDensity->GetRandom());
3014 // Step 2: Fit generated distribution with restricted gaussian
3015 Int_t maxBin = hInput->GetMaximumBin();
3016 Double_t max = hInput->GetBinContent(maxBin);
3018 UChar_t usedBins = 1;
3020 max += hInput->GetBinContent(maxBin - 1);
3023 if (maxBin < hInput->GetNbinsX()) {
3024 max += hInput->GetBinContent(maxBin + 1);
3029 // NOTE: The range (<-> fraction of maximum) should be the same
3030 // as for the spline and eta maps creation
3031 const Double_t lowThreshold = hInput->GetXaxis()->GetBinLowEdge(hInput->FindFirstBinAbove(0.1 * max));
3032 const Double_t highThreshold = hInput->GetXaxis()->GetBinUpEdge(hInput->FindLastBinAbove(0.1 * max));
3034 TFitResultPtr fitResGaussFirstStep = hInput->Fit("gaus", "QNRS", "", lowThreshold, highThreshold);
3036 TFitResultPtr fitResGauss;
3038 if ((Int_t)fitResGaussFirstStep == 0) {
3039 TF1 fGauss("fGauss", "[0]*TMath::Gaus(x, [1], [2], 1)", rangeStart, rangeEnd);
3040 fGauss.SetParameter(0, fitResGaussFirstStep->GetParams()[0]);
3041 fGauss.SetParError(0, fitResGaussFirstStep->GetErrors()[0]);
3042 fGauss.SetParameter(2, fitResGaussFirstStep->GetParams()[2]);
3043 fGauss.SetParError(2, fitResGaussFirstStep->GetErrors()[2]);
3045 fGauss.FixParameter(1, fitResGaussFirstStep->GetParams()[1]);
3046 fitResGauss = hInput->Fit(&fGauss, "QNS", "s", rangeStart, rangeEnd);
3049 fitResGauss = hInput->Fit("gaus", "QNRS", "same", rangeStart, rangeEnd);
3051 //OLD TFitResultPtr fitResGauss = hInput->Fit("gaus", "QNRS", "", hInput->GetXaxis()->GetBinLowEdge(hInput->FindFirstBinAbove(0.1 * max)),
3052 // hInput->GetXaxis()->GetBinUpEdge(hInput->FindLastBinAbove(0.1 * max)));
3055 // Step 3: Use parameters from gaussian fit to obtain parameters for the transition "restricted gauss" -> "convoluted gauss"
3057 // 3.1 The ratio sigmaInput / sigma_gaussFit ONLY depends on lambda (which is fixed per period) -> Calculate this first
3058 // for an arbitrary (here: typical) sigma. The ratio is then ~the same for ALL sigma for given lambda!
3059 if ((Int_t)fitResGauss != 0) {
3060 AliError("Not able to calculate parameters for the transition \"restricted gauss\" -> \"convoluted gauss\": Gauss Fit failed!\n");
3061 fConvolutedGausDeltaPrime->SetParameters(oldFuncParams);
3062 fConvolutedGausDeltaPrime->SetNpx(oldFuncNpx);
3063 fConvolutedGausDeltaPrime->SetRange(oldFuncRangeLow, oldFuncRangeUp);
3066 delete [] oldFuncParams;
3071 if (fitResGauss->GetParams()[2] <= 0) {
3072 AliError("Not able to calculate parameters for the transition \"restricted gauss\" -> \"convoluted gauss\": Sigma of gauss fit <= 0!\n");
3073 fConvolutedGausDeltaPrime->SetParameters(oldFuncParams);
3074 fConvolutedGausDeltaPrime->SetNpx(oldFuncNpx);
3075 fConvolutedGausDeltaPrime->SetRange(oldFuncRangeLow, oldFuncRangeUp);
3078 delete [] oldFuncParams;
3083 // sigma correction factor
3084 fConvolutedGaussTransitionPars[1] = sigmaInput / fitResGauss->GetParams()[2];
3086 // 3.2 Now that sigma und lambda are determined, one can calculate mu by shifting the maximum to the desired position,
3087 // i.e. the maximum of the input distribution should coincide with that of the re-calculated distribution,
3088 // which is achieved by getting the same mu for the same sigma.
3089 // NOTE: For fixed lambda, the shift is proportional to sigma and independent of mu!
3090 // So, one can calculate the shift for an arbitrary fixed (here: typical)
3091 // sigma and then simply use this shift for any other sigma by scaling it correspondingly!!!
3093 // Mu shift correction:
3094 // Shift in mu (difference between mean of gauss and mean of convolution) is proportional to sigma!
3095 // Thus, choose a reference sigma (typical -> 0.05), such that for arbitrary sigma one can simple scale
3096 // this shift correction with sigma / referenceSigma.
3097 fConvolutedGaussTransitionPars[0] = (fitResGauss->GetParams()[1] - muInput);
3100 /*Changed on 03.07.2013
3102 // Maximum of fConvolutedGausDeltaPrime should agree with maximum of input
3103 Double_t par[nPar] = { fitResGauss->GetParams()[1], // just as a guess of the maximum position
3107 fConvolutedGausDeltaPrime->SetParameters(par);
3109 Double_t maxXInput = fConvolutedGausDeltaPrime->GetMaximumX(TMath::Max(0.001, muInput - 3. * sigmaInput),
3110 muInput + 10. * sigmaInput,
3113 // Maximum shifts proportional to sigma and is linear in mu (~mean of gauss)
3114 // Maximum should be typically located within [gaussMean, gaussMean + 3 gaussSigma].
3115 // -> Larger search range for safety reasons (also: sigma and/or mean might be not 100% accurate).
3116 Double_t maxXconvoluted = fConvolutedGausDeltaPrime->GetMaximumX(TMath::Max(0.001,
3117 fitResGauss->GetParams()[1] - 3. * fitResGauss->GetParams()[2]),
3118 fitResGauss->GetParams()[1] + 10. * fitResGauss->GetParams()[2],
3120 if (maxXconvoluted <= 0) {
3121 AliError("Not able to calculate parameters for the transition \"restricted gauss\" -> \"convoluted gauss\": Maximum of fConvolutedGausDeltaPrime <= 0!\n");
3123 fConvolutedGausDeltaPrime->SetParameters(oldFuncParams);
3124 fConvolutedGausDeltaPrime->SetNpx(oldFuncNpx);
3125 fConvolutedGausDeltaPrime->SetRange(oldFuncRangeLow, oldFuncRangeUp);
3128 delete [] oldFuncParams;
3133 // maxX perfectly shifts as par[0] (scaled by sigma) -> Can shift maxX to input value.
3134 // Mu shift correction:
3135 fConvolutedGaussTransitionPars[0] = maxXconvoluted - maxXInput;
3140 fConvolutedGausDeltaPrime->SetParameters(oldFuncParams);
3141 fConvolutedGausDeltaPrime->SetNpx(oldFuncNpx);
3142 fConvolutedGausDeltaPrime->SetRange(oldFuncRangeLow, oldFuncRangeUp);
3145 delete [] oldFuncParams;
3151 //_____________________________________________________________________________
3152 AliAnalysisTaskPID::ErrorCode AliAnalysisTaskPID::SetParamsForConvolutedGaus(Double_t gausMean, Double_t gausSigma)
3154 // Set parameters for convoluted gauss using parameters for a pure gaussian.
3155 // If SetConvolutedGaussLambdaParameter has not been called before to initialise the translation parameters,
3156 // some default parameters will be used and an error will show up.
3159 printf("File: %s, Line: %d: SetParamsForConvolutedGaus: mean %e, sigma %e\n", (char*)__FILE__, __LINE__, gausMean, gausSigma);
3161 if (fConvolutedGaussTransitionPars[1] < -998) {
3162 AliError("Transition parameters not initialised! Default parameters will be used. Please call SetConvolutedGaussLambdaParameter(...) before any calculations!");
3163 SetConvolutedGaussLambdaParameter(2.0);
3164 AliError(Form("Parameters set to:\n[0]: %f\n[1]: %f\n[2]: %f\n", fConvolutedGaussTransitionPars[0],
3165 fConvolutedGaussTransitionPars[1], fConvolutedGaussTransitionPars[2]));
3168 Double_t par[fkConvolutedGausNPar];
3169 par[2] = fConvolutedGaussTransitionPars[2];
3170 par[1] = fConvolutedGaussTransitionPars[1] * gausSigma;
3171 // maxX perfectly shifts as par[0] (scaled by sigma) -> Can shift maxX so that it sits at the right place.
3172 par[0] = gausMean - fConvolutedGaussTransitionPars[0] * par[1] / fgkSigmaReferenceForTransitionPars;
3174 ErrorCode errCode = kNoErrors;
3175 fConvolutedGausDeltaPrime->SetParameters(par);
3178 printf("File: %s, Line: %d: SetParamsForConvolutedGaus -> Parameters set to: %e, %e, %e (transition pars: %e, %e, %e, %e)\n",
3179 (char*)__FILE__, __LINE__, par[0], par[1], par[2], fConvolutedGaussTransitionPars[0], fConvolutedGaussTransitionPars[1],
3180 fConvolutedGaussTransitionPars[2], fgkSigmaReferenceForTransitionPars);
3182 fConvolutedGausDeltaPrime->SetNpx(20); // Small value speeds up following algorithm (valid, since extrema far apart)
3184 // Accuracy of 10^-5 is enough to get 0.1% precise peak for MIPS w.r.t. to dEdx = 2000 of protons
3185 // (should boost up the algorithm, because 10^-10 is the default value!)
3186 Double_t maxX= fConvolutedGausDeltaPrime->GetMaximumX(TMath::Max(0.001, gausMean - 2. * gausSigma),
3187 gausMean + 6. * gausSigma, 1.0E-5);
3189 const Double_t maximum = fConvolutedGausDeltaPrime->Eval(maxX);
3190 const Double_t maximumFraction = maximum * fAccuracyNonGaussianTail;
3192 // Estimate lower boundary for subsequent search:
3193 Double_t lowBoundSearchBoundLow = TMath::Max(1e-4, maxX - 5. * gausSigma);
3194 Double_t lowBoundSearchBoundUp = maxX;
3196 Bool_t lowerBoundaryFixedAtZero = kFALSE;
3198 while (fConvolutedGausDeltaPrime->Eval(lowBoundSearchBoundLow) >= maximumFraction) {
3199 if (lowBoundSearchBoundLow <= 0) {
3200 // This should only happen to low dEdx particles with very few clusters and therefore large sigma, such that the gauss goes below zero deltaPrime
3201 if (maximum <= 0) { // Something is weired
3202 printf("Error generating signal: maximum is <= 0!\n");
3206 const Double_t valueAtZero = fConvolutedGausDeltaPrime->Eval(0);
3207 if (valueAtZero / maximum > 0.05) {
3208 // Too large fraction below zero deltaPrime. Signal generation cannot be reliable in this case
3209 printf("Error generating signal: Too large fraction below zero deltaPrime: convGauss(0) / convGauss(max) = %e / %e = %e!\n",
3210 valueAtZero, maximum, valueAtZero / maximum);
3216 printf("Warning: LowBoundSearchBoundLow gets smaller zero -> Set left boundary to zero! Debug output: maximumFraction * fAccuracyNonGaussianTail = %e * %e = %e maxX %f, par[0] %f, par[1] %f, par[2] %f, gausMean %f, gausSigma %f\n",
3217 fConvolutedGausDeltaPrime->Eval(maxX), fAccuracyNonGaussianTail, maximumFraction, maxX, par[0], par[1], par[2], gausMean, gausSigma);
3220 lowerBoundaryFixedAtZero = kTRUE;
3222 if (errCode != kError)
3228 lowBoundSearchBoundUp -= gausSigma;
3229 lowBoundSearchBoundLow -= gausSigma;
3231 if (lowBoundSearchBoundLow < 0) {
3232 lowBoundSearchBoundLow = 0;
3233 lowBoundSearchBoundUp += gausSigma;
3237 // Determine lower boundary inside estimated range. For small values of the maximum: Need more precision, since finer binning!
3238 Double_t rangeStart = lowerBoundaryFixedAtZero ? 0 :
3239 fConvolutedGausDeltaPrime->GetX(maximumFraction, lowBoundSearchBoundLow, lowBoundSearchBoundUp, (maxX < 0.4) ? 1e-5 : 0.001);
3241 // .. and the same for the upper boundary
3242 Double_t rangeEnd = 0;
3243 // If distribution starts beyond upper boundary, everything ends up in the overflow bin. So, just reduce range and Npx to minimum
3244 if (rangeStart > fkDeltaPrimeUpLimit) {
3245 rangeEnd = rangeStart + 0.00001;
3246 fConvolutedGausDeltaPrime->SetRange(rangeStart,rangeEnd);
3247 fConvolutedGausDeltaPrime->SetNpx(4);
3250 // Estimate upper boundary for subsequent search:
3251 Double_t upBoundSearchBoundUp = maxX + 5 * gausSigma;
3252 Double_t upBoundSearchBoundLow = maxX;
3253 while (fConvolutedGausDeltaPrime->Eval(upBoundSearchBoundUp) >= maximumFraction) {
3254 upBoundSearchBoundUp += gausSigma;
3255 upBoundSearchBoundLow += gausSigma;
3258 // For small values of the maximum: Need more precision, since finer binning!
3259 rangeEnd = fConvolutedGausDeltaPrime->GetX(maximumFraction, upBoundSearchBoundLow, upBoundSearchBoundUp, (maxX < 0.4) ? 1e-5 : 0.001);
3261 fConvolutedGausDeltaPrime->SetRange(rangeStart,rangeEnd);
3262 fConvolutedGausDeltaPrime->SetNpx(fhPIDdataAll->GetAxis(kDataDeltaPrimeSpecies)->FindBin(rangeEnd)
3263 - fhPIDdataAll->GetAxis(kDataDeltaPrimeSpecies)->FindBin(rangeStart) + 1);
3264 //fConvolutedGausDeltaPrime->SetNpx((rangeEnd - rangeStart) / fDeltaPrimeBinWidth + 1);
3268 printf("File: %s, Line: %d: SetParamsForConvolutedGaus -> range %f - %f, error code %d\n", (char*)__FILE__, __LINE__,
3269 rangeStart, rangeEnd, errCode);
3275 //________________________________________________________________________
3276 void AliAnalysisTaskPID::SetUpGenHist(THnSparse* hist, Double_t* binsPt, Double_t* binsDeltaPrime, Double_t* binsCent, Double_t* binsJetPt) const
3278 // Sets bin limits for axes which are not standard binned and the axes titles.
3280 hist->SetBinEdges(kGenPt, binsPt);
3281 hist->SetBinEdges(kGenDeltaPrimeSpecies, binsDeltaPrime);
3282 hist->SetBinEdges(kGenCentrality, binsCent);
3284 if (fStoreAdditionalJetInformation)
3285 hist->SetBinEdges(kGenJetPt, binsJetPt);
3288 hist->GetAxis(kGenMCID)->SetTitle("MC PID");
3289 hist->GetAxis(kGenMCID)->SetBinLabel(1, "e");
3290 hist->GetAxis(kGenMCID)->SetBinLabel(2, "K");
3291 hist->GetAxis(kGenMCID)->SetBinLabel(3, "#mu");
3292 hist->GetAxis(kGenMCID)->SetBinLabel(4, "#pi");
3293 hist->GetAxis(kGenMCID)->SetBinLabel(5, "p");
3295 hist->GetAxis(kGenSelectSpecies)->SetTitle("Select Species");
3296 hist->GetAxis(kGenSelectSpecies)->SetBinLabel(1, "e");
3297 hist->GetAxis(kGenSelectSpecies)->SetBinLabel(2, "K");
3298 hist->GetAxis(kGenSelectSpecies)->SetBinLabel(3, "#pi");
3299 hist->GetAxis(kGenSelectSpecies)->SetBinLabel(4, "p");
3301 hist->GetAxis(kGenPt)->SetTitle("p_{T} (GeV/c)");
3303 hist->GetAxis(kGenDeltaPrimeSpecies)->SetTitle("TPC #Delta'_{species} (arb. unit)");
3305 hist->GetAxis(kGenCentrality)->SetTitle(Form("Centrality Percentile (%s)", fCentralityEstimator.Data()));
3307 if (fStoreAdditionalJetInformation) {
3308 hist->GetAxis(kGenJetPt)->SetTitle("p_{T}^{jet} (GeV/c)");
3310 hist->GetAxis(kGenZ)->SetTitle("z = p_{T}^{track} / p_{T}^{jet}");
3312 hist->GetAxis(kGenXi)->SetTitle("#xi = ln(p_{T}^{jet} / p_{T}^{track})");
3315 hist->GetAxis(GetIndexOfChargeAxisGen())->SetTitle("Charge (e_{0})");
3317 hist->GetAxis(GetIndexOfTOFpidInfoAxisGen())->SetTitle("TOF PID Info");
3318 // Offset is (TMath::Abs(kNoTOFinfo) + 1), such that bin 1 (= first label) corresponds to kNoTOFinfo (< 0)
3319 hist->GetAxis(GetIndexOfTOFpidInfoAxisGen())->SetBinLabel(kNoTOFinfo + (TMath::Abs(kNoTOFinfo) + 1), "No TOF Info");
3320 hist->GetAxis(GetIndexOfTOFpidInfoAxisGen())->SetBinLabel(kNoTOFpid + (TMath::Abs(kNoTOFinfo) + 1), "No TOF PID");
3321 hist->GetAxis(GetIndexOfTOFpidInfoAxisGen())->SetBinLabel(kTOFpion + (TMath::Abs(kNoTOFinfo) + 1), "#pi");
3322 hist->GetAxis(GetIndexOfTOFpidInfoAxisGen())->SetBinLabel(kTOFkaon + (TMath::Abs(kNoTOFinfo) + 1), "K");
3323 hist->GetAxis(GetIndexOfTOFpidInfoAxisGen())->SetBinLabel(kTOFproton + (TMath::Abs(kNoTOFinfo) + 1), "p");
3327 //________________________________________________________________________
3328 void AliAnalysisTaskPID::SetUpGenYieldHist(THnSparse* hist, Double_t* binsPt, Double_t* binsCent, Double_t* binsJetPt) const
3330 // Sets bin limits for axes which are not standard binned and the axes titles.
3332 hist->SetBinEdges(kGenYieldPt, binsPt);
3333 hist->SetBinEdges(kGenYieldCentrality, binsCent);
3334 if (fStoreAdditionalJetInformation)
3335 hist->SetBinEdges(kGenYieldJetPt, binsJetPt);
3337 for (Int_t i = 0; i < 5; i++)
3338 hist->GetAxis(kGenYieldMCID)->SetBinLabel(i + 1, AliPID::ParticleLatexName(i));
3341 hist->GetAxis(kGenYieldMCID)->SetTitle("MC PID");
3342 hist->GetAxis(kGenYieldPt)->SetTitle("p_{T}^{gen} (GeV/c)");
3343 hist->GetAxis(kGenYieldCentrality)->SetTitle(Form("Centrality Percentile (%s)", fCentralityEstimator.Data()));
3345 if (fStoreAdditionalJetInformation) {
3346 hist->GetAxis(kGenYieldJetPt)->SetTitle("p_{T}^{jet, gen} (GeV/c)");
3348 hist->GetAxis(kGenYieldZ)->SetTitle("z = p_{T}^{track} / p_{T}^{jet}");
3350 hist->GetAxis(kGenYieldXi)->SetTitle("#xi = ln(p_{T}^{jet} / p_{T}^{track})");
3353 hist->GetAxis(GetIndexOfChargeAxisGenYield())->SetTitle("Charge (e_{0})");
3357 //________________________________________________________________________
3358 void AliAnalysisTaskPID::SetUpHist(THnSparse* hist, Double_t* binsPt, Double_t* binsDeltaPrime, Double_t* binsCent, Double_t* binsJetPt) const
3360 // Sets bin limits for axes which are not standard binned and the axes titles.
3362 hist->SetBinEdges(kDataPt, binsPt);
3363 hist->SetBinEdges(kDataDeltaPrimeSpecies, binsDeltaPrime);
3364 hist->SetBinEdges(kDataCentrality, binsCent);
3366 if (fStoreAdditionalJetInformation)
3367 hist->SetBinEdges(kDataJetPt, binsJetPt);
3370 hist->GetAxis(kDataMCID)->SetTitle("MC PID");
3371 hist->GetAxis(kDataMCID)->SetBinLabel(1, "e");
3372 hist->GetAxis(kDataMCID)->SetBinLabel(2, "K");
3373 hist->GetAxis(kDataMCID)->SetBinLabel(3, "#mu");
3374 hist->GetAxis(kDataMCID)->SetBinLabel(4, "#pi");
3375 hist->GetAxis(kDataMCID)->SetBinLabel(5, "p");
3377 hist->GetAxis(kDataSelectSpecies)->SetTitle("Select Species");
3378 hist->GetAxis(kDataSelectSpecies)->SetBinLabel(1, "e");
3379 hist->GetAxis(kDataSelectSpecies)->SetBinLabel(2, "K");
3380 hist->GetAxis(kDataSelectSpecies)->SetBinLabel(3, "#pi");
3381 hist->GetAxis(kDataSelectSpecies)->SetBinLabel(4, "p");
3383 hist->GetAxis(kDataPt)->SetTitle("p_{T} (GeV/c)");
3385 hist->GetAxis(kDataDeltaPrimeSpecies)->SetTitle("TPC #Delta'_{species} (arb. unit)");
3387 hist->GetAxis(kDataCentrality)->SetTitle(Form("Centrality Percentile (%s)", fCentralityEstimator.Data()));
3389 if (fStoreAdditionalJetInformation) {
3390 hist->GetAxis(kDataJetPt)->SetTitle("p_{T}^{jet} (GeV/c)");
3392 hist->GetAxis(kDataZ)->SetTitle("z = p_{T}^{track} / p_{T}^{jet}");
3394 hist->GetAxis(kDataXi)->SetTitle("#xi = ln(p_{T}^{jet} / p_{T}^{track})");
3397 hist->GetAxis(GetIndexOfChargeAxisData())->SetTitle("Charge (e_{0})");
3399 hist->GetAxis(GetIndexOfTOFpidInfoAxisData())->SetTitle("TOF PID Info");
3400 // Offset is (TMath::Abs(kNoTOFinfo) + 1), such that bin 1 (= first label) corresponds to kNoTOFinfo (< 0)
3401 hist->GetAxis(GetIndexOfTOFpidInfoAxisData())->SetBinLabel(kNoTOFinfo + (TMath::Abs(kNoTOFinfo) + 1), "No TOF Info");
3402 hist->GetAxis(GetIndexOfTOFpidInfoAxisData())->SetBinLabel(kNoTOFpid + (TMath::Abs(kNoTOFinfo) + 1), "No TOF PID");
3403 hist->GetAxis(GetIndexOfTOFpidInfoAxisData())->SetBinLabel(kTOFpion + (TMath::Abs(kNoTOFinfo) + 1), "#pi");
3404 hist->GetAxis(GetIndexOfTOFpidInfoAxisData())->SetBinLabel(kTOFkaon + (TMath::Abs(kNoTOFinfo) + 1), "K");
3405 hist->GetAxis(GetIndexOfTOFpidInfoAxisData())->SetBinLabel(kTOFproton + (TMath::Abs(kNoTOFinfo) + 1), "p");
3409 //________________________________________________________________________
3410 void AliAnalysisTaskPID::SetUpPtResHist(THnSparse* hist, Double_t* binsPt, Double_t* binsJetPt, Double_t* binsCent) const
3412 // Sets bin limits for axes which are not standard binned and the axes titles.
3414 hist->SetBinEdges(kPtResJetPt, binsJetPt);
3415 hist->SetBinEdges(kPtResGenPt, binsPt);
3416 hist->SetBinEdges(kPtResRecPt, binsPt);
3417 hist->SetBinEdges(kPtResCentrality, binsCent);
3420 hist->GetAxis(kPtResJetPt)->SetTitle("p_{T}^{jet, rec} (GeV/c)");
3421 hist->GetAxis(kPtResGenPt)->SetTitle("p_{T}^{gen} (GeV/c)");
3422 hist->GetAxis(kPtResRecPt)->SetTitle("p_{T}^{rec} (GeV/c)");
3424 hist->GetAxis(kPtResCharge)->SetTitle("Charge (e_{0})");
3425 hist->GetAxis(kPtResCentrality)->SetTitle(Form("Centrality Percentile (%s)", fCentralityEstimator.Data()));