]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGJE/macros/PID/PID.C
Fix for end-of-line style
[u/mrichter/AliRoot.git] / PWGJE / macros / PID / PID.C
CommitLineData
c683985a 1#include "THnSparse.h"
2#include "TH2D.h"
3#include "TH1D.h"
4#include "TProfile.h"
5#include "TF1.h"
6#include "TFitResultPtr.h"
7#include "TFitResult.h"
8#include "TCanvas.h"
9#include "TStyle.h"
10#include "TVirtualFitter.h"
11#include "TObjArray.h"
12#include "TString.h"
13#include "TLegend.h"
14#include "TFile.h"
15#include "TGraphErrors.h"
16#include "TGraph.h"
17#include "TMath.h"
18#include "TMatrixDSym.h"
19#include "TRandom3.h"
20#include "TROOT.h"
21
22#include <iostream>
23#include <iomanip>
24
25#include "AliPID.h"
26
27#include "THnSparseDefinitions.h"
28#include "AliTPCPIDmathFit.h"
29
30enum processMode { kPMpT = 0, kPMz = 1, kPMxi = 2 };
31enum muonTreatment { kNoMuons = 0, kMuonFracEqualElFrac = 1, kMuonFracOverElFracTunedOnMCStandardTrackCuts = 2,
32 kMuonFracOverElFracTunedOnMCHybridTrackCuts = 3, kMuonFracOverElFracTunedOnMCHybridTrackCutsJets = 4,
33 kMuonFracOverElFracTunedOnMCStandardTrackCutsPPb = 5,
34 kNumHandlings = 6 };
35
36const TString modeShortName[3] = { "Pt", "Z", "Xi" };
37const TString modeLatexName[3] = { "P_{T}", "z", "#xi" };
38
39const TString muonFractionHandlingShortName[kNumHandlings] =
40 { "noMuons", "muonsEqualElectrons", "muonToElTunedOnMCStandardTrackCuts", "muonToElTunedOnMCHybridTrackCuts",
41 "muonToElTunedOnMCHybridTrackCutsJets", "muonToElTunedOnMCStandardTrackCutsPPB" };
42
43const Double_t epsilon = 1e-10;
44const TString identifiedLabels[2] = { "Most Probable PID", "MC" };
45Int_t isMC = 0;
46
47TString minimisationStrategy = "MIGRAD"; // "MINIMIZE"
48Bool_t takeIntoAccountMuons = kTRUE;
49
50// 0 = no muons, 1 = muonFrac=elFrac, 2(3) = muonFrac/elFrac tuned on MC for DefaultTrackCuts (hybridTrackCuts),
51// 4 = muonFrac/elFrac tuned on MC for hybridTrackCuts for jet particles,
52Int_t muonFractionHandling = 3;
53
54
55//TODO getErrorOf.... is COMPLETELY wrong now, since the parameter numbering has changed and the muons had come into play!!!!!!
56
57// TODO CAREFUL: fitMethod == 1 adds errors of electrons to pions, but not to muons (should be added to electron error instead!)
58const Bool_t muonContamination = kFALSE;//TODO CAREFUL: fitMethod == 1 takes into account the muon contamination in the error calculation!!!
59
60const Bool_t normaliseResults = kTRUE; // Works only for fitMethod == 2
61
62const Bool_t enableShift = kFALSE;
63const Int_t dataAxis = kPidDeltaPrime;//kPidDelta; kPidDeltaPrime
64
65const Int_t numSimultaneousFits = 4;
66
67// Upper and lower axis bounds (y-axis) of (data - fit) / data QA histos
68const Double_t fitQAaxisLowBound = -0.5;
69const Double_t fitQAaxisUpBound = 0.5;
70
71Bool_t useDeltaPrime = (dataAxis == kPidDeltaPrime);
72
73// Will be set later
74Double_t muonFractionThresholdForFitting = -1.;
75Double_t muonFractionThresholdBinForFitting = -1;
76
77Double_t electronFractionThresholdForFitting = -1.;
78Double_t electronFractionThresholdBinForFitting = -1;
79
80
81TF1 fMuonOverElFractionMC("fMuonOverElFractionMC", "[0]+[1]/TMath::Min(x, [4])+[2]*TMath::Min(x, [4])+[3]*TMath::Min(x, [4])*TMath::Min(x, [4])+[5]*TMath::Min(x, [4])*TMath::Min(x, [4])*TMath::Min(x, [4])+[6]*(x>[7])*TMath::Min(x-[7], [8]-[7])",
82 0.01, 50.);
83
84TF1* fElectronFraction = 0x0;
85const Double_t lowFittingBoundElectronFraction = 3.0;
86
87TGraphErrors* gFractionElectronsData = 0x0;
88Double_t lastPtForCallOfGetElectronFraction = -1;
89
90
91//____________________________________________________________________________________________________________________
92Double_t GetElectronFraction(const Double_t pT, const Double_t *par)
93{
94 // During the fit (both, simultaneous and non-simultaneous), the algorithm will always start off from
95 // the low pT and go to higher pT. So, it is only necessary to do the fit once the first fixed bin is reached.
96 // Then the parameters for the electron fraction remain fixed until the next fit iteration.
97 // Since only for the case of regularisation the electron fractions of all x bins are stored in mathFit,
98 // the evaluation of this function is done here only in that case (only then the electron fraction will
99 // be set to "-pT".
100
101 // NOTE 1: Electrons have index 3 per x bin
102 // NOTE 2: This function is only called for fitting vs. pT. In that case, xValue holds the LOG of pT!
103
104 AliTPCPIDmathFit* mathFit = AliTPCPIDmathFit::Instance();
105
106 // lastPtForCallOfGetElectronFraction will be initialised with a value larger than any pT during the fit.
107 // So, if this function is called and the pT is smaller than lastPtForCallOfGetElectronFraction, the parameters
108 // must have changed and the electron fit needs to be re-done (also see comment above)
109 if (pT < lastPtForCallOfGetElectronFraction) {
110 for (Int_t xBin = 0; xBin < mathFit->GetNumXbinsRegularisation(); xBin++) {
111
112 const Double_t xCoord = TMath::Exp(mathFit->GetXvaluesForRegularisation()[xBin]);
113 const Int_t parIndexWithFraction = 3 + xBin * mathFit->GetNumParametersPerXbin();
114
115 if (xCoord >= lowFittingBoundElectronFraction && xCoord <= electronFractionThresholdForFitting
116 && par[parIndexWithFraction] > epsilon) { // Skip zero values (usually due to failed fits)
117 gFractionElectronsData->SetPoint(xBin, TMath::Exp(mathFit->GetXvaluesForRegularisation()[xBin]), par[parIndexWithFraction]);
118 // Since the errors during the fitting are not reliable, use the following approximation on a statistical basis
119 // (which indeed turns out to be rather good!)
120
121 // Bin effective weight required for weighted data sets. In case of no weighting, the weight error is sqrt(weight),
122 // i.e. effWeight is 1
123 const Double_t effWeight = mathFit->GetXstatisticalWeightError()[xBin] * mathFit->GetXstatisticalWeightError()[xBin]
124 / mathFit->GetXstatisticalWeight()[xBin];
125 gFractionElectronsData->SetPointError(xBin, 0, effWeight * TMath::Sqrt(par[parIndexWithFraction]
126 / mathFit->GetXstatisticalWeight()[xBin]));
127 }
128 else {
129 gFractionElectronsData->SetPoint(xBin, -1, 0);
130 gFractionElectronsData->SetPointError(xBin, 0, 0);
131 }
132 }
133
134 gFractionElectronsData->Fit(fElectronFraction, "Ex0NQ", "", lowFittingBoundElectronFraction, electronFractionThresholdForFitting);
135 }
136
137 lastPtForCallOfGetElectronFraction = pT;
138
139 // Catch cases in which the fit function yields invalid fractions (i.e. < 0 or > 1)
140 return TMath::Max(0.0, TMath::Min(1.0, fElectronFraction->Eval(pT)));
141}
142
143
144//____________________________________________________________________________________________________________________
145Double_t GetElectronFractionError()
146{
147 // This function estimates the error of the electron fraction for the fixed values via using the parameter errors of
148 // the electron fraction function. Note that the parameters (and errors) must be set before calling this function.
149
150 // Produce several values via setting the parameters to a random value, which is distributed with a gaussian with mean = parValue
151 // and sigma = parError and then take the 2*RMS as the error
152 const Int_t nGenValues = 1000;
153 Double_t genValues[nGenValues];
154
155 const Int_t nPars = fElectronFraction->GetNpar();
156 Double_t par[nPars];
157
158 TRandom3 rnd(0); // 0 means random seed
159
160 const Double_t x = electronFractionThresholdForFitting + 1.; // Some value above the threshold to obtain a fixed value
161 for (Int_t i = 0 ; i < nGenValues; i++) {
162 for (Int_t iPar = 0; iPar < nPars; iPar++)
163 par[iPar] = rnd.Gaus(fElectronFraction->GetParameter(iPar), fElectronFraction->GetParError(iPar));
164
165 genValues[i] = fElectronFraction->EvalPar(&x, &par[0]);
166 }
167
168 // NOTE: RMS is not really the root mean square, is it rather the sigma deviation, which is what is wanted here
169 return 2. * TMath::RMS(nGenValues, &genValues[0]);
170}
171
172
173//____________________________________________________________________________________________________________________
174Double_t GetMuonFractionFromElectronFractionAndPt(Double_t pT, Double_t elFrac)
175{
176 if (muonFractionHandling == kMuonFracOverElFracTunedOnMCStandardTrackCuts) {
177// return elFrac / (1. + 7.06909e+01 * TMath::Exp(-2.95078e+00 * TMath::Power(pT, 5.05016e-01)));
178 return elFrac / (1. + 2.01840e+10 * TMath::Exp(-2.50480e+01 * TMath::Power(pT, 5.89044e-02)));
179 }
180 else if (muonFractionHandling == kMuonFracOverElFracTunedOnMCHybridTrackCuts) {
181 fMuonOverElFractionMC.SetParameters(-6.87241e-01, 4.19528e-02, 4.52095e+00, -6.20026e+00, 5.16629e-01, 2.88604e+00, 3.68058e-02,
182 2.21086e+00, 5.75003e+00);
183 return elFrac * fMuonOverElFractionMC.Eval(pT);
184 }
185 else if (muonFractionHandling == kMuonFracOverElFracTunedOnMCHybridTrackCutsJets) {
186 fMuonOverElFractionMC.SetParameters(-7.64548e-01, 2.47929e-02, 4.49057e+00, -2.06320e-01, 4.23339e-02, 1.19697e+02, 1.28832e-01,
187 -1.71895e-01, 6.00000e+00);
188 return elFrac * fMuonOverElFractionMC.Eval(pT);
189 }
190 else if (muonFractionHandling == kMuonFracOverElFracTunedOnMCStandardTrackCutsPPb) {
191 // WITH PID cluster cut!
192 fMuonOverElFractionMC.SetParameters(-6.62149e-01, 4.89591e-02, 4.58356e+00, -6.04319e+00, 6.25368e-01, 3.27191e+00, 1.69933e-01,
193 1.00004e+00, 2.61438e+00);
194 return elFrac * fMuonOverElFractionMC.Eval(pT);
195 }
196 else if (muonFractionHandling == kMuonFracEqualElFrac) {
197 return elFrac;
198 }
199
200 return 0.;
201}
202
203
204//____________________________________________________________________________________________________________________
205Double_t GetCorrelatedError(const Double_t x, const Double_t y, const Double_t cov00, const Double_t cov11, const Double_t cov01)
206{
207 // Calculate the correlated error df of f:
208 // (cov00 cov01) (x)
209 //df^2 = (x, y) * (cov01 cov11) (y) = x^2 * cov00 + y^2 * cov11 + 2 * x * y * cov01
210 //
211 // with f = f(p1, p2) = p1 / p2
212 // and (x, y) = (\partial f / \partial p1, \partial f / \partial p2)
213 // = (f / p1, -f / p2)
214
215 const Double_t df2 = x * x * cov00 + y * y * cov11 + 2. * x * y * cov01;
216
217 if (df2 < epsilon)
218 return 0.;
219
220 return TMath::Sqrt(df2);
221}
222
223
224//____________________________________________________________________________________________________________________
225void GetRatioWithCorrelatedError(const Double_t fractionA, const Double_t fractionB,
226 const Double_t fractionErrorA, const Double_t fractionErrorB,
227 const Double_t covMatrixElementAB, Double_t& ratio, Double_t& ratioError)
228{
229 // Given fractions A and B with corresponding errors and the off-diagonal covariance matrix element of
230 // these fractions, calculate the ratio A/B and the error taking into account the correlation.
231 // The results are stored in ratio and ratioError.
232
233 if (fractionB < epsilon) {
234 ratio = -999.;
235 ratioError = 999.;
236
237 return;
238 }
239
240 if (fractionA < epsilon) {
241 ratio = 0.;
242 ratioError = 999.;
243
244 return;
245 }
246
247 ratio = fractionA / fractionB;
248
249 const Double_t x = ratio / fractionA;
250 const Double_t y = -ratio / fractionB;
251
252 // covMatrixElement(i, i) = error(i)^2
253 ratioError = GetCorrelatedError(x, y, fractionErrorA * fractionErrorA, fractionErrorB * fractionErrorB, covMatrixElementAB);
254
255 //printf("frationA %e\nfractionB %e\nfractionErrorA %e\nfractionErrorB %e\ncovMatrixElementAB %e\nratio %e\nx %e\ny %e\nratioError %e\n\n",
256 // fractionA, fractionB, fractionErrorA, fractionErrorB, covMatrixElementAB, ratio, x, y, ratioError);
257}
258
259
260//____________________________________________________________________________________________________________________
261void SetReasonableAxisRange(TAxis* axis, Int_t mode, Double_t pLow = -1, Double_t pHigh = -1)
262{
263 if (mode == kPMpT)
264 axis->SetRangeUser(TMath::Max(0.15, pLow - 0.1), TMath::Min(50., pHigh + 0.1));
265 else if (mode == kPMz)
266 axis->SetRange(0, -1);
267 else if (mode == kPMxi)
268 axis->SetRange(0, -1);
269}
270
271//____________________________________________________________________________________________________________________
272void SetReasonableXaxisRange(TH1* h, Int_t& binLow, Int_t& binHigh)
273{
274 binLow = TMath::Max(1, h->FindFirstBinAbove(0));
275 binHigh = TMath::Min(h->GetNbinsX(), h->FindLastBinAbove(0));
276
277 h->GetXaxis()->SetRange(binLow, binHigh);
278 h->GetXaxis()->SetMoreLogLabels(kTRUE);
279 h->GetXaxis()->SetNoExponent(kTRUE);
280}
281
282
283//____________________________________________________________________________________________________________________
284Int_t FindMomentumBin(const Double_t* pTbins, const Double_t value, const Int_t numPtBins = nPtBins)
285{
286 for (Int_t bin = 0; bin < numPtBins; bin++) {
287 if (value >= pTbins[bin] && value < pTbins[bin + 1])
288 return bin;
289 }
290
291 return -1;
292}
293
294
295//____________________________________________________________________________________________________________________
296Double_t normaliseHist(TH1* h, Double_t scaleFactor = -1)
297{
298 // Scales the histogram with the scale factor. If the scale factor is < 0,
299 // the histogram is normalised to it's integral.
300 // In both cases, the normalisation factor is returned.
301
302 Double_t normFactor = 1.;
303
304 if (scaleFactor < 0) {
305 Double_t integralTemp = h->Integral();
306 if (integralTemp > 0) {
307 normFactor = 1.0 / integralTemp;
308 h->Scale(normFactor);
309 }
310 }
311 else {
312 normFactor = scaleFactor;
313 h->Scale(normFactor);
314 }
315
316 h->GetXaxis()->SetTitleOffset(1.0);
317
318 return normFactor;
319}
320
321
322//____________________________________________________________________________________________________________________
323void normaliseYieldHist(TH1* h, Double_t numEvents, Double_t deta)
324{
325 // Yield histos are already normalised to dpT. Now normalise to 1/NeV 1/(2pi pT) 1/deta in addition
326
327 if (numEvents <= 0) // Do not normalise
328 numEvents = 1;
329
330 for (Int_t bin = 1; bin <= h->GetNbinsX(); bin++) {
331 Double_t normFactor = 1. / (numEvents * 2 * TMath::Pi() * h->GetXaxis()->GetBinCenter(bin) * deta);
332 h->SetBinContent(bin, h->GetBinContent(bin) * normFactor);
333 h->SetBinError(bin, h->GetBinError(bin) * normFactor);
334 }
335}
336
337
338//____________________________________________________________________________________________________________________
339void normaliseGenYieldMCtruthHist(TH1* h, Double_t numEvents, Double_t deta)
340{
341 // Yield histos are NOT normalised to dpT. Now normalise to 1/NeV 1/(2pi pT) 1/deta 1/dpT!
342
343 if (numEvents <= 0) // Do not normalise
344 numEvents = 1;
345
346 for (Int_t bin = 1; bin <= h->GetNbinsX(); bin++) {
347 Double_t normFactor = 1. / (numEvents * 2 * TMath::Pi() * h->GetXaxis()->GetBinCenter(bin) * h->GetXaxis()->GetBinWidth(bin) * deta);
348 h->SetBinContent(bin, h->GetBinContent(bin) * normFactor);
349 h->SetBinError(bin, h->GetBinError(bin) * normFactor);
350 }
351}
352
353
354//____________________________________________________________________________________________________________________
355void setUpFitFunction(TF1* fitFunc, Int_t nBins, Bool_t noShift = kFALSE)
356{
357 fitFunc->SetLineColor(kGray + 1);
358 fitFunc->SetLineWidth(2);
359 fitFunc->SetLineStyle(1);
360 fitFunc->SetNpx(nBins * 100);
361 fitFunc->SetParName(0, "Pion fraction");
362 fitFunc->SetParName(1, "Kaon fraction");
363 fitFunc->SetParName(2, "Proton fraction");
364 fitFunc->SetParName(3, "Electron fraction");
365 fitFunc->SetParName(4, "Muon fraction");
366 fitFunc->SetParName(5, "Total yield");
367 if (noShift == kFALSE) {
368 fitFunc->SetParName(6, "Shift of pion peak");
369 fitFunc->SetParName(7, "Shift of kaon peak");
370 fitFunc->SetParName(8, "Shift of proton peak");
371 fitFunc->SetParName(9, "Shift of electron peak");
372 fitFunc->SetParName(10, "Shift of muon peak");
373 }
374}
375
376
377//____________________________________________________________________________________________________________________
378inline Int_t findBinWithinRange(const TAxis* axis, Double_t value)
379{
380 Int_t bin = axis->FindFixBin(value);
381 if (bin <= 0)
382 bin = 1;
383 if (bin > axis->GetNbins())
384 bin = axis->GetNbins();
385
386 return bin;
387}
388
389
390//____________________________________________________________________________________________________________________
391Double_t linearInterpolation(const TH1* h, Double_t x, Double_t scaleFactor, Double_t shift, Double_t* error)
392{
393 // Do linear interpolation between 2 bins to handle non-integer values of the shift parameters.
394 // The shift also introduces some uncertainty, which is rather hard to estimate. Therefore, just take the maximum error of the involved bins.
395 const Double_t xShifted = x - shift;
396
397 // Just take value of bin, if beyond center of first/last bin
398 if (xShifted <= h->GetBinCenter(1)) {
399 if (error)
400 *error = h->GetBinError(1) * scaleFactor;
401 return h->GetBinContent(1) * scaleFactor;
402 }
403 else if(xShifted >= h->GetBinCenter(h->GetNbinsX())) {
404 if (error)
405 *error = h->GetBinError(h->GetNbinsX()) * scaleFactor;
406 return h->GetBinContent(h->GetNbinsX()) * scaleFactor;
407 }
408 else {
409 const Int_t xbin = h->FindFixBin(xShifted);
410 Double_t x0, x1, y0, y1;
411
412 if(xShifted <= h->GetBinCenter(xbin)) {
413 y0 = h->GetBinContent(xbin - 1);
414 x0 = h->GetBinCenter(xbin - 1);
415 y1 = h->GetBinContent(xbin);
416 x1 = h->GetBinCenter(xbin);
417
418 if (error)
419 *error = TMath::Max(h->GetBinError(xbin - 1), h->GetBinError(xbin)) * scaleFactor;
420 }
421 else {
422 y0 = h->GetBinContent(xbin);
423 x0 = h->GetBinCenter(xbin);
424 y1 = h->GetBinContent(xbin + 1);
425 x1 = h->GetBinCenter(xbin + 1);
426
427 if (error)
428 *error = TMath::Max(h->GetBinError(xbin), h->GetBinError(xbin + 1)) * scaleFactor;
429 }
430
431 return scaleFactor * (y0 + (xShifted - x0) * ((y1 - y0) / (x1 - x0)));
432 }
433
434 return 0;
435
436 /*Old version available for code bevor 03.05.2013*/
437}
438
439
440//____________________________________________________________________________________________________________________
441void shiftHist(TH1D* h, Double_t shift, Bool_t useRegularisation = kFALSE)
442{
443 // Shift not available for regularisation. Just for convenience (can use the same code and only set one flag)
444 // call this functions and then do nothing.
445 // Actually, the shift is not availabe for simultaneous fitting also, but the parameter is just set to 0 there
446 if (!h || useRegularisation)
447 return;
448
449 TString name = h->GetName();
450 TH1D* hTemp = (TH1D*)h->Clone(Form("%s_clone", name.Data()));
451 h->Reset();
452
453 Double_t error = 0;
454 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
455 // linearInterpolation with scaleFactor = 1.0, since histo is assumed to be properly scaled
456 h->SetBinContent(i, linearInterpolation(hTemp, h->GetXaxis()->GetBinCenter(i), 1.0, shift, &error));
457 h->SetBinError(i, error);
458 }
459
460 delete hTemp;
461}
462
463
464//____________________________________________________________________________________________________________________
465Double_t multiGaussFitForSimultaneousFitting(const Double_t *xx, const Double_t *par, const Int_t offset)
466{
467 // Offset for reference histos for delta_Species
468 AliTPCPIDmathFit* mathFit = AliTPCPIDmathFit::Instance();
469
470 // parXbinIndex (fixed) will be used my mathfit to hold the pT bin index (needed for regularisation)
471 const Int_t xBinIndex = mathFit->GetXbinIndex();
472 const Int_t numParsPerXbin = mathFit->GetNumParametersPerXbin();
473
474 const Int_t numRefHistosPerFit = numSimultaneousFits + (takeIntoAccountMuons ? 1 : 0);
475 const Int_t numRefHistosPerXbin = numRefHistosPerFit * numSimultaneousFits;
476
477 const Int_t refHistOffset = offset * numRefHistosPerFit + xBinIndex * numRefHistosPerXbin;
478
479 const TH1* hRefPi = mathFit->GetRefHisto(0 + refHistOffset);
480 const TH1* hRefKa = mathFit->GetRefHisto(1 + refHistOffset);
481 const TH1* hRefPr = mathFit->GetRefHisto(2 + refHistOffset);
482 const TH1* hRefEl = mathFit->GetRefHisto(3 + refHistOffset);
483 const TH1* hRefMu = takeIntoAccountMuons ? mathFit->GetRefHisto(4 + refHistOffset) : 0x0;
484
485 if (!hRefEl || !hRefKa || !hRefPi || !hRefPr)
486 return 0;
487
488 if (takeIntoAccountMuons && !hRefMu)
489 return 0;
490
491 const Int_t parOffset = xBinIndex * numParsPerXbin;
492 const Int_t parPi = 0 + parOffset;
493 const Int_t parKa = 1 + parOffset;
494 const Int_t parPr = 2 + parOffset;
495 const Int_t parEl = 3 + parOffset;
496 const Int_t parMu = 4 + parOffset;
497 const Int_t parAll = 5 + parOffset;
498
499 const Double_t scaleFactorPi = par[parAll] * (par[parPi] + (muonContamination ? par[parEl] : 0));
500 const Double_t scaleFactorKa = par[parAll] * par[parKa];
501 const Double_t scaleFactorPr = par[parAll] * par[parPr];
502 const Double_t parElFraction = (par[parEl] < 0) ? GetElectronFraction(-par[parEl], par) : par[parEl];
503 const Double_t scaleFactorEl = par[parAll] * parElFraction;
504 // Fix muon fraction to electron fraction (or some modified electron fraction) if desired, i.e. corresponding par < 0
505 const Double_t scaleFactorMu = (par[parMu] < 0)
506 ? (par[parAll] * GetMuonFractionFromElectronFractionAndPt(-par[parMu], parElFraction))
507 : (par[parAll] * par[parMu]);
508
509 // Since one is looking at the same deltaSpecies for all considered species, the reference histograms have the same axes
510 // => Only need to search for the bin once
511 const Int_t binWithinRange = findBinWithinRange(hRefPi->GetXaxis(), xx[0]);
512 const Double_t countPi = scaleFactorPi * hRefPi->GetBinContent(binWithinRange);
513 const Double_t countKa = scaleFactorKa * hRefKa->GetBinContent(binWithinRange);
514 const Double_t countPr = scaleFactorPr * hRefPr->GetBinContent(binWithinRange);
515 const Double_t countEl = scaleFactorEl * hRefEl->GetBinContent(binWithinRange);
516 const Double_t countMu = takeIntoAccountMuons ? scaleFactorMu * hRefMu->GetBinContent(binWithinRange) : 0;
517
518 const Double_t res = countPi + countKa + countPr + countEl + countMu;
519
520
521 return res;
522}
523
524
525//____________________________________________________________________________________________________________________
526inline Double_t multiGaussFitDeltaPi(const Double_t *xx, const Double_t *par)
527{
528 return multiGaussFitForSimultaneousFitting(xx, par, 0);
529}
530
531//____________________________________________________________________________________________________________________
532inline Double_t multiGaussFitDeltaKa(const Double_t *xx, const Double_t *par)
533{
534 return multiGaussFitForSimultaneousFitting(xx, par, 1);
535}
536
537//____________________________________________________________________________________________________________________
538inline Double_t multiGaussFitDeltaPr(const Double_t *xx, const Double_t *par)
539{
540 return multiGaussFitForSimultaneousFitting(xx, par, 2);
541}
542
543//____________________________________________________________________________________________________________________
544inline Double_t multiGaussFitDeltaEl(const Double_t *xx, const Double_t *par)
545{
546 return multiGaussFitForSimultaneousFitting(xx, par, 3);
547}
548
549
550//____________________________________________________________________________________________________________________
551Double_t multiGaussFit(const Double_t *xx, const Double_t *par)
552{
553 AliTPCPIDmathFit* mathFit = AliTPCPIDmathFit::Instance();
554 const TH1* hRefPi = mathFit->GetRefHisto(0);
555 const TH1* hRefKa = mathFit->GetRefHisto(1);
556 const TH1* hRefPr = mathFit->GetRefHisto(2);
557 const TH1* hRefEl = mathFit->GetRefHisto(3);
558 const TH1* hRefMu = takeIntoAccountMuons ? mathFit->GetRefHisto(4) : 0x0;
559
560 if (!hRefEl || !hRefKa || !hRefPi || !hRefPr)
561 return 0;
562
563 if (takeIntoAccountMuons && !hRefMu)
564 return 0;
565
566 // Do linear interpolation between 2 bins to handle non-integer values of the shift parameters
567 const Double_t scaleFactorPi = par[5] * (par[0] + (muonContamination ? par[3] : 0));
568 const Double_t scaleFactorKa = par[5] * par[1];
569 const Double_t scaleFactorPr = par[5] * par[2];
570 const Double_t parElFraction = (par[3] < 0) ? GetElectronFraction(-par[3], par) : par[3];
571 const Double_t scaleFactorEl = par[5] * parElFraction;
572 // Fix muon fraction to electron fraction (or some modified electron fraction) if desired, i.e. corresponding par < 0
573 const Double_t scaleFactorMu = (par[4] < 0)
574 ? (par[5] * GetMuonFractionFromElectronFractionAndPt(-par[4], parElFraction))
575 : (par[5] * par[4]);
576
577 const Double_t countPi = linearInterpolation(hRefPi, xx[0], scaleFactorPi, par[6], 0x0);
578 const Double_t countKa = linearInterpolation(hRefKa, xx[0], scaleFactorKa, par[7], 0x0);
579 const Double_t countPr = linearInterpolation(hRefPr, xx[0], scaleFactorPr, par[8], 0x0);
580 const Double_t countEl = linearInterpolation(hRefEl, xx[0], scaleFactorEl, par[9], 0x0);
581 const Double_t countMu = takeIntoAccountMuons ? linearInterpolation(hRefMu, xx[0], scaleFactorMu, par[10], 0x0) : 0;
582
583 const Double_t res = countPi + countKa + countPr + countEl + countMu;
584
585 /*
586 const Double_t countPi = linearInterpolation(hRefPi, xx[0], par[6], 0x0);
587 const Double_t countKa = linearInterpolation(hRefKa, xx[0], par[7], 0x0);
588 const Double_t countPr = linearInterpolation(hRefPr, xx[0], par[8], 0x0);
589 const Double_t countEl = linearInterpolation(hRefEl, xx[0], par[9], 0x0);
590 const Double_t countMu = takeIntoAccountMuons ? linearInterpolation(hRefMu, xx[0], par[10], 0x0) : 0;
591
592 const Double_t res = par[5] * ((par[0] + (muonContamination ? par[3] : 0)) * countPi + par[1] * countKa
593 + par[2] * countPr + par[3] * countEl + par[4] * countMu);
594
595 */
596
597 return res;
598}
599
600
601//____________________________________________________________________________________________________________________
602Double_t errorOfFitHistosForSimultaneousFitting(const Double_t *xx, const Double_t *par, const Int_t offset)
603{
604 AliTPCPIDmathFit* mathFit = AliTPCPIDmathFit::Instance();
605
606 Double_t summedError = 0;
607
608 // parXbinIndex (fixed) will be used my mathfit to hold the pT bin index (needed for regularisation)
609 const Int_t xBinIndex = mathFit->GetXbinIndex();
610 const Int_t numParsPerXbin = mathFit->GetNumParametersPerXbin();
611
612 const Int_t numRefHistosPerFit = numSimultaneousFits + (takeIntoAccountMuons ? 1 : 0);
613 const Int_t numRefHistosPerXbin = numRefHistosPerFit * numSimultaneousFits;
614
615 const Int_t refHistOffset = offset * numRefHistosPerFit + xBinIndex * numRefHistosPerXbin;
616
617 const TH1* hRefPi = mathFit->GetRefHisto(0 + refHistOffset);
618 const TH1* hRefKa = mathFit->GetRefHisto(1 + refHistOffset);
619 const TH1* hRefPr = mathFit->GetRefHisto(2 + refHistOffset);
620 const TH1* hRefEl = mathFit->GetRefHisto(3 + refHistOffset);
621 const TH1* hRefMu = takeIntoAccountMuons ?
622 mathFit->GetRefHisto(4 + refHistOffset)
623 : 0x0;
624
625 if (!hRefEl || !hRefKa || !hRefPi || !hRefPr)
626 return 0;
627
628 if (takeIntoAccountMuons && !hRefMu)
629 return 0;
630
631 const Int_t parOffset = xBinIndex * numParsPerXbin;
632 const Int_t parPi = 0 + parOffset;
633 const Int_t parKa = 1 + parOffset;
634 const Int_t parPr = 2 + parOffset;
635 const Int_t parEl = 3 + parOffset;
636 const Int_t parMu = 4 + parOffset;
637 const Int_t parAll = 5 + parOffset;
638
639 const Double_t scaleFactorPi = par[parAll] * (par[parPi] + (muonContamination ? par[parEl] : 0));
640 const Double_t scaleFactorKa = par[parAll] * par[parKa];
641 const Double_t scaleFactorPr = par[parAll] * par[parPr];
642 const Double_t scaleFactorEl = par[parAll] * ((par[parEl] < 0) ? GetElectronFraction(-par[parEl], par) : par[parEl]);
643 // Fix muon fraction to electron fraction (or some modified electron fraction) if desired, i.e. corresponding par < 0
644 const Double_t scaleFactorMu = (par[parMu] < 0) ?
645 (scaleFactorEl * GetMuonFractionFromElectronFractionAndPt(-par[parMu], par[parEl]) / par[parEl])
646 : (par[parAll] * par[parMu]);
647
648 Double_t errorPi = 0, errorKa = 0, errorPr = 0, errorEl = 0, errorMu = 0;
649
650 // Do linear interpolation between 2 bins to handle non-integer values of the shift parameters
651 // Shift not implemented for simultaneous fit -> Just set all corresponding parameters to zero
652 linearInterpolation(hRefPi, xx[0], scaleFactorPi, 0, &errorPi);
653 linearInterpolation(hRefKa, xx[0], scaleFactorKa, 0, &errorKa);
654 linearInterpolation(hRefPr, xx[0], scaleFactorPr, 0, &errorPr);
655 linearInterpolation(hRefEl, xx[0], scaleFactorEl, 0, &errorEl);
656 if (takeIntoAccountMuons)
657 linearInterpolation(hRefMu, xx[0], scaleFactorMu, 0, &errorMu);
658
659 summedError += TMath::Power(errorPi, 2);
660 summedError += TMath::Power(errorKa, 2);
661 summedError += TMath::Power(errorPr, 2);
662 summedError += TMath::Power(errorEl, 2);
663 if (takeIntoAccountMuons)
664 summedError += TMath::Power(errorMu, 2);
665
666 return summedError;
667}
668
669
670//____________________________________________________________________________________________________________________
671inline Double_t errorOfFitHistosDeltaPi(const Double_t *xx, const Double_t *par)
672{
673 return errorOfFitHistosForSimultaneousFitting(xx, par, 0);
674}
675
676
677//____________________________________________________________________________________________________________________
678inline Double_t errorOfFitHistosDeltaKa(const Double_t *xx, const Double_t *par)
679{
680 return errorOfFitHistosForSimultaneousFitting(xx, par, 1);
681}
682
683
684//____________________________________________________________________________________________________________________
685inline Double_t errorOfFitHistosDeltaPr(const Double_t *xx, const Double_t *par)
686{
687 return errorOfFitHistosForSimultaneousFitting(xx, par, 2);
688}
689
690
691//____________________________________________________________________________________________________________________
692inline Double_t errorOfFitHistosDeltaEl(const Double_t *xx, const Double_t *par)
693{
694 return errorOfFitHistosForSimultaneousFitting(xx, par, 3);
695}
696
697
698//____________________________________________________________________________________________________________________
699Double_t errorOfFitHistos(const Double_t *xx, const Double_t *par)
700{
701 //TODO Error of shift is still not taken into account
702 AliTPCPIDmathFit* mathFit = AliTPCPIDmathFit::Instance();
703
704 Double_t summedError = 0;
705
706 const TH1* hRefPi = mathFit->GetRefHisto(0);
707 const TH1* hRefKa = mathFit->GetRefHisto(1);
708 const TH1* hRefPr = mathFit->GetRefHisto(2);
709 const TH1* hRefEl = mathFit->GetRefHisto(3);
710 const TH1* hRefMu = takeIntoAccountMuons ? mathFit->GetRefHisto(4) : 0x0;
711
712 if (!hRefEl || !hRefKa || !hRefPi || !hRefPr)
713 return 0;
714
715 if (takeIntoAccountMuons && !hRefMu)
716 return 0;
717
718 // Do linear interpolation between 2 bins to handle non-integer values of the shift parameters
719 const Double_t scaleFactorPi = par[5] * (par[0] + (muonContamination ? par[3] : 0));
720 const Double_t scaleFactorKa = par[5] * par[1];
721 const Double_t scaleFactorPr = par[5] * par[2];
722 const Double_t scaleFactorEl = par[5] * ((par[3] < 0) ? GetElectronFraction(-par[3], par) : par[3]);
723 // Fix muon fraction to electron fraction (or some modified electron fraction) if desired, i.e. corresponding par < 0
724 const Double_t scaleFactorMu = (par[4] < 0) ? (scaleFactorEl * GetMuonFractionFromElectronFractionAndPt(-par[4], par[3]) / par[3])
725 : (par[5] * par[4]);
726
727 Double_t errorPi = 0, errorKa = 0, errorPr = 0, errorEl = 0, errorMu = 0;
728
729 linearInterpolation(hRefPi, xx[0], scaleFactorPi, par[6], &errorPi);
730 linearInterpolation(hRefKa, xx[0], scaleFactorKa, par[7], &errorKa);
731 linearInterpolation(hRefPr, xx[0], scaleFactorPr, par[8], &errorPr);
732 linearInterpolation(hRefEl, xx[0], scaleFactorEl, par[9], &errorEl);
733 if (takeIntoAccountMuons)
734 linearInterpolation(hRefMu, xx[0], scaleFactorMu, par[10], &errorMu); // Assume same fraction as electron, i.e. same scale factor
735
736 summedError += TMath::Power(errorPi, 2);
737 summedError += TMath::Power(errorKa, 2);
738 summedError += TMath::Power(errorPr, 2);
739 summedError += TMath::Power(errorEl, 2);
740 if (takeIntoAccountMuons)
741 summedError += TMath::Power(errorMu, 2);
742
743
744 /*
745 for (Int_t index = 0; index < mathFit->GetNrefHistos(); index++) {
746 TH1* HREF = mathFit->GetRefHisto(index);
747 Int_t bin = findBinWithinRange(HREF->GetXaxis(), xx[0]);
748 summedError += TMath::Power(HREF->GetBinError(bin) * par[index] * par[mathFit->GetNrefHistos()], 2);
749 }
750 */
751 return summedError;
752}
753
754
755//____________________________________________________________________________________________________________________
756inline Double_t saveDivide(Double_t numerator, Double_t denominator)
757{
758 return ((denominator != 0) ? numerator/denominator : 0 );
759}
760
761
762//____________________________________________________________________________________________________________________
763Double_t getErrorOfPionIntegral(TMatrixDSym covMat)
764{
765 return TMath::Sqrt(covMat(0, 0) + covMat(12, 12) + 2 * covMat(0, 12));
766}
767
768
769//____________________________________________________________________________________________________________________
770Double_t getErrorOfElectronFraction(Double_t* par, TMatrixDSym covMat)
771{
772 Double_t g = saveDivide(par[3], (par[0] + par[1] + par[2] + 2 * par[3]));
773 Double_t s1 = TMath::Power(g, 4) * (covMat(0, 0) + covMat(1, 1) + covMat(2, 2) + 4 * covMat(3, 3));
774 Double_t s2 = TMath::Power(g, 2) * covMat(3, 3);
775 Double_t s3 = (4 * TMath::Power(g, 4) - 2 * TMath::Power(g, 3)) * (covMat(3, 2) + covMat(3, 1) + covMat(3, 0));
776 Double_t s4 = TMath::Power(g, 4) * 2 * (covMat(2, 1) + covMat(2, 0) +covMat(1, 0));
777
778 return saveDivide(TMath::Sqrt(s1 + s2 + s3 + s4), par[3]);
779}
780
781
782//____________________________________________________________________________________________________________________
783Double_t getErrorOfKaonFraction(Double_t* par, TMatrixDSym covMat)
784{
785 Double_t g = saveDivide(par[1], (par[0] + par[1] + par[2] + 2 * par[3]));
786 Double_t s1 = TMath::Power(g, 4) * (covMat(0, 0) + covMat(1, 1) + covMat(2, 2) + 4 * covMat(3, 3));
787 Double_t s2 = TMath::Power(g, 2) * covMat(1, 1);
788 Double_t s3 = TMath::Power(g, 4) * (4 * covMat(3, 0) + 4 * covMat(3, 2) + 4 * covMat(3, 1) +
789 2 * covMat(2, 1) + 2 * covMat(2, 0) + 2 * covMat(1, 0));
790 Double_t s4 = TMath::Power(g, 3) * ((-4) * covMat(3, 1) - 2 * covMat(2, 1) - 2 * covMat(1, 0));
791
792 return saveDivide(TMath::Sqrt(s1 + s2 + s3 + s4), par[1]);
793}
794
795
796//____________________________________________________________________________________________________________________
797Double_t getErrorOfPionFraction(Double_t* par, TMatrixDSym covMat)
798{
799 Double_t g = saveDivide(par[0] + par[3], (par[0] + par[1] + par[2] + 2 * par[3]));
800 Double_t s1 = TMath::Power(g, 4) * (covMat(0, 0) + covMat(1, 1) + covMat(2, 2) + 4 * covMat(3, 3));
801 Double_t s2 = TMath::Power(g, 2) * (covMat(0, 0) + covMat(3, 3));
802 Double_t s3 = TMath::Power(g, 4) * 2 * covMat(2, 1);
803 Double_t s4 = (4 * TMath::Power(g, 4) - 2 * TMath::Power(g, 3)) * (covMat(3, 2) + covMat(3, 1));
804 Double_t s5 = 2 * covMat(3, 0) * (2 * TMath::Power(g, 4) - 3 * TMath::Power(g, 3) + TMath::Power(g, 2));
805 Double_t s6 = 2 * (covMat(2, 0) + covMat(1, 0)) * (TMath::Power(g, 4) - TMath::Power(g, 3));
806
807 return saveDivide(TMath::Sqrt(s1 + s2 + s3 + s4 + s5 + s6), par[0] + par[3]);
808}
809
810
811//____________________________________________________________________________________________________________________
812Double_t getErrorOfProtonFraction(Double_t* par, TMatrixDSym covMat)
813{
814 Double_t g = saveDivide(par[2], (par[0] + par[2] + par[1] + 2 * par[3]));
815 Double_t s1 = TMath::Power(g, 4) * (covMat(0, 0) + covMat(1, 1) + covMat(2, 2) + 4 * covMat(3, 3));
816 Double_t s2 = TMath::Power(g, 2) * covMat(2, 2);
817 Double_t s3 = TMath::Power(g, 4) * (4 * covMat(3, 0) + 4 * covMat(3, 2) + 4 * covMat(3, 1) +
818 2 * covMat(2, 1) + 2 * covMat(2, 0) + 2 * covMat(1, 0));
819 Double_t s4 = TMath::Power(g, 3) * ((-4) * covMat(3, 2) - 2 * covMat(2, 1) - 2 * covMat(2, 0));
820
821 return saveDivide(TMath::Sqrt(s1 + s2 + s3 + s4), par[2]);
822}
823
824
825//____________________________________________________________________________________________________________________
826Double_t getErrorOfTotalIntegral(TMatrixDSym covMat)
827{
828 Double_t s1 = covMat(0, 0) + covMat(1, 1) + covMat(2, 2) + 4 * covMat(3, 3);
829 Double_t s2 = 4 * (covMat(3, 0) + covMat(3, 1) + covMat(3, 2));
830 Double_t s3 = 2 * (covMat(2, 1) + covMat(2, 0) + covMat(1, 0));
831
832 return TMath::Sqrt(s1 + s2 + s3);
833}
834
835
836//____________________________________________________________________________________________________________________
837Double_t getMedianOfNonZeros(Double_t input[4])
838{
839 Double_t values[4] = {0,0,0,0};
840 Int_t numNonZero = 0;
841 if (input[0] > 0) {
842 values[numNonZero] = input[0];
843 numNonZero++;
844 }
845 if (input[1] > 0) {
846 values[numNonZero] = input[1];
847 numNonZero++;
848 }
849 if (input[2] > 0) {
850 values[numNonZero] = input[2];
851 numNonZero++;
852 }
853 if (input[3] > 0) {
854 values[numNonZero] = input[3];
855 numNonZero++;
856 }
857
858 return ((numNonZero > 0) ? TMath::Median(numNonZero, values) : 0);
859}
860
861
862//____________________________________________________________________________________________________________________
863TCanvas* drawFractionHistos(TString canvName, TString canvTitle, Int_t mode, Double_t pLow, Double_t pHigh,
864 TH1* histDeltaPion, TH1* histDeltaElectron, TH1* histDeltaKaon, TH1* histDeltaProton, TH1* histMC,
865 Bool_t plotIdentifiedSpectra)
866{
867 TCanvas* canv = new TCanvas(canvName.Data(), canvTitle.Data(),100,10,1200,800);
868 canv->SetGridx(1);
869 canv->SetGridy(1);
870 canv->SetLogx(mode == kPMpT);
871 histDeltaPion->GetYaxis()->SetRangeUser(0.0, 1.0);
872 histDeltaPion->GetYaxis()->SetTitle(canvTitle.Data());
873 SetReasonableAxisRange(histDeltaPion->GetXaxis(), mode, pLow, pHigh);
874 histDeltaPion->SetMarkerStyle(20);
875 histDeltaPion->GetXaxis()->SetMoreLogLabels(kTRUE);
876 histDeltaPion->GetXaxis()->SetNoExponent(kTRUE);
877 histDeltaPion->Draw("e p");
878 histDeltaElectron->GetYaxis()->SetTitle(canvTitle.Data());
879 SetReasonableAxisRange(histDeltaElectron->GetXaxis(), mode, pLow, pHigh);
880 histDeltaElectron->SetMarkerStyle(21);
881 histDeltaElectron->Draw("e p same");
882 histDeltaKaon->GetYaxis()->SetTitle(canvTitle.Data());
883 SetReasonableAxisRange(histDeltaKaon->GetXaxis(), mode, pLow, pHigh);
884 histDeltaKaon->SetMarkerStyle(22);
885 histDeltaKaon->Draw("e p same");
886 histDeltaProton->GetYaxis()->SetTitle(canvTitle.Data());
887 SetReasonableAxisRange(histDeltaProton->GetXaxis(), mode, pLow, pHigh);
888 histDeltaProton->SetMarkerStyle(29);
889 histDeltaProton->Draw("e p same");
890 if (plotIdentifiedSpectra) {
891 histMC->GetYaxis()->SetTitle(canvTitle.Data());
892 SetReasonableAxisRange(histMC->GetXaxis(), mode, pLow, pHigh);
893 histMC->SetMarkerStyle(24);
894 histMC->Draw("e p same");
895 }
896
897 TLegend* legend = new TLegend(0.622126, 0.605932, 0.862069, 0.855932);
898 legend->SetBorderSize(0);
899 legend->SetFillColor(0);
900 legend->AddEntry(histDeltaPion, Form("#Delta%s", useDeltaPrime ? "'_{#lower[-0.5]{#pi}}" : "_{#pi}"), "p");
901 legend->AddEntry(histDeltaElectron, Form("#Delta%s", useDeltaPrime ? "'_{#lower[-0.5]{e}}" : "_{e}"), "p");
902 legend->AddEntry(histDeltaKaon, Form("#Delta%s", useDeltaPrime ? "'_{#lower[-0.5]{K}}" : "_{K}"), "p");
903 legend->AddEntry(histDeltaProton, Form("#Delta%s", useDeltaPrime ? "'_{#lower[-0.5]{p}}" : "_{p}"), "p");
904 if (plotIdentifiedSpectra)
905 legend->AddEntry(histMC, identifiedLabels[isMC].Data(), "p");
906 legend->SetEntrySeparation(0.2);
907 legend->Draw();
908
909 ClearTitleFromHistoInCanvas(canv);
910
911 return canv;
912}
913
914
915//____________________________________________________________________________________________________________________
916TCanvas* drawYieldHistos(TString canvName, TString canvTitle, Int_t mode, Double_t pLow, Double_t pHigh,
917 TH1* histDeltaPion, TH1* histDeltaElectron, TH1* histDeltaKaon, TH1* histDeltaProton, TH1* histMC,
918 Bool_t plotIdentifiedSpectra)
919{
920 TCanvas* canv = new TCanvas(canvName.Data(), canvTitle.Data(),100,10,1200,800);
921 canv->SetGridx(1);
922 canv->SetGridy(1);
923 canv->SetLogx(mode == kPMpT);
924 canv->SetLogy(1);
925 histDeltaPion->GetYaxis()->SetRangeUser(histDeltaPion->GetBinContent(histDeltaPion->FindLastBinAbove(0.)) / 10.,
926 histDeltaPion->GetBinContent(histDeltaPion->GetMaximumBin()) * 10.);
927 histDeltaPion->GetYaxis()->SetTitle(canvTitle.Data());
928 SetReasonableAxisRange(histDeltaPion->GetXaxis(), mode, pLow, pHigh);
929 histDeltaPion->SetMarkerStyle(20);
930 histDeltaPion->GetXaxis()->SetMoreLogLabels(kTRUE);
931 histDeltaPion->GetXaxis()->SetNoExponent(kTRUE);
932 histDeltaPion->Draw("e p");
933 histDeltaElectron->GetYaxis()->SetTitle(canvTitle.Data());
934 SetReasonableAxisRange(histDeltaElectron->GetXaxis(), mode, pLow, pHigh);
935 histDeltaElectron->SetMarkerStyle(21);
936 histDeltaElectron->Draw("e p same");
937 histDeltaKaon->GetYaxis()->SetTitle(canvTitle.Data());
938 SetReasonableAxisRange(histDeltaKaon->GetXaxis(), mode, pLow, pHigh);
939 histDeltaKaon->SetMarkerStyle(22);
940 histDeltaKaon->Draw("e p same");
941 histDeltaProton->GetYaxis()->SetTitle(canvTitle.Data());
942 SetReasonableAxisRange(histDeltaProton->GetXaxis(), mode, pLow, pHigh);
943 histDeltaProton->SetMarkerStyle(29);
944 histDeltaProton->Draw("e p same");
945 if (plotIdentifiedSpectra) {
946 histMC->GetYaxis()->SetTitle(canvTitle.Data());
947 SetReasonableAxisRange(histMC->GetXaxis(), mode, pLow, pHigh);
948 histMC->SetMarkerStyle(24);
949 histMC->Draw("e p same");
950 }
951
952 TLegend* legend = new TLegend(0.622126, 0.605932, 0.862069, 0.855932);
953 legend->SetBorderSize(0);
954 legend->SetFillColor(0);
955
956 legend->AddEntry(histDeltaPion, Form("#Delta%s", useDeltaPrime ? "'_{#lower[-0.5]{#pi}}" : "_{#pi}"), "p");
957 legend->AddEntry(histDeltaElectron, Form("#Delta%s", useDeltaPrime ? "'_{#lower[-0.5]{e}}" : "_{e}"), "p");
958 legend->AddEntry(histDeltaKaon, Form("#Delta%s", useDeltaPrime ? "'_{#lower[-0.5]{K}}" : "_{K}"), "p");
959 legend->AddEntry(histDeltaProton, Form("#Delta%s", useDeltaPrime ? "'_{#lower[-0.5]{p}}" : "_{p}"), "p");
960 if (plotIdentifiedSpectra)
961 legend->AddEntry(histMC, identifiedLabels[isMC].Data(), "p");
962 legend->SetEntrySeparation(0.2);
963 legend->Draw();
964
965 ClearTitleFromHistoInCanvas(canv);
966
967 return canv;
968}
969
970
971//____________________________________________________________________________________________________________________
972Int_t doSimultaneousFitRegularised(Int_t nPar, Double_t* gausParams, Double_t* parameterErrorsOut, Double_t* covMatrix,
973 Double_t* stepSize, Double_t* lowParLimits, Double_t* upParLimits, Double_t& reducedChiSquare)
974{
975 AliTPCPIDmathFit* mathFit = AliTPCPIDmathFit::Instance();
976
977 Double_t chiSquare = -999;
978 Int_t ndf = -1;
979
980 AliTPCPIDmathFit::FitFunc_t* multiGaussFitArray = new AliTPCPIDmathFit::FitFunc_t[numSimultaneousFits];
981 multiGaussFitArray[0] = multiGaussFitDeltaPi;
982 multiGaussFitArray[1] = multiGaussFitDeltaKa;
983 multiGaussFitArray[2] = multiGaussFitDeltaPr;
984 multiGaussFitArray[3] = multiGaussFitDeltaEl;
985
986 AliTPCPIDmathFit::FitFunc_t* errorOfFitHistosArray = new AliTPCPIDmathFit::FitFunc_t[numSimultaneousFits];
987 errorOfFitHistosArray[0] = errorOfFitHistosDeltaPi;
988 errorOfFitHistosArray[1] = errorOfFitHistosDeltaKa;
989 errorOfFitHistosArray[2] = errorOfFitHistosDeltaPr;
990 errorOfFitHistosArray[3] = errorOfFitHistosDeltaEl;
991
992 //TODO errorFunction for bin errors of fit histos?
993 Int_t errFlag = mathFit->MinuitFit(multiGaussFitArray, 0x0, nPar, gausParams, parameterErrorsOut, covMatrix,
994 chiSquare, ndf, stepSize, lowParLimits, upParLimits);
995 //Int_t errFlag = mathFit->MinuitFit(multiGaussFitArray, errorOfFitHistosArray, nPar, gausParams, parameterErrorsOut, covMatrix,
996 // chiSquare, ndf, stepSize, lowParLimits, upParLimits);
997
998 std::cout << std::endl;
999
1000 for (Int_t xBin = 0; xBin < mathFit->GetNumXbinsRegularisation(); xBin++) {
1001 std::cout << "x bin " << xBin << ":" << std::endl;
1002
1003 Double_t sumFractions = 0;
1004
1005 for (Int_t parIndex = xBin * mathFit->GetNumParametersPerXbin(); parIndex < (xBin + 1) * mathFit->GetNumParametersPerXbin();
1006 parIndex++) {
1007 Int_t parIndexModulo = parIndex % mathFit->GetNumParametersPerXbin();
1008
1009 // NOTE: Covariance matrix is NOT set. But this doesn't matter since the parameter is fixed anyway, so
1010 // the error from the matrix would be zero.
1011 // parIndexModulo = 4 means muons, parIndexModulo = 3 means electrons, i.e. if parIndexModulo corresponds to muons,
1012 // then parIndexModulo - 1 corresponds to electrons.
1013
1014 // Set electron fraction to value evaluated from a function above some threshold.
1015 // Fixed electron fraction < 0 does this job within the fitting functions
1016 if (parIndexModulo == 3 && gausParams[parIndex] < 0) {
1017 gausParams[parIndex] = GetElectronFraction(-gausParams[parIndex], &gausParams[0]);
1018 parameterErrorsOut[parIndex] = GetElectronFractionError();
1019 }
1020 // Set muon fraction equal to electron fraction (or some modified electron fraction) above some threshold,
1021 // which should be a reasonable approximation:
1022 // Fixed muon fraction < 0 does this job within the fitting functions
1023 else if (parIndexModulo == 4 && gausParams[parIndex] < 0) {
1024 gausParams[parIndex] = GetMuonFractionFromElectronFractionAndPt(-gausParams[parIndex], gausParams[parIndex - 1]);
1025 parameterErrorsOut[parIndex] = parameterErrorsOut[parIndex - 1];
1026 }
1027
1028
1029 std::cout << "par[" << parIndex << "]: " << gausParams[parIndex] << " +- " << parameterErrorsOut[parIndex] << std::endl;
1030
1031 if (parIndexModulo <= 3 || ((muonContamination || takeIntoAccountMuons) && parIndexModulo == 4))
1032 sumFractions += gausParams[parIndex];
1033 }
1034
1035 std::cout << "Sum of fractions" << (muonContamination || takeIntoAccountMuons ? "(including muon contamination)" : "") << ": "
1036 << sumFractions; std::cout << std::endl;
1037 std::cout << std::endl << std::endl;
1038 }
1039
1040 if (errFlag == 0)
1041 std::cout << std::endl << "***Fit operation completed successfully***" << std::endl << std::endl;
1042 else
1043 std::cout << std::endl << "***Fit operation completed, but with errors***" << std::endl << std::endl;
1044
1045 reducedChiSquare = (ndf > 0) ? chiSquare / ndf : -1;
1046
1047 return errFlag;
1048}
1049
1050
1051//____________________________________________________________________________________________________________________
1052Int_t doSimultaneousFit(TH1D** hDelta, Double_t xLow, Double_t xUp, Int_t nPar, Double_t* gausParams, Double_t* parameterErrorsOut,
1053 Double_t* covMatrix, Double_t* stepSize, Double_t* lowParLimits, Double_t* upParLimits, Double_t&
1054 reducedChiSquare)
1055{
1056 AliTPCPIDmathFit* mathFit = AliTPCPIDmathFit::Instance();
1057
1058 Double_t chiSquare = -999;
1059 Int_t ndf = -1;
1060
1061 //TODO:
1062 // Using no error on x (next TODO line) and no errorFunction (next after next TODO line) sometimes gives good results.
1063 // However, it can completely fail for low statistics for the fit histos.
1064 // Using either an error on x or the errorFunction both gives reasonable results, but might be slightly worse results in some cases
1065 // (shifted/distorted data). Maybe: Choose one method - the rest is for systematic errors of this fitting
1066
1067 //TODO The next TODO marks are only relevant for chiSquare, but not for loglikelihood
1068 //TODO Use error in x also -> If reference histos have low statistics, this will be very important
1069
1070 for (Int_t i = 0; i < numSimultaneousFits; i++) {
1071 mathFit->InputData(hDelta[i], 0, i, xLow, xUp, -1., kFALSE);
1072 //mathFit->InputData(hDelta[i], 0, i, xLow, xUp, -1., kTRUE);
1073 }
1074
1075 AliTPCPIDmathFit::FitFunc_t* multiGaussFitArray = new AliTPCPIDmathFit::FitFunc_t[numSimultaneousFits];
1076 multiGaussFitArray[0] = multiGaussFitDeltaPi;
1077 multiGaussFitArray[1] = multiGaussFitDeltaKa;
1078 multiGaussFitArray[2] = multiGaussFitDeltaPr;
1079 multiGaussFitArray[3] = multiGaussFitDeltaEl;
1080
1081 AliTPCPIDmathFit::FitFunc_t* errorOfFitHistosArray = new AliTPCPIDmathFit::FitFunc_t[numSimultaneousFits];
1082 errorOfFitHistosArray[0] = errorOfFitHistosDeltaPi;
1083 errorOfFitHistosArray[1] = errorOfFitHistosDeltaKa;
1084 errorOfFitHistosArray[2] = errorOfFitHistosDeltaPr;
1085 errorOfFitHistosArray[3] = errorOfFitHistosDeltaEl;
1086
1087 //TODO errorFunction for bin errors of fit histos?
1088 Int_t errFlag = mathFit->MinuitFit(multiGaussFitArray, 0x0, nPar, gausParams, parameterErrorsOut, covMatrix,
1089 chiSquare, ndf, stepSize, lowParLimits, upParLimits);
1090 //Int_t errFlag = mathFit->MinuitFit(multiGaussFitArray, errorOfFitHistosArray, nPar, gausParams, parameterErrorsOut, covMatrix,
1091 // chiSquare, ndf, stepSize, lowParLimits, upParLimits);
1092
1093 std::cout << std::endl;
1094
1095 // If the electron fraction is fixed, evaluate the error of the extrapolation of the fixed value
1096 if (TMath::Abs(lowParLimits[3] - upParLimits[3]) < epsilon) {
1097 // NOTE: Covariance matrix is NOT set. But this doesn't matter since the parameter is fixed anyway, so
1098 // the error from the matrix would be zero
1099 parameterErrorsOut[3] = GetElectronFractionError();
1100 }
1101
1102 // Set muon fraction equal to electron fraction (or some modified electron fraction) above some threshold,
1103 // which should be a reasonable approximation:
1104 // Fixed muon fraction < 0 does this job within the fitting functions
1105 if (gausParams[4] < 0 ) {
1106 // NOTE: Covariance matrix is NOT set. But this doesn't matter since the parameter is fixed anyway, so
1107 // the error from the matrix would be zero
1108 gausParams[4] = GetMuonFractionFromElectronFractionAndPt(-gausParams[4], gausParams[3]);
1109 parameterErrorsOut[4] = parameterErrorsOut[3];
1110 }
1111
1112 Double_t sumFractions = 0;
1113 for (Int_t parIndex = 0; parIndex < nPar; parIndex++) {
1114 std::cout << "par[" << parIndex << "]: " << gausParams[parIndex] << " +- " << parameterErrorsOut[parIndex] << std::endl;
1115 }
1116 sumFractions = gausParams[0] + gausParams[1] + gausParams[2] + gausParams[3];
1117 // In case of muon contamination add muon fraction also
1118 if (muonContamination || takeIntoAccountMuons) {
1119 sumFractions += gausParams[4];
1120 }
1121
1122 std::cout << "Sum of fractions" << (muonContamination || takeIntoAccountMuons ? "(including muon contamination)" : "") << ": " << sumFractions; std::cout << std::endl;
1123
1124 if (errFlag == 0)
1125 std::cout << std::endl << "***Fit operation completed successfully***" << std::endl << std::endl;
1126 else
1127 std::cout << std::endl << "***Fit operation completed, but with errors***" << std::endl << std::endl;
1128
1129 reducedChiSquare = (ndf > 0) ? chiSquare / ndf : -1;
1130
1131 return errFlag;
1132}
1133
1134
1135//____________________________________________________________________________________________________________________
1136Int_t doFit(TH1D* hDelta, Double_t xLow, Double_t xUp, Int_t nPar, Double_t* gausParams, Double_t* parameterErrorsOut, Double_t* covMatrix,
1137 Double_t* stepSize, Double_t* lowParLimits, Double_t* upParLimits, TF1* totalDeltaSpecies, Double_t& reducedChiSquare)
1138{
1139 AliTPCPIDmathFit* mathFit = AliTPCPIDmathFit::Instance();
1140
1141 Double_t chiSquare = -999;
1142 Int_t ndf = -1;
1143
1144 //TODO:
1145 // Using no error on x (next TODO line) and no errorFunction (next after next TODO line) sometimes gives good results.
1146 // However, it can completely fail for low statistics for the fit histos.
1147 // Using either an error on x or the errorFunction both gives reasonable results, but might be slightly worse results in some cases
1148 // (shifted/distorted data). Maybe: Choose one method - the rest is for systematic errors of this fitting
1149
1150 //TODO The next TODO marks are only relevant for chiSquare, but not for loglikelihood
1151 //TODO Use error in x also -> If reference histos have low statistics, this will be very important
1152 mathFit->InputData(hDelta, 0, 0, xLow, xUp, -1., kFALSE);
1153 //mathFit->InputData(hDelta, 0, 0, xLow, xUp, -1., kTRUE);
1154
1155 AliTPCPIDmathFit::FitFunc_t* multiGaussFitArray = new AliTPCPIDmathFit::FitFunc_t[1];
1156 multiGaussFitArray[0] = multiGaussFit;
1157
1158 AliTPCPIDmathFit::FitFunc_t* errorOfFitHistosArray = new AliTPCPIDmathFit::FitFunc_t[1];
1159 errorOfFitHistosArray[0] = errorOfFitHistos;
1160
1161 //TODO errorFunction for bin errors of fit histos?
1162 Int_t errFlag = mathFit->MinuitFit(multiGaussFitArray, 0x0, nPar, gausParams, parameterErrorsOut, covMatrix,
1163 chiSquare, ndf, stepSize, lowParLimits, upParLimits);
1164 //Int_t errFlag = mathFit->MinuitFit(multiGaussFitArray, errorOfFitHistosArray, nPar, gausParams, parameterErrorsOut, covMatrix,
1165 // chiSquare, ndf, stepSize, lowParLimits, upParLimits);
1166
1167 // If the electron fraction is fixed, evaluate the error of the extrapolation of the fixed value
1168 if (TMath::Abs(lowParLimits[3] - upParLimits[3]) < epsilon) {
1169 // NOTE: Covariance matrix is NOT set. But this doesn't matter since the parameter is fixed anyway, so
1170 // the error from the matrix would be zero
1171 parameterErrorsOut[3] = GetElectronFractionError();
1172 }
1173
1174 // Set muon fraction equal to electron fraction (or some modified electron fraction) above some threshold, which should be a reasonable approximation:
1175 // Fixed muon fraction < 0 does this job within the fitting functions
1176 if (gausParams[4] < 0 ) {
1177 // NOTE: Covariance matrix is NOT set. But this doesn't matter since the parameter is fixed anyway, so
1178 // the error from the matrix would be zero
1179 gausParams[4] = GetMuonFractionFromElectronFractionAndPt(-gausParams[4], gausParams[3]);
1180 parameterErrorsOut[4] = parameterErrorsOut[3];
1181 }
1182
1183 Double_t sumFractions = 0;
1184 for (Int_t parIndex = 0; parIndex < nPar; parIndex++) {
1185 std::cout << totalDeltaSpecies->GetParName(parIndex) << ": " << gausParams[parIndex] << " +- " << parameterErrorsOut[parIndex] << std::endl;
1186 }
1187 sumFractions = gausParams[0] + gausParams[1] + gausParams[2] + gausParams[3];
1188 // In case of muon contamination add muon fraction also
1189 if (muonContamination || takeIntoAccountMuons) {
1190 sumFractions += gausParams[4];
1191 }
1192
1193 std::cout << "Sum of fractions" << (muonContamination || takeIntoAccountMuons ? "(including muon contamination)" : "") << ": " << sumFractions;
1194 std::cout << std::endl;
1195
1196 if (errFlag == 0)
1197 std::cout << std::endl << "***Fit operation completed successfully***" << std::endl << std::endl;
1198 else
1199 std::cout << std::endl << "***Fit operation completed, but with errors***" << std::endl << std::endl;
1200
1201 for (Int_t parIndex = 0; parIndex < nPar; parIndex++) {
1202 totalDeltaSpecies->SetParameter(parIndex, gausParams[parIndex]);
1203 totalDeltaSpecies->SetParError(parIndex, parameterErrorsOut[parIndex]);
1204 }
1205
1206 reducedChiSquare = (ndf > 0) ? chiSquare / ndf : -1;
1207
1208 return errFlag;
1209}
1210
1211
1212//____________________________________________________________________________________________________________________
1213Double_t setFractionsAndYields(Int_t slice, Double_t inverseBinWidth, Double_t binWidthFitHisto, Int_t species, Double_t* parametersOut,
1214 Double_t* parameterErrorsOut, TH1* hFractionSpecies, TH1* hFractionPionsDeltaSpecies,
1215 TH1* hFractionElectronsDeltaSpecies, TH1* hFractionKaonsDeltaSpecies, TH1* hFractionProtonsDeltaSpecies,
1216 TH1* hFractionMuonsDeltaSpecies, TH1* hYieldSpecies, TH1* hYieldPionsDeltaSpecies,
1217 TH1* hYieldElectronsDeltaSpecies, TH1* hYieldKaonsDeltaSpecies, TH1* hYieldProtonsDeltaSpecies,
1218 TH1* hYieldMuonsDeltaSpecies,
1219 Bool_t normaliseFractions = kFALSE)
1220{
1221 // Set fraction and yields in corresponding histograms. If normaliseFractions is kTRUE, the fractions will be normalised to unity
1222 // and the normalisation factor will be returned (i.e. 1./sumFraction)
1223
1224 Double_t normalisationFactor = 1.0;
1225
1226 // Since a log likelihood fit is anyway used, the normalisation should give a factor close to unity
1227 if (normaliseFractions) {
1228 Double_t sumFractions = parametersOut[0] + (muonContamination ? parametersOut[3] : 0) + parametersOut[1] + parametersOut[2] +
1229 parametersOut[3] + (takeIntoAccountMuons ? parametersOut[4] : 0.);
1230 if (sumFractions > 0) {
1231 normalisationFactor = 1./sumFractions;
1232 for (Int_t i = 0; i < 5; i++) {
1233 parametersOut[i] *= normalisationFactor;
1234
1235 // Do not introduce an error for the normalisation, i.e. just scale parameters and fractions with the same factor which is
1236 // assumed to be exact.
1237 // Note that correlations should already be included in the parameterError
1238 parameterErrorsOut[i] *= normalisationFactor;
1239 }
1240 }
1241 }
1242
1243 Double_t sumOfParticles = inverseBinWidth * parametersOut[5] / binWidthFitHisto; // Divide by binWidthFitHisto since parametersOut includes this width
1244
1245 if (species == kPi) {
1246 hFractionSpecies->SetBinContent(slice + 1, (parametersOut[0]+(muonContamination ? parametersOut[3] : 0)));
1247 hFractionSpecies->SetBinError(slice + 1, parameterErrorsOut[0]);
1248 }
1249 else if (species == kEl) {
1250 hFractionSpecies->SetBinContent(slice + 1, parametersOut[3]);
1251 hFractionSpecies->SetBinError(slice + 1, parameterErrorsOut[3]);
1252 }
1253 else if (species == kKa) {
1254 hFractionSpecies->SetBinContent(slice + 1, parametersOut[1]);
1255 hFractionSpecies->SetBinError(slice + 1, parameterErrorsOut[1]);
1256 }
1257 else if (species == kPr) {
1258 hFractionSpecies->SetBinContent(slice + 1, parametersOut[2]);
1259 hFractionSpecies->SetBinError(slice + 1, parameterErrorsOut[2]);
1260 }
1261 else if (species == kMu) {
1262 if (takeIntoAccountMuons) {
1263 hFractionSpecies->SetBinContent(slice + 1, parametersOut[4]);
1264 hFractionSpecies->SetBinError(slice + 1, parameterErrorsOut[4]);
1265
1266 hYieldSpecies->SetBinContent(slice + 1, sumOfParticles * hFractionSpecies->GetBinContent(slice + 1));
1267 hYieldSpecies->SetBinError(slice + 1, sumOfParticles * hFractionSpecies->GetBinError(slice + 1));
1268 }
1269
1270 // Only set these histos for muons. The DeltaSpecies histos for muons will be set together with all other species
1271 return normalisationFactor;
1272 }
1273
1274 hFractionPionsDeltaSpecies->SetBinContent(slice + 1, (parametersOut[0]+(muonContamination ? parametersOut[3] : 0)));
1275 hFractionPionsDeltaSpecies->SetBinError(slice + 1, parameterErrorsOut[0]);//TODO What about error of parOut[3]?
1276 hFractionElectronsDeltaSpecies->SetBinContent(slice + 1, parametersOut[3]);
1277 hFractionElectronsDeltaSpecies->SetBinError(slice + 1, parameterErrorsOut[3]);
1278 hFractionKaonsDeltaSpecies->SetBinContent(slice + 1, parametersOut[1]);
1279 hFractionKaonsDeltaSpecies->SetBinError(slice + 1, parameterErrorsOut[1]);
1280 hFractionProtonsDeltaSpecies->SetBinContent(slice + 1, parametersOut[2]);
1281 hFractionProtonsDeltaSpecies->SetBinError(slice + 1, parameterErrorsOut[2]);
1282 if (takeIntoAccountMuons) {
1283 hFractionMuonsDeltaSpecies->SetBinContent(slice + 1, parametersOut[4]);
1284 hFractionMuonsDeltaSpecies->SetBinError(slice + 1, parameterErrorsOut[4]);
1285 }
1286
1287 hYieldSpecies->SetBinContent(slice + 1, sumOfParticles * hFractionSpecies->GetBinContent(slice + 1));
1288 hYieldSpecies->SetBinError(slice + 1, sumOfParticles * hFractionSpecies->GetBinError(slice + 1));
1289
1290 hYieldPionsDeltaSpecies->SetBinContent(slice + 1, sumOfParticles * hFractionPionsDeltaSpecies->GetBinContent(slice + 1));
1291 hYieldPionsDeltaSpecies->SetBinError(slice + 1, sumOfParticles * hFractionPionsDeltaSpecies->GetBinError(slice + 1));
1292 hYieldElectronsDeltaSpecies->SetBinContent(slice + 1, sumOfParticles * hFractionElectronsDeltaSpecies->GetBinContent(slice + 1));
1293 hYieldElectronsDeltaSpecies->SetBinError(slice + 1, sumOfParticles * hFractionElectronsDeltaSpecies->GetBinError(slice + 1));
1294 hYieldKaonsDeltaSpecies->SetBinContent(slice + 1, sumOfParticles * hFractionKaonsDeltaSpecies->GetBinContent(slice + 1));
1295 hYieldKaonsDeltaSpecies->SetBinError(slice + 1, sumOfParticles * hFractionKaonsDeltaSpecies->GetBinError(slice + 1));
1296 hYieldProtonsDeltaSpecies->SetBinContent(slice + 1, sumOfParticles * hFractionProtonsDeltaSpecies->GetBinContent(slice + 1));
1297 hYieldProtonsDeltaSpecies->SetBinError(slice + 1, sumOfParticles * hFractionProtonsDeltaSpecies->GetBinError(slice + 1));
1298 if (takeIntoAccountMuons) {
1299 hYieldMuonsDeltaSpecies->SetBinContent(slice + 1, sumOfParticles * hFractionMuonsDeltaSpecies->GetBinContent(slice + 1));
1300 hYieldMuonsDeltaSpecies->SetBinError(slice + 1, sumOfParticles * hFractionMuonsDeltaSpecies->GetBinError(slice + 1));
1301 }
1302
1303 return normalisationFactor;
1304}
1305
1306//____________________________________________________________________________________________________________________
1307Int_t PID(TString fileName, Double_t deta, Double_t pLow, Double_t pHigh, Bool_t isMCdataSet, Int_t fitMethod,
1308 Int_t muonFractionHandlingParameter, //0 = no muons, 1 = muonFrac=elFrac,
1309 //2(3) = muonFrac/elFrac tuned on MC for StandardTrackCuts(HybridTrackCuts)
1310 Bool_t useIdentifiedGeneratedSpectra, Bool_t plotIdentifiedSpectra, Int_t mode/*0=pT,1=z,2=xi*/,
1311 Int_t chargeMode /*kNegCharge = -1, kAllCharged = 0, kPosCharge = 1*/,
1312 Double_t lowerCentrality /*= -2*/, Double_t upperCentrality /*= -2*/,
1313 Double_t lowerJetPt /*= -1*/ , Double_t upperJetPt/* = -1*/,
1314 Int_t rebin/* = 1 -> DON'T USE FOR PT (will not work since binsPt will and should be used!)*/,
1315 Int_t rebinDeltaPrime/* = 1*/,
1316 TString listName /* = "bhess_PID"*/,
1317 Bool_t useLogLikelihood /*= kTRUE*/, Bool_t useWeightsForLogLikelihood /*= kFALSE*/,
1318 Int_t regularisation /*= 0*/,
1319 Double_t regularisationFactor /*= 1*/,
1320 TString filePathNameFileWithInititalFractions /*= ""*/,
1321 TString* filePathNameResults /*= 0x0*/)
1322{
1323 // Do all the fitting
1324
1325 isMC = isMCdataSet;
1326
1327 muonFractionHandling = muonFractionHandlingParameter;
1328
1329 Int_t genAxis = useDeltaPrime ? kPidGenDeltaPrime : 1000/*kPidGenDelta*/;
1330 if (!useDeltaPrime) {
1331 std::cout << "ERROR: delta plots no longer available!" << std::endl;
1332 return -1;
1333 }
1334
1335 if (listName == "") {
1336 listName = fileName;
1337 listName.Replace(0, listName.Last('/') + 1, "");
1338 listName.ReplaceAll(".root", "");
1339 }
1340
1341
1342 if (rebin > 1 && mode == kPMpT) {
1343 std::cout << "ERROR: Requested re-binning of pT-axis! Since binsPt will be used, re-binning the data histo will lead to "
1344 << "unforeseen consequences!" << std::endl;
1345 return -1;
1346 }
1347
1348 Int_t pSliceLow = -1;
1349 Int_t pSliceHigh = -1;
1350
1351 Int_t axisForMode = kPidPt;
1352 Int_t axisGenForMode = kPidGenPt;
1353
1354 std::cout << "Fitting \"" << fileName.Data() << "\" with settings:" << std::endl;
1355
1356 std::cout << "Minimisation strategy: " << minimisationStrategy.Data() << std::endl;
1357 if (useLogLikelihood)
1358 std::cout << "Binned loglikelihood fit" << (useWeightsForLogLikelihood ? " (weighted)" : "") << std::endl;
1359 else
1360 std::cout << "ChiSquare fit" << std::endl;
1361 std::cout << "Processing mode: ";
1362 if (mode == kPMpT)
1363 std::cout << "pT" << std::endl;
1364 else if (mode == kPMz) {
1365 std::cout << "z" << std::endl;
1366 axisForMode = kPidZ;
1367 axisGenForMode = kPidGenZ;
1368 }
1369 else if (mode == kPMxi) {
1370 std::cout << "xi" << std::endl;
1371 axisForMode = kPidXi;
1372 axisGenForMode = kPidGenXi;
1373 }
1374 else {
1375 std::cout << "Unknown -> ERROR" << std::endl;
1376 return -1;
1377 }
1378
1379 std::cout << "Charge selection: ";
1380 if (chargeMode == kAllCharged)
1381 std::cout << "All charged particles" << std::endl;
1382 else if (chargeMode == kNegCharge)
1383 std::cout << "Negative particles only" << std::endl;
1384 else if (chargeMode == kPosCharge)
1385 std::cout << "Positive particles only" << std::endl;
1386 else {
1387 std::cout << "Unknown -> ERROR" << std::endl;
1388 return -1;
1389 }
1390
1391 const Bool_t restrictCharge = (chargeMode != kAllCharged);
1392
1393 if (regularisation > 0)
1394 std::cout << "Regularisation with +-" << regularisation << " bins and factor " << regularisationFactor << " for penalty term."
1395 << std::endl;
1396 else
1397 std::cout << "No regularisation" << std::endl;
1398
1399 std::cout << "Assumption on muon fraction: ";
1400 if (muonFractionHandlingParameter >= 0 && muonFractionHandlingParameter < kNumHandlings)
1401 std::cout << muonFractionHandlingShortName[muonFractionHandlingParameter].Data() << std::endl;
1402 /*if (muonFractionHandlingParameter == kNoMuons)
1403 std::cout << "Identical zero" << std::endl;
1404 else if (muonFractionHandlingParameter == kMuonFracEqualElFrac)
1405 std::cout << "Equal electron fraction" << std::endl;
1406 else if (muonFractionHandlingParameter == kMuonFracOverElFracTunedOnMCStandardTrackCuts)
1407 std::cout << "Ratio to electron fraction tuned on MC for standard track cuts" << std::endl;
1408 else if (muonFractionHandlingParameter == kMuonFracOverElFracTunedOnMCHybridTrackCuts)
1409 std::cout << "Ratio to electron fraction tuned on MC for hybrid track cuts" << std::endl;
1410 else if (muonFractionHandlingParameter == kMuonFracOverElFracTunedOnMCHybridTrackCutsJets)
1411 std::cout << "Ratio to electron fraction tuned on MC for hybrid track cuts for jet particles" << std::endl;
1412 else if (muonFractionHandlingParameter == kMuonFracOverElFracTunedOnMCHybridTrackCutsJets)
1413 std::cout << "Ratio to electron fraction tuned on MC for hybrid track cuts for jet particles" << std::endl;*/
1414 else {
1415 std::cout << "Unknown -> ERROR" << std::endl;
1416 return -1;
1417 }
1418
1419 if (mode == kPMpT) {
1420 Int_t index = 0;
1421 while (pLow >= binsPt[index] && index < nPtBins)
1422 index++;
1423 pSliceLow = index - 1;
1424
1425 index = 0;
1426 while (pHigh > binsPt[index] && index < nPtBins)
1427 index++;
1428 pSliceHigh = index - 1;
1429
1430 Int_t numMomIntervals = pSliceHigh - pSliceLow + 1;
1431
1432 if (numMomIntervals <= 0 || pSliceLow < 0 || pSliceHigh > nPtBins) {
1433 std::cout << "Wrong choice of limits pLow/pHigh!" << std::endl;
1434 return -1;
1435 }
1436
1437 pLow = binsPt[pSliceLow];
1438 pHigh = binsPt[pSliceHigh + 1]; // need upper edge, but binsPt holds lower edge
1439 std::cout << "pLow/pHigh: ";
1440 std::cout << pLow << " / " << pHigh << std::endl;
1441 }
1442
1443 Bool_t initialiseWithFractionsFromFile = kFALSE;
1444 TFile* fInitialFractions = 0x0;
1445 TH1 *hInitFracEl = 0x0, *hInitFracKa = 0x0, *hInitFracPi = 0x0, *hInitFracMu = 0x0, *hInitFracPr = 0x0;
1446
1447 if (filePathNameFileWithInititalFractions != "") {
1448 initialiseWithFractionsFromFile = kTRUE;
1449
1450 std::cout << "Initialising fractions from file: " << filePathNameFileWithInititalFractions.Data() << std::endl;
1451 }
1452 else
1453 std::cout << "Not initialising fractions from file" << std::endl;
1454
1455 if (initialiseWithFractionsFromFile) {
1456 fInitialFractions = TFile::Open(filePathNameFileWithInititalFractions.Data());
1457 if (!fInitialFractions) {
1458 std::cout << std::endl;
1459 std::cout << "Failed to open file with initial fractions \"" << filePathNameFileWithInititalFractions.Data() << "\"!"
1460 << std::endl;
1461 return -1;
1462 }
1463
1464 hInitFracEl = (TH1*)fInitialFractions->Get("hFractionElectrons");
1465 hInitFracKa = (TH1*)fInitialFractions->Get("hFractionKaons");
1466 hInitFracPi = (TH1*)fInitialFractions->Get("hFractionPions");
1467 hInitFracMu = (TH1*)fInitialFractions->Get("hFractionMuons");
1468 hInitFracPr = (TH1*)fInitialFractions->Get("hFractionProtons");
1469
1470 if (!hInitFracEl || ! hInitFracKa || ! hInitFracPi || ! hInitFracMu || ! hInitFracPr) {
1471 std::cout << std::endl;
1472 std::cout << "Failed to load initial fractions from file \"" << filePathNameFileWithInititalFractions.Data() << "\"!"
1473 << std::endl;
1474
1475 fInitialFractions->Close();
1476 return -1;
1477 }
1478 }
1479
1480
1481
1482 TObjArray* histList = 0x0;
1483
1484 TFile* f = TFile::Open(fileName.Data());
1485 if (!f) {
1486 std::cout << std::endl;
1487 std::cout << "Failed to open file \"" << fileName.Data() << "\"!" << std::endl;
1488 return -1;
1489 }
1490
1491 //TString listName = fileName;
1492 //listName = listName.ReplaceAll(".root", "");
1493 //listName = listName.Remove(1, listName.Last('/') + 1);
1494 histList = (TObjArray*)(f->Get(listName.Data()));
1495 if (!histList) {
1496 std::cout << std::endl;
1497 std::cout << "Failed to load list \"" << listName.Data() << "\"!" << std::endl;
1498 return -1;
1499 }
1500
1501 // Extract the data histogram
1502 THnSparse* hPIDdata = dynamic_cast<THnSparse*>(histList->FindObject("hPIDdataAll"));
1503 if (!hPIDdata) {
1504 std::cout << std::endl;
1505 std::cout << "Failed to load data histo!" << std::endl;
1506 return -1;
1507 }
1508
1509 // If desired, rebin considered axis
1510 if (rebin > 1 || rebinDeltaPrime > 1) {
1511 const Int_t nDimensions = hPIDdata->GetNdimensions();
1512 Int_t rebinFactor[nDimensions];
1513
1514 for (Int_t dim = 0; dim < nDimensions; dim++) {
1515 if (dim == axisForMode && rebin > 1)
1516 rebinFactor[dim] = rebin;
1517 else if (dim == kPidDeltaPrime && rebinDeltaPrime > 1)
1518 rebinFactor[dim] = rebinDeltaPrime;
1519 else
1520 rebinFactor[dim] = 1;
1521 }
1522
1523 THnSparse* temp = hPIDdata->Rebin(&rebinFactor[0]);
1524 hPIDdata->Reset();
1525 hPIDdata = temp;
1526 }
1527
1528 // Set proper errors, if not yet calculated
1529 if (!hPIDdata->GetCalculateErrors()) {
1530 std::cout << "Re-calculating errors of " << hPIDdata->GetName() << "..." << std::endl;
1531 hPIDdata->Sumw2();
1532 Long64_t nBinsTHnSparse = hPIDdata->GetNbins();
1533 Double_t binContent = 0;
1534
1535 for (Long64_t bin = 0; bin < nBinsTHnSparse; bin++) {
1536 binContent = hPIDdata->GetBinContent(bin);
1537 hPIDdata->SetBinError(bin, TMath::Sqrt(binContent));
1538 }
1539 }
1540
1541
1542 // If desired, restrict centrality axis
1543 Int_t lowerCentralityBinLimit = -1;
1544 Int_t upperCentralityBinLimit = -1;
1545 Bool_t restrictCentralityAxis = kFALSE;
1546 Double_t actualLowerCentrality = -1.;
1547 Double_t actualUpperCentrality = -1.;
1548
1549 if (lowerCentrality >= -1 && upperCentrality >= -1) {
1550 // Add subtract a very small number to avoid problems with values right on the border between to bins
1551 lowerCentralityBinLimit = hPIDdata->GetAxis(kPidCentrality)->FindBin(lowerCentrality + 0.001);
1552 upperCentralityBinLimit = hPIDdata->GetAxis(kPidCentrality)->FindBin(upperCentrality - 0.001);
1553
1554 // Check if the values look reasonable
1555 if (lowerCentralityBinLimit <= upperCentralityBinLimit && lowerCentralityBinLimit >= 1
1556 && upperCentralityBinLimit <= hPIDdata->GetAxis(kPidCentrality)->GetNbins()) {
1557 actualLowerCentrality = hPIDdata->GetAxis(kPidCentrality)->GetBinLowEdge(lowerCentralityBinLimit);
1558 actualUpperCentrality = hPIDdata->GetAxis(kPidCentrality)->GetBinUpEdge(upperCentralityBinLimit);
1559
1560 restrictCentralityAxis = kTRUE;
1561 }
1562 else {
1563 std::cout << std::endl;
1564 std::cout << "Requested centrality range out of limits or upper and lower limit are switched!" << std::endl;
1565 return -1;
1566 }
1567 }
1568
1569 std::cout << "centrality: ";
1570 if (restrictCentralityAxis) {
1571 std::cout << actualLowerCentrality << " - " << actualUpperCentrality << std::endl;
1572 }
1573 else {
1574 std::cout << "All" << std::endl;
1575 }
1576
1577 if (restrictCentralityAxis) {
1578 hPIDdata->GetAxis(kPidCentrality)->SetRange(lowerCentralityBinLimit, upperCentralityBinLimit);
1579 }
1580
1581
1582
1583 // If desired, restrict jetPt axis
1584 Int_t lowerJetPtBinLimit = -1;
1585 Int_t upperJetPtBinLimit = -1;
1586 Bool_t restrictJetPtAxis = kFALSE;
1587 Double_t actualLowerJetPt = -1.;
1588 Double_t actualUpperJetPt = -1.;
1589
1590 if (lowerJetPt >= 0 && upperJetPt >= 0) {
1591 // Add subtract a very small number to avoid problems with values right on the border between to bins
1592 lowerJetPtBinLimit = hPIDdata->GetAxis(kPidJetPt)->FindBin(lowerJetPt + 0.001);
1593 upperJetPtBinLimit = hPIDdata->GetAxis(kPidJetPt)->FindBin(upperJetPt - 0.001);
1594
1595 // Check if the values look reasonable
1596 if (lowerJetPtBinLimit <= upperJetPtBinLimit && lowerJetPtBinLimit >= 1 && upperJetPtBinLimit <= hPIDdata->GetAxis(kPidJetPt)->GetNbins()) {
1597 actualLowerJetPt = hPIDdata->GetAxis(kPidJetPt)->GetBinLowEdge(lowerJetPtBinLimit);
1598 actualUpperJetPt = hPIDdata->GetAxis(kPidJetPt)->GetBinUpEdge(upperJetPtBinLimit);
1599
1600 restrictJetPtAxis = kTRUE;
1601 }
1602 else {
1603 std::cout << std::endl;
1604 std::cout << "Requested jet pT range out of limits or upper and lower limit are switched!" << std::endl;
1605 return -1;
1606 }
1607 }
1608
1609 std::cout << "jet pT: ";
1610 if (restrictJetPtAxis) {
1611 std::cout << actualLowerJetPt << " - " << actualUpperJetPt << std::endl;
1612 }
1613 else {
1614 std::cout << "All" << std::endl;
1615 }
1616
1617 if (restrictJetPtAxis) {
1618 hPIDdata->GetAxis(kPidJetPt)->SetRange(lowerJetPtBinLimit, upperJetPtBinLimit);
1619 }
1620
1621
1622 // If desired, restrict charge axis
1623 const Int_t indexChargeAxisData = GetAxisByTitle(hPIDdata, "Charge (e_{0})");
1624 if (indexChargeAxisData < 0 && restrictCharge) {
1625 std::cout << "Error: Charge axis not found for data histogram!" << std::endl;
1626 return -1;
1627 }
1628 Int_t lowerChargeBinLimitData = -1;
1629 Int_t upperChargeBinLimitData = -2;
1630 Double_t actualLowerChargeData = -999;
1631 Double_t actualUpperChargeData = -999;
1632
1633 if (restrictCharge) {
1634 // Add subtract a very small number to avoid problems with values right on the border between to bins
1635 if (chargeMode == kNegCharge) {
1636 lowerChargeBinLimitData = hPIDdata->GetAxis(indexChargeAxisData)->FindBin(-1. + 0.001);
1637 upperChargeBinLimitData = hPIDdata->GetAxis(indexChargeAxisData)->FindBin(0. - 0.001);
1638 }
1639 else if (chargeMode == kPosCharge) {
1640 lowerChargeBinLimitData = hPIDdata->GetAxis(indexChargeAxisData)->FindBin(0. + 0.001);
1641 upperChargeBinLimitData = hPIDdata->GetAxis(indexChargeAxisData)->FindBin(1. - 0.001);
1642 }
1643
1644 // Check if the values look reasonable
1645 if (lowerChargeBinLimitData <= upperChargeBinLimitData && lowerChargeBinLimitData >= 1
1646 && upperChargeBinLimitData <= hPIDdata->GetAxis(indexChargeAxisData)->GetNbins()) {
1647 actualLowerChargeData = hPIDdata->GetAxis(indexChargeAxisData)->GetBinLowEdge(lowerChargeBinLimitData);
1648 actualUpperChargeData = hPIDdata->GetAxis(indexChargeAxisData)->GetBinUpEdge(upperChargeBinLimitData);
1649
1650 std::cout << "Charge range data: " << actualLowerChargeData << " - " << actualUpperChargeData << std::endl;
1651 }
1652 else {
1653 std::cout << std::endl;
1654 std::cout << "Requested charge range out of limits or upper and lower limit are switched!" << std::endl;
1655 return -1;
1656 }
1657
1658 hPIDdata->GetAxis(indexChargeAxisData)->SetRange(lowerChargeBinLimitData, upperChargeBinLimitData);
1659 }
1660
1661 std::cout << std::endl;
1662
1663
1664
1665 // Open file in which all the projections (= intermediate results) will be saved
1666 TString saveInterFName = fileName;
1667 TString chargeString = "";
1668 if (chargeMode == kPosCharge)
1669 chargeString = "_posCharge";
1670 else if (chargeMode == kNegCharge)
1671 chargeString = "_negCharge";
1672
1673 saveInterFName = Form("%s_Projections_%s_%d_%s%s%s%s%s.root", saveInterFName.ReplaceAll(".root", "").Data(),
1674 modeShortName[mode].Data(),
1675 fitMethod, muonFractionHandlingShortName[muonFractionHandlingParameter].Data(),
1676 useIdentifiedGeneratedSpectra ? "_idSpectra" : "",
1677 restrictCentralityAxis ? Form("_centrality%.0f_%.0f", actualLowerCentrality, actualUpperCentrality) : "",
1678 restrictJetPtAxis ? Form("_jetPt%.1f_%.1f", actualLowerJetPt, actualUpperJetPt) : "",
1679 chargeString.Data());
1680 TFile *saveInterF = TFile::Open(saveInterFName.Data(), "RECREATE");
1681 saveInterF->cd();
1682
1683 // TH1 hist with number of processed events
1684 Double_t numEvents = -1;
1685 TH1* hNumEvents = dynamic_cast<TH1*>(histList->FindObject("fhEventsProcessed"));
1686 if (!hNumEvents) {
1687 std::cout << std::endl;
1688 std::cout << "Histo with number of processed events not found! Yields will NOT be normalised to this number!" << std::endl
1689 << std::endl;
1690 }
1691 else {
1692 numEvents = restrictCentralityAxis ? hNumEvents->Integral(lowerCentralityBinLimit, upperCentralityBinLimit) :
1693 hNumEvents->Integral();
1694
1695 if (numEvents <= 0) {
1696 numEvents = -1;
1697 std::cout << std::endl;
1698 std::cout << "Number of processed events < 1 in selected range! Yields will NOT be normalised to this number!"
1699 << std::endl << std::endl;
1700 }
1701 }
1702
1703
1704 // TH1D hist with total yield per pT bin (-> project to arbitrary selectSpecies to avoid multiple counting)
1705 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(1, 1);
1706 TH1D* hYieldPt = hPIDdata->Projection(axisForMode, "e");
1707 hYieldPt->SetName(Form("hYield%s", modeShortName[mode].Data()));
1708 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(0, -1);
1709
1710
1711 // Fill \Delta\species histograms for each momentum slice
1712 Int_t nBins = hPIDdata->GetAxis(dataAxis)->GetNbins();
1713 Double_t xLow = hPIDdata->GetAxis(dataAxis)->GetXmin();
1714 Double_t xUp = hPIDdata->GetAxis(dataAxis)->GetXmax();
1715
1716 const Int_t numSlices = (mode == kPMpT) ? nPtBins : hPIDdata->GetAxis(axisForMode)->GetNbins();
1717
1718 TH1D* hDeltaPi[numSlices];
1719 TH1D* hDeltaEl[numSlices];
1720 TH1D* hDeltaKa[numSlices];
1721 TH1D* hDeltaPr[numSlices];
1722
1723 TH1D* hDeltaPiFitQA[numSlices];
1724 TH1D* hDeltaElFitQA[numSlices];
1725 TH1D* hDeltaKaFitQA[numSlices];
1726 TH1D* hDeltaPrFitQA[numSlices];
1727
1728 const Int_t nMCbins = 5;
1729 TH1D* hDeltaPiMC[numSlices][nMCbins];
1730 TH1D* hDeltaElMC[numSlices][nMCbins];
1731 TH1D* hDeltaKaMC[numSlices][nMCbins];
1732 TH1D* hDeltaPrMC[numSlices][nMCbins];
1733
1734
1735 TH2D* h2Delta[4];
1736 TH2D* h2DeltaMC[4][nMCbins];
1737
1738 for (Int_t i = 0; i < 4; i++) {
1739 TString speciesLabel = hPIDdata->GetAxis(kPidSelectSpecies)->GetBinLabel(i + 1);
1740
1741 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(i + 1, i + 1);
1742 h2Delta[i] = hPIDdata->Projection(dataAxis, axisForMode, "e");
1743 h2Delta[i]->SetName(Form("h2Delta_%s", speciesLabel.Data()));
1744 h2Delta[i]->GetXaxis()->SetTitle(hPIDdata->GetAxis(axisForMode)->GetTitle());
1745 h2Delta[i]->GetYaxis()->SetTitle(Form("#Delta%s_{%s} = dE/dx %s <dE/dx>_{%s} (arb. units)", useDeltaPrime ? "'" : "", speciesLabel.Data(),
1746 useDeltaPrime ? "/" : "-", speciesLabel.Data()));
1747
1748 for (Int_t species = 0; species < nMCbins; species++) {
1749 hPIDdata->GetAxis(kPidMCpid)->SetRange(species + 1, species + 1); // Select MC species
1750 h2DeltaMC[i][species] = hPIDdata->Projection(dataAxis, axisGenForMode, "e");
1751 h2DeltaMC[i][species]->SetName(Form("h2Delta_MC_%s", speciesLabel.Data()));
1752 h2DeltaMC[i][species]->GetXaxis()->SetTitle(hPIDdata->GetAxis(axisGenForMode)->GetTitle());
1753 h2DeltaMC[i][species]->GetYaxis()->SetTitle(h2Delta[i]->GetYaxis()->GetTitle());
1754 }
1755 hPIDdata->GetAxis(kPidMCpid)->SetRange(0, -1);
1756 }
1757
1758 Int_t firstValidSlice = -1;
1759 for (Int_t slice = 0; (mode == kPMpT) ? slice < nPtBins : slice < hPIDdata->GetAxis(axisForMode)->GetNbins(); slice++) {
1760 if (mode == kPMpT && (slice < pSliceLow || slice > pSliceHigh))
1761 continue;
1762
1763 if (firstValidSlice < 0)
1764 firstValidSlice = slice;
1765
1766 // Add/subtract some very small offset to be sure not to sit on the bin boundary, when looking for the integration/projection limits.
1767 // For modes different from pT, just take 1 bin
1768 const Int_t pBinLowProjLimit = (mode == kPMpT) ? h2Delta[0]->GetXaxis()->FindBin(binsPt[slice] + 1e-5) : slice + 1;
1769 const Int_t pBinUpProjLimit = (mode == kPMpT) ? h2Delta[0]->GetXaxis()->FindBin(binsPt[slice + 1]- 1e-5) : slice + 1;
1770
1771 const TString binInfo = (mode == kPMpT) ? Form("%.2f_Pt_%.2f", binsPt[slice], binsPt[slice + 1])
1772 : Form("%.2f_%s_%.2f", hPIDdata->GetAxis(axisForMode)->GetBinLowEdge(pBinLowProjLimit),
1773 modeShortName[mode].Data(),
1774 hPIDdata->GetAxis(axisForMode)->GetBinUpEdge(pBinUpProjLimit));
1775
1776 hDeltaEl[slice] = h2Delta[0]->ProjectionY(Form("hDeltaEl_%s", binInfo.Data()), pBinLowProjLimit, pBinUpProjLimit, "e");
1777 hDeltaEl[slice]->GetXaxis()->SetTitle(h2Delta[0]->GetYaxis()->GetTitle());
1778 hDeltaEl[slice]->GetXaxis()->SetTitleOffset(1.0);
1779 hDeltaEl[slice]->SetStats(kFALSE);
1780
1781 hDeltaKa[slice] = h2Delta[1]->ProjectionY(Form("hDeltaKa_%s", binInfo.Data()), pBinLowProjLimit, pBinUpProjLimit, "e");
1782 hDeltaKa[slice]->SetName(Form("hDeltaKa_%s", binInfo.Data()));
1783 hDeltaKa[slice]->GetXaxis()->SetTitle(h2Delta[1]->GetYaxis()->GetTitle());
1784 hDeltaKa[slice]->GetXaxis()->SetTitleOffset(1.0);
1785 hDeltaKa[slice]->SetStats(kFALSE);
1786
1787 hDeltaPi[slice] = h2Delta[2]->ProjectionY(Form("hDeltaPi_%s", binInfo.Data()), pBinLowProjLimit, pBinUpProjLimit, "e");
1788 hDeltaPi[slice]->SetName(Form("hDeltaPi_%s", binInfo.Data()));
1789 hDeltaPi[slice]->GetXaxis()->SetTitle(h2Delta[2]->GetYaxis()->GetTitle());
1790 hDeltaPi[slice]->GetXaxis()->SetTitleOffset(1.0);
1791 hDeltaPi[slice]->SetStats(kFALSE);
1792
1793 hDeltaPr[slice] = h2Delta[3]->ProjectionY(Form("hDeltaPr_%s", binInfo.Data()), pBinLowProjLimit, pBinUpProjLimit, "e");
1794 hDeltaPr[slice]->SetName(Form("hDeltaPr_%s", binInfo.Data()));
1795 hDeltaPr[slice]->GetXaxis()->SetTitle(h2Delta[3]->GetYaxis()->GetTitle());
1796 hDeltaPr[slice]->GetXaxis()->SetTitleOffset(1.0);
1797 hDeltaPr[slice]->SetStats(kFALSE);
1798
1799 if (plotIdentifiedSpectra) {
1800 // If identified spectra are available (mainly useful in the MC case) and shall be used,
1801 // create histos with signals from identified particles
1802
1803 // DeltaEl
1804 for (Int_t species = 0; species < nMCbins; species++) {
1805 hDeltaElMC[slice][species] = h2DeltaMC[0][species]->ProjectionY(Form("hDeltaElMC_%s_species_%d", binInfo.Data(), species),
1806 pBinLowProjLimit, pBinUpProjLimit, "e");
1807 hDeltaElMC[slice][species]->SetLineColor(getLineColor(species + 1));
1808 hDeltaElMC[slice][species]->SetMarkerColor(getLineColor(species + 1));
1809 hDeltaElMC[slice][species]->SetMarkerStyle(24);
1810 hDeltaElMC[slice][species]->SetLineStyle(1);
1811 hDeltaElMC[slice][species]->GetXaxis()->SetTitle(h2DeltaMC[0][species]->GetYaxis()->GetTitle());
1812 hDeltaElMC[slice][species]->GetXaxis()->SetTitleOffset(1.0);
1813 hDeltaElMC[slice][species]->SetStats(kFALSE);
1814 }
1815
1816 // DeltaKa
1817 for (Int_t species = 0; species < nMCbins; species++) {
1818 hDeltaKaMC[slice][species] = h2DeltaMC[1][species]->ProjectionY(Form("hDeltaKaMC_%s_species_%d", binInfo.Data(), species),
1819 pBinLowProjLimit, pBinUpProjLimit, "e");
1820 hDeltaKaMC[slice][species]->SetLineColor(getLineColor(species + 1));
1821 hDeltaKaMC[slice][species]->SetMarkerColor(getLineColor(species + 1));
1822 hDeltaKaMC[slice][species]->SetMarkerStyle(24);
1823 hDeltaKaMC[slice][species]->SetLineStyle(1);
1824 hDeltaKaMC[slice][species]->GetXaxis()->SetTitle(h2DeltaMC[1][species]->GetYaxis()->GetTitle());
1825 hDeltaKaMC[slice][species]->GetXaxis()->SetTitleOffset(1.0);
1826 hDeltaKaMC[slice][species]->SetStats(kFALSE);
1827 }
1828
1829 // DeltaPi
1830 for (Int_t species = 0; species < nMCbins; species++) {
1831 hDeltaPiMC[slice][species] = h2DeltaMC[2][species]->ProjectionY(Form("hDeltaPiMC_%s_species_%d", binInfo.Data(), species),
1832 pBinLowProjLimit, pBinUpProjLimit, "e");
1833 hDeltaPiMC[slice][species]->SetLineColor(getLineColor(species + 1));
1834 hDeltaPiMC[slice][species]->SetMarkerColor(getLineColor(species + 1));
1835 hDeltaPiMC[slice][species]->SetMarkerStyle(24);
1836 hDeltaPiMC[slice][species]->SetLineStyle(1);
1837 hDeltaPiMC[slice][species]->GetXaxis()->SetTitle(h2DeltaMC[2][species]->GetYaxis()->GetTitle());
1838 hDeltaPiMC[slice][species]->GetXaxis()->SetTitleOffset(1.0);
1839 hDeltaPiMC[slice][species]->SetStats(kFALSE);
1840 }
1841
1842 // DeltaPr
1843 for (Int_t species = 0; species < nMCbins; species++) {
1844 hDeltaPrMC[slice][species] = h2DeltaMC[3][species]->ProjectionY(Form("hDeltaPrMC_%s_species_%d", binInfo.Data(), species),
1845 pBinLowProjLimit, pBinUpProjLimit, "e");
1846 hDeltaPrMC[slice][species]->SetLineColor(getLineColor(species + 1));
1847 hDeltaPrMC[slice][species]->SetMarkerColor(getLineColor(species + 1));
1848 hDeltaPrMC[slice][species]->SetMarkerStyle(24);
1849 hDeltaPrMC[slice][species]->SetLineStyle(1);
1850 hDeltaPrMC[slice][species]->GetXaxis()->SetTitle(h2DeltaMC[3][species]->GetYaxis()->GetTitle());
1851 hDeltaPrMC[slice][species]->GetXaxis()->SetTitleOffset(1.0);
1852 hDeltaPrMC[slice][species]->SetStats(kFALSE);
1853 }
1854 }
1855 }
1856 hPIDdata->GetAxis(kPidMCpid)->SetRange(0, -1);
1857 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(0, -1);
1858
1859 hPIDdata->GetAxis(axisForMode)->SetRange(0, -1);
1860
1861 /*
1862 // TOF TODO
1863 TCanvas* cTOF = new TCanvas("cTOF", "TOF PID",100,10,1200,800);
1864 cTOF->Divide(4,1);
1865 cTOF->cd(1);
1866 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(1, 1);
1867 TH2D* h2TOFel = hPIDdata->Projection(kPidDeltaTOF, kPidPvertex);
1868 h2TOFel->SetName("h2TOFel");
1869 h2TOFel->GetYaxis()->SetTitle(Form("#DeltaTOF_{%s} (ps)", hPIDdata->GetAxis(kPidSelectSpecies)->GetBinLabel(1)));
1870 h2TOFel->Draw("colz");
1871
1872 cTOF->cd(2);
1873 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(2, 2);
1874 TH2D* h2TOFka = hPIDdata->Projection(kPidDeltaTOF, kPidPvertex);
1875 h2TOFka->SetName("h2TOFka");
1876 h2TOFka->GetYaxis()->SetTitle(Form("#DeltaTOF_{%s} (ps)", hPIDdata->GetAxis(kPidSelectSpecies)->GetBinLabel(2)));
1877 h2TOFka->Draw("colz");
1878
1879 cTOF->cd(3);
1880 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(3, 3);
1881 TH2D* h2TOFpi = hPIDdata->Projection(kPidDeltaTOF, kPidPvertex);
1882 h2TOFpi->SetName("h2TOFpi");
1883 h2TOFpi->GetYaxis()->SetTitle(Form("#DeltaTOF_{%s} (ps)", hPIDdata->GetAxis(kPidSelectSpecies)->GetBinLabel(3)));
1884 h2TOFpi->Draw("colz");
1885
1886 cTOF->cd(4);
1887 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(4, 4);
1888 TH2D* h2TOFpr = hPIDdata->Projection(kPidDeltaTOF, kPidPvertex);
1889 h2TOFpr->SetName("h2TOFpr");
1890 h2TOFpr->GetYaxis()->SetTitle(Form("#DeltaTOF_{%s} (ps)", hPIDdata->GetAxis(kPidSelectSpecies)->GetBinLabel(4)));
1891 h2TOFpr->Draw("colz");
1892
1893 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(0, -1);
1894 */
1895
1896 // Start fitting of slices
1897 TCanvas* cSingleFit[numSlices][4];
1898
1899 TF1* fitFuncTotalDeltaPion[numSlices];
1900 TF1* fitFuncTotalDeltaElectron[numSlices];
1901 TF1* fitFuncTotalDeltaKaon[numSlices];
1902 TF1* fitFuncTotalDeltaProton[numSlices];
1903
1904 // Histos for particle fractions
1905 TH1F* hFractionElectrons = 0x0;
1906 if (mode == kPMpT)
1907 hFractionElectrons = new TH1F("hFractionElectrons", "e", nPtBins, binsPt);
1908 else {
1909 const TArrayD* histBins = hPIDdata->GetAxis(axisForMode)->GetXbins();
1910 if (histBins->fN == 0)
1911 hFractionElectrons = new TH1F("hFractionElectrons", "e", hPIDdata->GetAxis(axisForMode)->GetNbins(), hPIDdata->GetAxis(axisForMode)->GetXmin(),
1912 hPIDdata->GetAxis(axisForMode)->GetXmax());
1913 else
1914 hFractionElectrons = new TH1F("hFractionElectrons", "e", hPIDdata->GetAxis(axisForMode)->GetNbins(), histBins->fArray);
1915 }
1916
1917 hFractionElectrons->GetXaxis()->SetTitle(hPIDdata->GetAxis(axisForMode)->GetTitle());
1918 hFractionElectrons->GetYaxis()->SetTitle("Fraction");
1919 hFractionElectrons->SetLineColor(getLineColor(kEl));
1920 hFractionElectrons->SetMarkerColor(getLineColor(kEl));
1921 hFractionElectrons->SetMarkerStyle(20);
1922 hFractionElectrons->Sumw2();
1923 hFractionElectrons->SetStats(kFALSE);
1924
1925 TH1F* hFractionElectronsDeltaPion = (TH1F*)hFractionElectrons->Clone("hFractionElectronsDeltaPion");
1926 TH1F* hFractionElectronsDeltaElectron = (TH1F*)hFractionElectrons->Clone("hFractionElectronsDeltaElectron");
1927 TH1F* hFractionElectronsDeltaKaon = (TH1F*)hFractionElectrons->Clone("hFractionElectronsDeltaKaon");
1928 TH1F* hFractionElectronsDeltaProton = (TH1F*)hFractionElectrons->Clone("hFractionElectronsDeltaProton");
1929
1930 TH1F* hFractionKaons = (TH1F*)hFractionElectrons->Clone("hFractionKaons");
1931 hFractionKaons->SetTitle("K");
1932 hFractionKaons->SetLineColor(getLineColor(kKa));
1933 hFractionKaons->SetMarkerColor(getLineColor(kKa));
1934
1935 TH1F* hFractionKaonsDeltaPion = (TH1F*)hFractionKaons->Clone("hFractionKaonsDeltaPion");
1936 TH1F* hFractionKaonsDeltaElectron = (TH1F*)hFractionKaons->Clone("hFractionKaonsDeltaElectron");
1937 TH1F* hFractionKaonsDeltaKaon = (TH1F*)hFractionKaons->Clone("hFractionKaonsDeltaKaon");
1938 TH1F* hFractionKaonsDeltaProton = (TH1F*)hFractionKaons->Clone("hFractionKaonsDeltaProton");
1939
1940 TH1F* hFractionPions = (TH1F*)hFractionElectrons->Clone("hFractionPions");
1941 hFractionPions->SetTitle("#pi");
1942 hFractionPions->SetLineColor(getLineColor(kPi));
1943 hFractionPions->SetMarkerColor(getLineColor(kPi));
1944
1945 TH1F* hFractionPionsDeltaPion = (TH1F*)hFractionPions->Clone("hFractionPionsDeltaPion");
1946 TH1F* hFractionPionsDeltaElectron = (TH1F*)hFractionPions->Clone("hFractionPionsDeltaElectron");
1947 TH1F* hFractionPionsDeltaKaon = (TH1F*)hFractionPions->Clone("hFractionPionsDeltaKaon");
1948 TH1F* hFractionPionsDeltaProton = (TH1F*)hFractionPions->Clone("hFractionPionsDeltaProton");
1949
1950 TH1F* hFractionProtons = (TH1F*)hFractionElectrons->Clone("hFractionProtons");
1951 hFractionProtons->SetTitle("p");
1952 hFractionProtons->SetLineColor(getLineColor(kPr));
1953 hFractionProtons->SetMarkerColor(getLineColor(kPr));
1954
1955 TH1F* hFractionProtonsDeltaPion = (TH1F*)hFractionProtons->Clone("hFractionProtonsDeltaPion");
1956 TH1F* hFractionProtonsDeltaElectron = (TH1F*)hFractionProtons->Clone("hFractionProtonsDeltaElectron");
1957 TH1F* hFractionProtonsDeltaKaon = (TH1F*)hFractionProtons->Clone("hFractionProtonsDeltaKaon");
1958 TH1F* hFractionProtonsDeltaProton = (TH1F*)hFractionProtons->Clone("hFractionProtonsDeltaProton");
1959
1960 TH1F* hFractionMuons = (TH1F*)hFractionElectrons->Clone("hFractionMuons");
1961 hFractionMuons->SetTitle("#mu");
1962 hFractionMuons->SetLineColor(getLineColor(kMu));
1963 hFractionMuons->SetMarkerColor(getLineColor(kMu));
1964
1965 TH1F* hFractionMuonsDeltaPion = (TH1F*)hFractionMuons->Clone("hFractionMuonsDeltaPion");
1966 TH1F* hFractionMuonsDeltaElectron = (TH1F*)hFractionMuons->Clone("hFractionMuonsDeltaElectron");
1967 TH1F* hFractionMuonsDeltaKaon = (TH1F*)hFractionMuons->Clone("hFractionMuonsDeltaKaon");
1968 TH1F* hFractionMuonsDeltaProton = (TH1F*)hFractionMuons->Clone("hFractionMuonsDeltaProton");
1969
1970 TH1F* hFractionSummed = (TH1F*)hFractionProtons->Clone("hFractionSummed");
1971 hFractionSummed->SetTitle("Sum");
1972 hFractionSummed->SetLineColor(kBlack);
1973 hFractionSummed->SetMarkerColor(kBlack);
1974
1975
1976 // MC fractions
1977 TH1F* hFractionElectronsMC = (TH1F*)hFractionElectrons->Clone("hFractionElectronsMC");
1978 hFractionElectronsMC->SetMarkerStyle(24);
1979 TH1F* hFractionKaonsMC = (TH1F*)hFractionKaons->Clone("hFractionKaonsMC");
1980 hFractionKaonsMC->SetMarkerStyle(24);
1981 TH1F* hFractionPionsMC = (TH1F*)hFractionPions->Clone("hFractionPionsMC");
1982 hFractionPionsMC->SetMarkerStyle(24);
1983 TH1F* hFractionMuonsMC = (TH1F*)hFractionMuons->Clone("hFractionMuonsMC");
1984 hFractionMuonsMC->SetMarkerStyle(24);
1985 TH1F* hFractionProtonsMC = (TH1F*)hFractionProtons->Clone("hFractionProtonsMC");
1986 hFractionProtonsMC->SetMarkerStyle(24);
1987
1988
1989 // Comparison fit result<->MC
1990 TString fractionComparisonTitle = Form("Fraction fit / fraction %s", identifiedLabels[isMC].Data());
1991 TH1F* hFractionComparisonElectrons = (TH1F*)hFractionElectrons->Clone("hFractionComparisonElectrons");
1992 hFractionComparisonElectrons->GetYaxis()->SetTitle(fractionComparisonTitle.Data());
1993 TH1F* hFractionComparisonMuons = (TH1F*)hFractionMuons->Clone("hFractionComparisonMuons");
1994 hFractionComparisonMuons->GetYaxis()->SetTitle(fractionComparisonTitle.Data());
1995 TH1F* hFractionComparisonKaons = (TH1F*)hFractionKaons->Clone("hFractionComparisonKaons");
1996 hFractionComparisonKaons->GetYaxis()->SetTitle(fractionComparisonTitle.Data());
1997 TH1F* hFractionComparisonPions = (TH1F*)hFractionPions->Clone("hFractionComparisonPions");
1998 hFractionComparisonPions->GetYaxis()->SetTitle(fractionComparisonTitle.Data());
1999 TH1F* hFractionComparisonProtons = (TH1F*)hFractionProtons->Clone("hFractionComparisonProtons");
2000 hFractionComparisonProtons->GetYaxis()->SetTitle(fractionComparisonTitle.Data());
2001 TH1F* hFractionComparisonTotal = (TH1F*)hFractionSummed->Clone("hFractionComparisonTotal");
2002 hFractionComparisonTotal->GetYaxis()->SetTitle(fractionComparisonTitle.Data());
2003
2004
2005
2006 // Histos for particle yields
2007 TH1F* hYieldElectrons = 0x0;
2008 if (mode == kPMpT)
2009 hYieldElectrons = new TH1F("hYieldElectrons", "e", nPtBins, binsPt);
2010 else {
2011 const TArrayD* histBins = hPIDdata->GetAxis(axisForMode)->GetXbins();
2012 if (histBins->fN == 0)
2013 hYieldElectrons = new TH1F("hYieldElectrons", "e", hPIDdata->GetAxis(axisForMode)->GetNbins(), hPIDdata->GetAxis(axisForMode)->GetXmin(),
2014 hPIDdata->GetAxis(axisForMode)->GetXmax());
2015 else
2016 hYieldElectrons = new TH1F("hYieldElectrons", "e", hPIDdata->GetAxis(axisForMode)->GetNbins(), histBins->fArray);
2017 }
2018
2019 hYieldElectrons->GetXaxis()->SetTitle(hPIDdata->GetAxis(axisForMode)->GetTitle());
2020 hYieldElectrons->GetYaxis()->SetTitle(Form("%s1/(2#pi%s) d^{2}N/d#etad%s%s", numEvents > 0 ? "1/N_{ev} " : "",
2021 modeLatexName[mode].Data(), modeLatexName[mode].Data(),
2022 mode == kPMpT ? " (GeV/c)^{-2}" : 0));
2023 hYieldElectrons->SetLineColor(getLineColor(kEl));
2024 hYieldElectrons->SetMarkerColor(getLineColor(kEl));
2025 hYieldElectrons->SetMarkerStyle(20);
2026 hYieldElectrons->Sumw2();
2027 hYieldElectrons->SetStats(kFALSE);
2028
2029 TH1F* hYieldElectronsDeltaPion = (TH1F*)hYieldElectrons->Clone("hYieldElectronsDeltaPion");
2030 TH1F* hYieldElectronsDeltaElectron = (TH1F*)hYieldElectrons->Clone("hYieldElectronsDeltaElectron");
2031 TH1F* hYieldElectronsDeltaKaon = (TH1F*)hYieldElectrons->Clone("hYieldElectronsDeltaKaon");
2032 TH1F* hYieldElectronsDeltaProton = (TH1F*)hYieldElectrons->Clone("hYieldElectronsDeltaProton");
2033
2034 TH1F* hYieldKaons = (TH1F*)hYieldElectrons->Clone("hYieldKaons");
2035 hYieldKaons->SetTitle("K");
2036 hYieldKaons->SetLineColor(getLineColor(kKa));
2037 hYieldKaons->SetMarkerColor(getLineColor(kKa));
2038
2039 TH1F* hYieldKaonsDeltaPion = (TH1F*)hYieldKaons->Clone("hYieldKaonsDeltaPion");
2040 TH1F* hYieldKaonsDeltaElectron = (TH1F*)hYieldKaons->Clone("hYieldKaonsDeltaElectron");
2041 TH1F* hYieldKaonsDeltaKaon = (TH1F*)hYieldKaons->Clone("hYieldKaonsDeltaKaon");
2042 TH1F* hYieldKaonsDeltaProton = (TH1F*)hYieldKaons->Clone("hYieldKaonsDeltaProton");
2043
2044 TH1F* hYieldPions = (TH1F*)hYieldElectrons->Clone("hYieldPions");
2045 hYieldPions->SetTitle("#pi");
2046 hYieldPions->SetLineColor(getLineColor(kPi));
2047 hYieldPions->SetMarkerColor(getLineColor(kPi));
2048
2049 TH1F* hYieldPionsDeltaPion = (TH1F*)hYieldPions->Clone("hYieldPionsDeltaPion");
2050 TH1F* hYieldPionsDeltaElectron = (TH1F*)hYieldPions->Clone("hYieldPionsDeltaElectron");
2051 TH1F* hYieldPionsDeltaKaon = (TH1F*)hYieldPions->Clone("hYieldPionsDeltaKaon");
2052 TH1F* hYieldPionsDeltaProton = (TH1F*)hYieldPions->Clone("hYieldPionsDeltaProton");
2053
2054 TH1F* hYieldProtons = (TH1F*)hYieldElectrons->Clone("hYieldProtons");
2055 hYieldProtons->SetTitle("p");
2056 hYieldProtons->SetLineColor(getLineColor(kPr));
2057 hYieldProtons->SetMarkerColor(getLineColor(kPr));
2058
2059 TH1F* hYieldProtonsDeltaPion = (TH1F*)hYieldProtons->Clone("hYieldProtonsDeltaPion");
2060 TH1F* hYieldProtonsDeltaElectron = (TH1F*)hYieldProtons->Clone("hYieldProtonsDeltaElectron");
2061 TH1F* hYieldProtonsDeltaKaon = (TH1F*)hYieldProtons->Clone("hYieldProtonsDeltaKaon");
2062 TH1F* hYieldProtonsDeltaProton = (TH1F*)hYieldProtons->Clone("hYieldProtonsDeltaProton");
2063
2064 TH1F* hYieldMuons = (TH1F*)hYieldElectrons->Clone("hYieldMuons");
2065 hYieldMuons->SetTitle("#mu");
2066 hYieldMuons->SetLineColor(getLineColor(kMu));
2067 hYieldMuons->SetMarkerColor(getLineColor(kMu));
2068
2069 TH1F* hYieldMuonsDeltaPion = (TH1F*)hYieldMuons->Clone("hYieldMuonsDeltaPion");
2070 TH1F* hYieldMuonsDeltaElectron = (TH1F*)hYieldMuons->Clone("hYieldMuonsDeltaElectron");
2071 TH1F* hYieldMuonsDeltaKaon = (TH1F*)hYieldMuons->Clone("hYieldMuonsDeltaKaon");
2072 TH1F* hYieldMuonsDeltaProton = (TH1F*)hYieldMuons->Clone("hYieldMuonsDeltaProton");
2073
2074 // MC yields
2075 TH1F* hYieldElectronsMC = (TH1F*)hYieldElectrons->Clone("hYieldElectronsMC");
2076 hYieldElectronsMC->SetMarkerStyle(24);
2077 TH1F* hYieldMuonsMC = (TH1F*)hYieldElectrons->Clone("hYieldMuonsMC");
2078 hYieldMuonsMC->SetMarkerStyle(24);
2079 hYieldMuonsMC->SetLineColor(getLineColor(kMu));
2080 hYieldMuonsMC->SetMarkerColor(getLineColor(kMu));
2081 TH1F* hYieldKaonsMC = (TH1F*)hYieldKaons->Clone("hYieldKaonsMC");
2082 hYieldKaonsMC->SetMarkerStyle(24);
2083 TH1F* hYieldPionsMC = (TH1F*)hYieldPions->Clone("hYieldPionsMC");
2084 hYieldPionsMC->SetMarkerStyle(24);
2085 TH1F* hYieldProtonsMC = (TH1F*)hYieldProtons->Clone("hYieldProtonsMC");
2086 hYieldProtonsMC->SetMarkerStyle(24);
2087 TH1F* hYieldSummedMC = (TH1F*)hYieldProtonsMC->Clone("hYieldSummedMC");
2088 hYieldSummedMC->SetTitle("Sum");
2089 hYieldSummedMC->SetLineColor(kBlack);
2090 hYieldSummedMC->SetMarkerColor(kBlack);
2091
2092 // Comparison fit result<->MC (yields)
2093 TString yieldComparisonTitle = Form("Yield fit / yield %s", identifiedLabels[isMC].Data());
2094 TH1F* hYieldComparisonElectrons = (TH1F*)hYieldElectrons->Clone("hYieldComparisonElectrons");
2095 hYieldComparisonElectrons->GetYaxis()->SetTitle(yieldComparisonTitle.Data());
2096 TH1F* hYieldComparisonMuons = (TH1F*)hYieldMuons->Clone("hYieldComparisonMuons");
2097 hYieldComparisonMuons->GetYaxis()->SetTitle(yieldComparisonTitle.Data());
2098 TH1F* hYieldComparisonKaons = (TH1F*)hYieldKaons->Clone("hYieldComparisonKaons");
2099 hYieldComparisonKaons->GetYaxis()->SetTitle(yieldComparisonTitle.Data());
2100 TH1F* hYieldComparisonPions = (TH1F*)hYieldPions->Clone("hYieldComparisonPions");
2101 hYieldComparisonPions->GetYaxis()->SetTitle(yieldComparisonTitle.Data());
2102 TH1F* hYieldComparisonProtons = (TH1F*)hYieldProtons->Clone("hYieldComparisonProtons");
2103 hYieldComparisonProtons->GetYaxis()->SetTitle(yieldComparisonTitle.Data());
2104
2105
2106 // To-pi ratios
2107 TString electronString[3] = { "e^{-}", "e^{+}+e^{-}", "e^{+}" };
2108 TString muonString[3] = { "#mu^{-}", "#mu^{+}+#mu^{-}", "#mu^{+}" };
2109 TString kaonString[3] = { "K^{-}", "K^{+}+K^{-}", "K^{+}" };
2110 TString pionString[3] = { "#pi^{-}", "#pi^{+}+#pi^{-}", "#pi^{+}" };
2111 TString protonString[3] = { "#bar{p}", "p+#bar{p}", "p" };
2112
2113 TH1F* hRatioToPiElectrons = (TH1F*)hYieldElectrons->Clone("hRatioToPiElectrons");
2114 hRatioToPiElectrons->GetYaxis()->SetTitle(Form("d^{2}N_{%s}/d#etad%s / d^{2}N_{%s}/d#etad%s",
2115 electronString[chargeMode+1].Data(),
2116 modeLatexName[mode].Data(),
2117 pionString[chargeMode+1].Data(),
2118 modeLatexName[mode].Data()));
2119 hRatioToPiElectrons->SetTitle(Form("%s", chargeMode == 0
2120 ? Form("(%s)/(%s)", electronString[chargeMode+1].Data(), pionString[chargeMode+1].Data())
2121 : Form("%s/%s", electronString[chargeMode+1].Data(), pionString[chargeMode+1].Data())));
2122
2123
2124 TH1F* hRatioToPiMuons = (TH1F*)hYieldMuons->Clone("hRatioToPiMuons");
2125 hRatioToPiMuons->GetYaxis()->SetTitle(Form("d^{2}N_{%s}/d#etad%s / d^{2}N_{%s}/d#etad%s",
2126 muonString[chargeMode+1].Data(),
2127 modeLatexName[mode].Data(),
2128 pionString[chargeMode+1].Data(),
2129 modeLatexName[mode].Data()));
2130 hRatioToPiMuons->SetTitle(Form("%s", chargeMode == 0
2131 ? Form("(%s)/(%s)", muonString[chargeMode+1].Data(), pionString[chargeMode+1].Data())
2132 : Form("%s/%s", muonString[chargeMode+1].Data(), pionString[chargeMode+1].Data())));
2133
2134 TH1F* hRatioToPiKaons = (TH1F*)hYieldKaons->Clone("hRatioToPiKaons");
2135 hRatioToPiKaons->GetYaxis()->SetTitle(Form("d^{2}N_{%s}/d#etad%s / d^{2}N_{%s}/d#etad%s",
2136 kaonString[chargeMode+1].Data(),
2137 modeLatexName[mode].Data(),
2138 pionString[chargeMode+1].Data(),
2139 modeLatexName[mode].Data()));
2140 hRatioToPiKaons->SetTitle(Form("%s", chargeMode == 0
2141 ? Form("(%s)/(%s)", kaonString[chargeMode+1].Data(), pionString[chargeMode+1].Data())
2142 : Form("%s/%s", kaonString[chargeMode+1].Data(), pionString[chargeMode+1].Data())));
2143
2144 TH1F* hRatioToPiProtons = (TH1F*)hYieldProtons->Clone("hRatioToPiProtons");
2145 hRatioToPiProtons->GetYaxis()->SetTitle(Form("d^{2}N_{%s}/d#etad%s / d^{2}N_{%s}/d#etad%s",
2146 protonString[chargeMode+1].Data(),
2147 modeLatexName[mode].Data(),
2148 pionString[chargeMode+1].Data(),
2149 modeLatexName[mode].Data()));
2150 hRatioToPiProtons->SetTitle(Form("%s", chargeMode == 0
2151 ? Form("(%s)/(%s)", protonString[chargeMode+1].Data(), pionString[chargeMode+1].Data())
2152 : Form("%s/%s", protonString[chargeMode+1].Data(), pionString[chargeMode+1].Data())));
2153
2154 // MC to-pi ratios
2155 TH1F* hRatioToPiElectronsMC = (TH1F*)hRatioToPiElectrons->Clone("hRatioToPiElectronsMC");
2156 hRatioToPiElectronsMC->SetMarkerStyle(24);
2157 TH1F* hRatioToPiMuonsMC = (TH1F*)hRatioToPiMuons->Clone("hRatioToPiMuonsMC");
2158 hRatioToPiMuonsMC->SetMarkerStyle(24);
2159 hRatioToPiMuonsMC->SetLineColor(getLineColor(kMu));
2160 hRatioToPiMuonsMC->SetMarkerColor(getLineColor(kMu));
2161 TH1F* hRatioToPiKaonsMC = (TH1F*)hRatioToPiKaons->Clone("hRatioToPiKaonsMC");
2162 hRatioToPiKaonsMC->SetMarkerStyle(24);
2163 TH1F* hRatioToPiProtonsMC = (TH1F*)hRatioToPiProtons->Clone("hRatioToPiProtonsMC");
2164 hRatioToPiProtonsMC->SetMarkerStyle(24);
2165
2166 // Reduced Chi^2 of fits vs. pT for all Delta_Species
2167 TH2F* hReducedChiSquarePt = 0x0;
2168 if (mode == kPMpT)
2169 hReducedChiSquarePt = new TH2F("hReducedChiSquarePt", "e", nPtBins, binsPt, 4, 0, 4);
2170 else {
2171 const TArrayD* histBins = hPIDdata->GetAxis(axisForMode)->GetXbins();
2172 if (histBins->fN == 0)
2173 hReducedChiSquarePt = new TH2F(Form("hReducedChiSquare%s", modeShortName[mode].Data()), "e",
2174 hPIDdata->GetAxis(axisForMode)->GetNbins(), hPIDdata->GetAxis(axisForMode)->GetXmin(),
2175 hPIDdata->GetAxis(axisForMode)->GetXmax(), 4, 0, 4);
2176 else
2177 hReducedChiSquarePt = new TH2F(Form("hReducedChiSquare%s", modeShortName[mode].Data()), "e",
2178 hPIDdata->GetAxis(axisForMode)->GetNbins(), histBins->fArray, 4, 0, 4);
2179 }
2180
2181 hReducedChiSquarePt->GetXaxis()->SetTitle(hPIDdata->GetAxis(axisForMode)->GetTitle());
2182 hReducedChiSquarePt->GetYaxis()->SetTitle("Delta_{Species}");
2183 hReducedChiSquarePt->GetYaxis()->SetBinLabel(1, "e");
2184 hReducedChiSquarePt->GetYaxis()->SetBinLabel(2, "K");
2185 hReducedChiSquarePt->GetYaxis()->SetBinLabel(3, "#pi");
2186 hReducedChiSquarePt->GetYaxis()->SetBinLabel(4, "p");
2187 hReducedChiSquarePt->SetMarkerColor(kRed);
2188 hReducedChiSquarePt->SetMarkerStyle(20);
2189 hReducedChiSquarePt->SetStats(kFALSE);
2190
2191 // Obtain MC information about particle yields
2192 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(1, 1); // Do not count each particle more than once
2193 TH2D* hMCdata = (TH2D*)hPIDdata->Projection(kPidMCpid, axisForMode, "e");
2194 hMCdata->SetName("hMCdata");
2195 hPIDdata->GetAxis(kPidSelectSpecies)->SetRange(0, -1); // Reset range
2196
2197
2198
2199 // Extract the MC truth generated primary yields
2200 THnSparse* hMCgeneratedYieldsPrimaries = isMCdataSet ? dynamic_cast<THnSparse*>(histList->FindObject("fhMCgeneratedYieldsPrimaries"))
2201 : 0x0;
2202
2203 TH1D* hMCgenYieldsPrimSpecies[AliPID::kSPECIES];
2204 for (Int_t i = 0; i < AliPID::kSPECIES; i++)
2205 hMCgenYieldsPrimSpecies[i] = 0x0;
2206
2207 if (hMCgeneratedYieldsPrimaries) {
2208 // Set proper errors, if not yet calculated
2209 if (!hMCgeneratedYieldsPrimaries->GetCalculateErrors()) {
2210 std::cout << "Re-calculating errors of " << hMCgeneratedYieldsPrimaries->GetName() << "..." << std::endl;
2211
2212 hMCgeneratedYieldsPrimaries->Sumw2();
2213
2214 Long64_t nBinsTHnSparseGenYield = hMCgeneratedYieldsPrimaries->GetNbins();
2215 Double_t binContentGenYield = 0;
2216 for (Long64_t bin = 0; bin < nBinsTHnSparseGenYield; bin++) {
2217 binContentGenYield = hMCgeneratedYieldsPrimaries->GetBinContent(bin);
2218 hMCgeneratedYieldsPrimaries->SetBinError(bin, TMath::Sqrt(binContentGenYield));
2219 }
2220 }
2221
2222 if (restrictJetPtAxis)
2223 hMCgeneratedYieldsPrimaries->GetAxis(kPidGenYieldJetPt)->SetRange(lowerJetPtBinLimit, upperJetPtBinLimit);
2224
2225 if (restrictCentralityAxis)
2226 hMCgeneratedYieldsPrimaries->GetAxis(kPidGenYieldCentrality)->SetRange(lowerCentralityBinLimit, upperCentralityBinLimit);
2227
2228
2229 if (restrictCharge) {
2230 const Int_t indexChargeAxisGenYield = GetAxisByTitle(hMCgeneratedYieldsPrimaries, "Charge (e_{0})");
2231 if (indexChargeAxisGenYield < 0) {
2232 std::cout << "Error: Charge axis not found for gen yield histogram!" << std::endl;
2233 return -1;
2234 }
2235
2236 Int_t lowerChargeBinLimitGenYield = -1;
2237 Int_t upperChargeBinLimitGenYield = -2;
2238 Double_t actualLowerChargeGenYield = -999;
2239 Double_t actualUpperChargeGenYield = -999;
2240
2241 // Add subtract a very small number to avoid problems with values right on the border between to bins
2242 if (chargeMode == kNegCharge) {
2243 lowerChargeBinLimitGenYield = hMCgeneratedYieldsPrimaries->GetAxis(indexChargeAxisGenYield)->FindBin(-1. + 0.001);
2244 upperChargeBinLimitGenYield = hMCgeneratedYieldsPrimaries->GetAxis(indexChargeAxisGenYield)->FindBin(0. - 0.001);
2245 }
2246 else if (chargeMode == kPosCharge) {
2247 lowerChargeBinLimitGenYield = hMCgeneratedYieldsPrimaries->GetAxis(indexChargeAxisGenYield)->FindBin(0. + 0.001);
2248 upperChargeBinLimitGenYield = hMCgeneratedYieldsPrimaries->GetAxis(indexChargeAxisGenYield)->FindBin(1. - 0.001);
2249 }
2250
2251 // Check if the values look reasonable
2252 if (lowerChargeBinLimitGenYield <= upperChargeBinLimitGenYield && lowerChargeBinLimitGenYield >= 1
2253 && upperChargeBinLimitGenYield <= hMCgeneratedYieldsPrimaries->GetAxis(indexChargeAxisGenYield)->GetNbins()) {
2254 actualLowerChargeGenYield = hMCgeneratedYieldsPrimaries->GetAxis(indexChargeAxisGenYield)->GetBinLowEdge(lowerChargeBinLimitGenYield);
2255 actualUpperChargeGenYield = hMCgeneratedYieldsPrimaries->GetAxis(indexChargeAxisGenYield)->GetBinUpEdge(upperChargeBinLimitGenYield);
2256
2257 if (TMath::Abs(actualLowerChargeGenYield - actualLowerChargeData) > 1e-4 ||
2258 TMath::Abs(actualUpperChargeGenYield - actualUpperChargeData) > 1e-4) {
2259 std::cout << std::endl;
2260 std::cout << "Error: Charge range gen yield: " << actualLowerChargeGenYield << " - " << actualUpperChargeGenYield
2261 << std::endl << "differs from that of data: " << actualLowerChargeData << " - " << actualUpperChargeData
2262 << std::endl;
2263 return -1;
2264 }
2265 }
2266 else {
2267 std::cout << std::endl;
2268 std::cout << "Requested charge range (gen yield) out of limits or upper and lower limit are switched!" << std::endl;
2269 return -1;
2270 }
2271
2272 hMCgeneratedYieldsPrimaries->GetAxis(indexChargeAxisGenYield)->SetRange(lowerChargeBinLimitGenYield, upperChargeBinLimitGenYield);
2273 }
2274
2275 for (Int_t MCid = 0; MCid < AliPID::kSPECIES; MCid++) {
2276 hMCgeneratedYieldsPrimaries->GetAxis(kPidGenYieldMCpid)->SetRange(MCid + 1, MCid + 1);
2277
2278 hMCgenYieldsPrimSpecies[MCid] = hMCgeneratedYieldsPrimaries->Projection(kPidGenYieldPt, "e");
2279 hMCgenYieldsPrimSpecies[MCid]->SetName(Form("hMCgenYieldsPrimSpecies_%s", AliPID::ParticleShortName(MCid)));
2280 hMCgenYieldsPrimSpecies[MCid]->SetTitle(Form("MC truth generated primary yield, %s", AliPID::ParticleName(MCid)));
2281
2282 // Choose the same binning as for the fitted yields, i.e. rebin the histogram (Rebin will create a clone!)
2283 TH1D* temp = (TH1D*)hMCgenYieldsPrimSpecies[MCid]->Rebin(nPtBins, hMCgenYieldsPrimSpecies[MCid]->GetName(), binsPt);
2284 // Delete the old binned histo and take the new binned one
2285 delete hMCgenYieldsPrimSpecies[MCid];
2286 hMCgenYieldsPrimSpecies[MCid] = temp;
2287
2288 hMCgeneratedYieldsPrimaries->GetAxis(kPidGenYieldMCpid)->SetRange(0, -1);
2289 }
2290 }
2291
2292
2293 // Get expected shapes for pT bins
2294 TString Ytitle = "";
2295
2296 // Array index 0 as unused dummy
2297 TH2D* hGenDelta[6][6]; // DeltaSpecies (first index) for species (second index)
2298 TH2D* hGenDeltaMCid[6][6]; // DeltaSpecies (first index) for species (second index)
2299
2300 for (Int_t i = 0; i < 6; i++) {
2301 for (Int_t j = 0; j < 6; j++) {
2302 hGenDelta[i][j] = 0x0;
2303 hGenDeltaMCid[i][j] = 0x0;
2304 }
2305 }
2306
2307 THnSparse* current = 0x0;
2308
2309 THnSparse* hGenEl = dynamic_cast<THnSparse*>(histList->FindObject("hGenEl"));
2310 if (!hGenEl) {
2311 std::cout << "Failed to load expected dEdx signal shape for: Electrons!" << std::endl;
2312 return -1;
2313 }
2314
2315 THnSparse* hGenKa = dynamic_cast<THnSparse*>(histList->FindObject("hGenKa"));
2316 if (!hGenKa) {
2317 std::cout << "Failed to load expected dEdx signal shape for: Kaons!" << std::endl;
2318 return -1;
2319 }
2320
2321 THnSparse* hGenPi = dynamic_cast<THnSparse*>(histList->FindObject("hGenPi"));
2322 if (!hGenPi) {
2323 std::cout << "Failed to load expected dEdx signal shape for: Pions!" << std::endl;
2324 return -1;
2325 }
2326
2327 THnSparse* hGenMu = dynamic_cast<THnSparse*>(histList->FindObject("hGenMu"));
2328 if (!hGenMu) {
2329 std::cout << "Failed to load expected dEdx signal shape for: Muons! Treated muons as pions in the following." << std::endl;
2330 takeIntoAccountMuons = kFALSE;
2331 }
2332
2333 THnSparse* hGenPr = dynamic_cast<THnSparse*>(histList->FindObject("hGenPr"));
2334 if (!hGenPr) {
2335 std::cout << "Failed to load expected dEdx signal shape for: Protons!" << std::endl;
2336 return -1;
2337 }
2338
2339 for (Int_t MCid = kEl; MCid <= kPr; MCid++) {
2340 if (MCid == kEl)
2341 current = hGenEl;
2342 else if (MCid == kKa)
2343 current = hGenKa;
2344 else if (MCid == kMu) {
2345 if (takeIntoAccountMuons)
2346 current = hGenMu;
2347 else
2348 continue; // No histo for muons in this case
2349 }
2350 else if (MCid == kPi)
2351 current = hGenPi;
2352 else if (MCid == kPr)
2353 current = hGenPr;
2354 else
2355 break;
2356
2357 // If desired, rebin considered axis
2358 if (rebin > 1 || rebinDeltaPrime > 1) {
2359 const Int_t nDimensions = current->GetNdimensions();
2360 Int_t rebinFactor[nDimensions];
2361
2362 for (Int_t dim = 0; dim < nDimensions; dim++) {
2363 if (dim == axisGenForMode)
2364 rebinFactor[dim] = rebin;
2365 else if (dim == kPidGenDeltaPrime && rebinDeltaPrime > 1)
2366 rebinFactor[dim] = rebinDeltaPrime;
2367 else
2368 rebinFactor[dim] = 1;
2369 }
2370
2371 THnSparse* temp = current->Rebin(&rebinFactor[0]);
2372 current->Reset();
2373 current = temp;
2374 }
2375
2376 // Set proper errors, if not yet calculated
2377 if (!current->GetCalculateErrors()) {
2378 std::cout << "Re-calculating errors of " << current->GetName() << "..." << std::endl;
2379
2380 current->Sumw2();
2381
2382 Long64_t nBinsTHnSparseGen = current->GetNbins();
2383 Double_t binContentGen = 0;
2384 for (Long64_t bin = 0; bin < nBinsTHnSparseGen; bin++) {
2385 binContentGen = current->GetBinContent(bin);
2386 current->SetBinError(bin, TMath::Sqrt(binContentGen));
2387 }
2388 }
2389
2390 // If desired, restrict centrality range
2391 if (restrictCentralityAxis) {
2392 current->GetAxis(kPidGenCentrality)->SetRange(lowerCentralityBinLimit, upperCentralityBinLimit);
2393 }
2394
2395 // If desired, restrict jet pT range
2396 if (restrictJetPtAxis) {
2397 current->GetAxis(kPidGenJetPt)->SetRange(lowerJetPtBinLimit, upperJetPtBinLimit);
2398 }
2399
2400 // If desired, restrict charge range
2401 if (restrictCharge) {
2402 const Int_t indexChargeAxisGen = GetAxisByTitle(current, "Charge (e_{0})");
2403 if (indexChargeAxisGen < 0) {
2404 std::cout << "Error: Charge axis not found for gen histogram!" << std::endl;
2405 return -1;
2406 }
2407
2408 Int_t lowerChargeBinLimitGen = -1;
2409 Int_t upperChargeBinLimitGen = -2;
2410 Double_t actualLowerChargeGen = -999;
2411 Double_t actualUpperChargeGen = -999;
2412
2413 // Add subtract a very small number to avoid problems with values right on the border between to bins
2414 if (chargeMode == kNegCharge) {
2415 lowerChargeBinLimitGen = current->GetAxis(indexChargeAxisGen)->FindBin(-1. + 0.001);
2416 upperChargeBinLimitGen = current->GetAxis(indexChargeAxisGen)->FindBin(0. - 0.001);
2417 }
2418 else if (chargeMode == kPosCharge) {
2419 lowerChargeBinLimitGen = current->GetAxis(indexChargeAxisGen)->FindBin(0. + 0.001);
2420 upperChargeBinLimitGen = current->GetAxis(indexChargeAxisGen)->FindBin(1. - 0.001);
2421 }
2422
2423 // Check if the values look reasonable
2424 if (lowerChargeBinLimitGen <= upperChargeBinLimitGen && lowerChargeBinLimitGen >= 1
2425 && upperChargeBinLimitGen <= current->GetAxis(indexChargeAxisGen)->GetNbins()) {
2426 actualLowerChargeGen = current->GetAxis(indexChargeAxisGen)->GetBinLowEdge(lowerChargeBinLimitGen);
2427 actualUpperChargeGen = current->GetAxis(indexChargeAxisGen)->GetBinUpEdge(upperChargeBinLimitGen);
2428
2429 if (TMath::Abs(actualLowerChargeGen - actualLowerChargeData) > 1e-4 ||
2430 TMath::Abs(actualUpperChargeGen - actualUpperChargeData) > 1e-4) {
2431 std::cout << std::endl;
2432 std::cout << "Error: Charge range gen: " << actualLowerChargeGen << " - " << actualUpperChargeGen
2433 << std::endl << "differs from that of data: " << actualLowerChargeData << " - " << actualUpperChargeData
2434 << std::endl;
2435 return -1;
2436 }
2437 }
2438 else {
2439 std::cout << std::endl;
2440 std::cout << "Requested charge range (gen) out of limits or upper and lower limit are switched!" << std::endl;
2441 return -1;
2442 }
2443
2444 current->GetAxis(indexChargeAxisGen)->SetRange(lowerChargeBinLimitGen, upperChargeBinLimitGen);
2445 }
2446
2447
2448
2449 for (Int_t selectBin = 1; selectBin <= 4; selectBin++) {
2450 Int_t selectMCid = (selectBin >= 3) ? (selectBin+1) : selectBin;
2451
2452 current->GetAxis(kPidGenSelectSpecies)->SetRange(selectBin, selectBin);
2453
2454 Ytitle = Form("#Delta%s_{%s} = dE/dx %s <dE/dx>_{%s} (arb. units)", useDeltaPrime ? "'" : "",
2455 partShortName[selectMCid - 1].Data(), useDeltaPrime ? "/" : "-",
2456 partShortName[selectMCid - 1].Data());
2457
2458 TH2* hGenCurrent = 0x0;
2459 if (!useIdentifiedGeneratedSpectra) {
2460 hGenDelta[selectMCid][MCid] = current->Projection(genAxis, axisGenForMode, "e");
2461 hGenDelta[selectMCid][MCid]->SetName(Form("hGenDelta%sFor%s", partShortName[selectMCid - 1].Data(),
2462 partShortName[MCid - 1].Data()));
2463 hGenCurrent = hGenDelta[selectMCid][MCid];
2464 }
2465 else {
2466 current->GetAxis(kPidGenMCpid)->SetRange(MCid, MCid);
2467 hGenDeltaMCid[selectMCid][MCid] = current->Projection(genAxis, axisGenForMode, "e");
2468 hGenDeltaMCid[selectMCid][MCid]->SetName(Form("hGenDelta%sForMCid%s", partShortName[selectMCid - 1].Data(),
2469 partShortName[MCid - 1].Data()));
2470
2471 hGenCurrent = hGenDeltaMCid[selectMCid][MCid];
2472 current->GetAxis(kPidGenMCpid)->SetRange(0, -1);
2473 }
2474
2475 hGenCurrent->GetYaxis()->SetTitle(Ytitle.Data());
2476 hGenCurrent->SetLineColor(getLineColor(MCid));
2477 hGenCurrent->SetMarkerColor(getLineColor(MCid));
2478 hGenCurrent->SetLineWidth(2);
2479 hGenCurrent->SetLineStyle(2);
2480 hGenCurrent->SetMarkerStyle(20);
2481 hGenCurrent->GetXaxis()->SetTitleOffset(1.0);
2482 }
2483
2484 current->GetAxis(kPidGenSelectSpecies)->SetRange(0, -1);
2485 }
2486
2487 // Free a lot of memory for the following procedure. Histogram is not needed anymore (only its projections)
2488 delete f;
2489
2490 // Save intermediate results
2491 //TODO save intermediate TOF results
2492 saveInterF->cd();
2493
2494 if (hMCdata)
2495 hMCdata->Write();
2496
2497 for (Int_t i = 0; i < 6; i++) {
2498 for (Int_t j = 0; j < 6; j++) {
2499 if (hGenDelta[i][j])
2500 hGenDelta[i][j]->Write();
2501
2502 if (hGenDeltaMCid[i][j])
2503 hGenDeltaMCid[i][j]->Write();
2504 }
2505 }
2506
2507 for (Int_t slice = 0; (mode == kPMpT) ? slice < nPtBins : slice < hFractionPions->GetXaxis()->GetNbins(); slice++) {
2508 if (mode == kPMpT && (slice < pSliceLow || slice > pSliceHigh))
2509 continue;
2510
2511 if(hDeltaPi[slice])
2512 hDeltaPi[slice]->Write();
2513 if(hDeltaEl[slice])
2514 hDeltaEl[slice]->Write();
2515 if(hDeltaKa[slice])
2516 hDeltaKa[slice]->Write();
2517 if(hDeltaPr[slice])
2518 hDeltaPr[slice]->Write();
2519
2520 if (plotIdentifiedSpectra) {
2521 for (Int_t species = 0; species < 5; species++) {
2522 hDeltaElMC[slice][species]->Write();
2523 hDeltaKaMC[slice][species]->Write();
2524 hDeltaPiMC[slice][species]->Write();
2525 hDeltaPrMC[slice][species]->Write();
2526 }
2527 }
2528 }
2529
2530 // File may not be closed because the projections are needed in the following!
2531 //saveInterF->Close();
2532
2533 // Save some first results for the final output
2534 TString saveFName = fileName;
2535 saveFName = Form("%s_results_%s__%s_%d_reg%d_regFac%.2f_%s%s%s%s%s.root", saveFName.ReplaceAll(".root", "").Data(),
2536 useLogLikelihood ? (useWeightsForLogLikelihood ? "weightedLLFit" : "LLFit") : "ChiSquareFit",
2537 modeShortName[mode].Data(), fitMethod, regularisation, regularisationFactor,
2538 muonFractionHandlingShortName[muonFractionHandlingParameter].Data(),
2539 useIdentifiedGeneratedSpectra ? "_idSpectra" : "",
2540 restrictCentralityAxis ? Form("_centrality%.0f_%.0f", actualLowerCentrality, actualUpperCentrality) : "",
2541 restrictJetPtAxis ? Form("_jetPt%.1f_%.1f", actualLowerJetPt, actualUpperJetPt) : "",
2542 chargeString.Data());
2543 TFile *saveF = TFile::Open(saveFName.Data(), "RECREATE");
2544 saveF->cd();
2545
2546 if (hFractionElectrons)
2547 hFractionElectrons->Write(0, TObject::kWriteDelete);
2548
2549 if (hFractionKaons)
2550 hFractionKaons->Write(0, TObject::kWriteDelete);
2551
2552 if (hFractionPions)
2553 hFractionPions->Write(0, TObject::kWriteDelete);
2554
2555 if (hFractionProtons)
2556 hFractionProtons->Write(0, TObject::kWriteDelete);
2557
2558 if (hFractionMuons)
2559 hFractionMuons->Write(0, TObject::kWriteDelete);
2560
2561 if (hFractionSummed)
2562 hFractionSummed->Write(0, TObject::kWriteDelete);
2563
2564 if (hFractionElectronsMC)
2565 hFractionElectronsMC->Write(0, TObject::kWriteDelete);
2566
2567 if (hFractionKaonsMC)
2568 hFractionKaonsMC->Write(0, TObject::kWriteDelete);
2569
2570 if (hFractionPionsMC)
2571 hFractionPionsMC->Write(0, TObject::kWriteDelete);
2572
2573 if (hFractionMuonsMC)
2574 hFractionMuonsMC->Write(0, TObject::kWriteDelete);
2575
2576 if (hFractionProtonsMC)
2577 hFractionProtonsMC->Write(0, TObject::kWriteDelete);
2578
2579
2580 if (hYieldElectrons)
2581 hYieldElectrons->Write(0, TObject::kWriteDelete);
2582
2583 if (hYieldKaons)
2584 hYieldKaons->Write(0, TObject::kWriteDelete);
2585
2586 if (hYieldPions)
2587 hYieldPions->Write(0, TObject::kWriteDelete);
2588
2589 if (hYieldProtons)
2590 hYieldProtons->Write(0, TObject::kWriteDelete);
2591
2592 if (hYieldMuons)
2593 hYieldMuons->Write(0, TObject::kWriteDelete);
2594
2595 if (hYieldElectronsMC)
2596 hYieldElectronsMC->Write(0, TObject::kWriteDelete);
2597
2598 if (hYieldMuonsMC)
2599 hYieldMuonsMC->Write(0, TObject::kWriteDelete);
2600
2601 if (hYieldKaonsMC)
2602 hYieldKaonsMC->Write(0, TObject::kWriteDelete);
2603
2604 if (hYieldPionsMC)
2605 hYieldPionsMC->Write(0, TObject::kWriteDelete);
2606
2607 if (hYieldProtonsMC)
2608 hYieldProtonsMC->Write(0, TObject::kWriteDelete);
2609
2610 if (hYieldSummedMC)
2611 hYieldSummedMC->Write(0, TObject::kWriteDelete);
2612
2613
2614 if (hRatioToPiElectrons)
2615 hRatioToPiElectrons->Write(0, TObject::kWriteDelete);
2616
2617 if (hRatioToPiMuons)
2618 hRatioToPiMuons->Write(0, TObject::kWriteDelete);
2619
2620 if (hRatioToPiKaons)
2621 hRatioToPiKaons->Write(0, TObject::kWriteDelete);
2622
2623 if (hRatioToPiProtons)
2624 hRatioToPiProtons->Write(0, TObject::kWriteDelete);
2625
2626 if (hRatioToPiElectronsMC)
2627 hRatioToPiElectronsMC->Write(0, TObject::kWriteDelete);
2628
2629 if (hRatioToPiMuonsMC)
2630 hRatioToPiMuonsMC->Write(0, TObject::kWriteDelete);
2631
2632 if (hRatioToPiKaonsMC)
2633 hRatioToPiKaonsMC->Write(0, TObject::kWriteDelete);
2634
2635 if (hRatioToPiProtonsMC)
2636 hRatioToPiProtonsMC->Write(0, TObject::kWriteDelete);
2637
2638
2639 // Dummy histo to create generic legend entries from
2640 TH1D* hMCmuonsAndPionsDummy = 0x0;
2641 if (plotIdentifiedSpectra && firstValidSlice >= 0) {
2642 hMCmuonsAndPionsDummy = new TH1D(*hDeltaPiMC[firstValidSlice][kPi]);
2643 hMCmuonsAndPionsDummy->SetLineColor(getLineColor(kMuPlusPi));
2644 hMCmuonsAndPionsDummy->SetMarkerColor(getLineColor(kMuPlusPi));
2645 hMCmuonsAndPionsDummy->SetName("hMCmuonsAndPionsDummy");
2646 }
2647
2648
2649 muonFractionThresholdForFitting = 0.;//OLD 0.295;
2650 muonFractionThresholdBinForFitting = (mode == kPMpT) ? FindMomentumBin(binsPt, muonFractionThresholdForFitting) : -1;
2651
2652 electronFractionThresholdForFitting = 9.;
2653 electronFractionThresholdBinForFitting = (mode == kPMpT) ? FindMomentumBin(binsPt, electronFractionThresholdForFitting) : -1;
2654
2655 lastPtForCallOfGetElectronFraction = pHigh + 10.; // Make sure that this value is higher than in any call during the fit
2656
2657 fElectronFraction = new TF1("fElectronFraction", Form("[0]+(x<%f)*[1]*(x-%f)", electronFractionThresholdForFitting,
2658 electronFractionThresholdForFitting),
2659 pLow, pHigh);
2660 fElectronFraction->SetParameters(0.01, 0.0);
2661
2662
2663
2664 TString speciesLabel[4] = {"El", "Ka", "Pi", "Pr" };
2665
2666 const Double_t binWidthFitHisto = 1.0; // Not used any longer
2667
2668 // In case of regularisation, the actual number of x bins and the (for pT: logs of their) bin centres are required
2669 Int_t numXBins = 0;
2670 Double_t* xBinCentres = 0x0;
2671 Double_t* xBinStatisticalWeight = 0x0;
2672 Double_t* xBinStatisticalWeightError = 0x0;
2673
2674 // Set the number of parameters per x bin:
2675 // Regularisation only implemented for simultaneous fit.
2676 const Int_t numParamsPerXbin = AliPID::kSPECIES + 1; // Fractions of each species + total yield in x bin
2677
2678 // Construct the array of all the parameters that are to be regularised, i.e. only the FREE fractions
2679 // and NOT the total yields or the x bin
2680 Int_t nParToRegulariseSimultaneousFit = 0;
2681 Int_t* indexParametersToRegularise = 0x0;
2682 Int_t* lastNotFixedIndexOfParameters = 0x0;
2683
2684 if (regularisation > 0) {
2685 Int_t xBinIndexTemp = 0;
2686 Int_t internalParIndexTemp = 0;
2687
2688 // Loop twice over data: Determine the number of bins in the first iteration, allocate the memory and fill in the 2. iteration
2689 for (Int_t i = 0; i < 2; i++) {
2690 if (i == 1) {
2691 if (numXBins == 0) {
2692 printf("No bins for fitting! Exiting...\n");
2693
2694 return -1;
2695 }
2696 if (nParToRegulariseSimultaneousFit == 0) {
2697 printf("No parameters to regularise! Exiting...\n");
2698
2699 return -1;
2700 }
2701
2702 xBinCentres = new Double_t[numXBins];
2703 xBinStatisticalWeight = new Double_t[numXBins];
2704 xBinStatisticalWeightError = new Double_t[numXBins];
2705
2706 indexParametersToRegularise = new Int_t[nParToRegulariseSimultaneousFit];
2707
2708 lastNotFixedIndexOfParameters = new Int_t[numParamsPerXbin];
2709
2710 // Set last not fixed index of parameter to numXBins, i.e. a index larger than any existing index.
2711 // This will not restrict the parameter regularisation range. In the following, the range for electrons
2712 // and muons will be restricted
2713 for (Int_t iPar = 0; iPar < numParamsPerXbin; iPar++)
2714 lastNotFixedIndexOfParameters[iPar] = numXBins;
2715 }
2716
2717
2718 for (Int_t slice = 0; (mode == kPMpT) ? slice < nPtBins : slice < hFractionPions->GetXaxis()->GetNbins(); slice++) {
2719 if (mode == kPMpT && (slice < pSliceLow || slice > pSliceHigh))
2720 continue;
2721
2722 // There won't (actually: shouldn't) be tracks with a pT larger than the jet pT
2723 if (mode == kPMpT && restrictJetPtAxis && binsPt[slice] >= actualUpperJetPt)
2724 continue;
2725
2726 const Int_t pBinLowProjLimit = (mode == kPMpT) ? hYieldPt->GetXaxis()->FindBin(binsPt[slice] + 1e-5) : slice + 1;
2727 const Int_t pBinUpProjLimit = (mode == kPMpT) ? hYieldPt->GetXaxis()->FindBin(binsPt[slice + 1]- 1e-5) : slice + 1;
2728
2729 // NOTE: In case of regularisation, only the simultaneous fit values will be used, i.e. totalYield and not allDeltaSpecies!
2730
2731 // Also take into account bin width in delta(Prime) plots -> Multiply by binWidthFitHisto
2732 Double_t totalYieldError = 0;
2733 const Double_t totalYield = binWidthFitHisto * hYieldPt->IntegralAndError(pBinLowProjLimit, pBinUpProjLimit, totalYieldError);
2734 totalYieldError *= binWidthFitHisto;
2735
2736 if (totalYield <= 0)
2737 continue;
2738
2739 if (i == 1) {
2740 if (mode == kPMpT)
2741 // Take the logarithm in case of pT
2742 xBinCentres[xBinIndexTemp] = TMath::Log((binsPt[slice + 1] + binsPt[slice]) / 2.);
2743 else
2744 xBinCentres[xBinIndexTemp] = hFractionPions->GetXaxis()->GetBinCenter(slice + 1);
2745
2746 xBinStatisticalWeight[xBinIndexTemp] = totalYield;
2747
2748 // NOTE: The total yield is a fact - a number w/o error. However, one assigns this error here to use it
2749 // to calculate the effective weighting for the weighted likelihood fit (and the error is only used for this).
2750 // So, it is more like a weighting than an error...
2751 xBinStatisticalWeightError[xBinIndexTemp] = totalYieldError;
2752
2753
2754 // Mark the fractions for all species except for electrons and muons in this bin for regularisation
2755 for (Int_t speciesIndex = 0; speciesIndex < AliPID::kSPECIES - 2; speciesIndex++)
2756 indexParametersToRegularise[internalParIndexTemp++] = numParamsPerXbin * xBinIndexTemp + speciesIndex;
2757
2758 // Also mark electrons for regularisation in this bin, if not fixed
2759 if( !(mode == kPMpT && slice >= electronFractionThresholdBinForFitting) ) {
2760 indexParametersToRegularise[internalParIndexTemp++] = numParamsPerXbin * xBinIndexTemp + 3;
2761 }
2762 else {
2763 // Set the index of the last x bin in which the parameter is not fixed.
2764 // If the parameter is fixed in all x bins, this index will be -1.
2765 if (xBinIndexTemp - 1 < lastNotFixedIndexOfParameters[3])
2766 lastNotFixedIndexOfParameters[3] = xBinIndexTemp - 1;
2767 }
2768
2769 // Also mark muons for regularisation in this bin, if not fixed
2770 if( !(mode != kPMpT || slice >= muonFractionThresholdBinForFitting) ) {
2771 indexParametersToRegularise[internalParIndexTemp++] = numParamsPerXbin * xBinIndexTemp + 4;
2772 }
2773 else {
2774 // Set the index of the last x bin in which the parameter is not fixed.
2775 // If the parameter is fixed in all x bins, this index will be -1.
2776 if (xBinIndexTemp - 1 < lastNotFixedIndexOfParameters[4])
2777 lastNotFixedIndexOfParameters[4] = xBinIndexTemp - 1;
2778 }
2779
2780 xBinIndexTemp++;
2781 }
2782
2783 if (i == 0) {
2784 nParToRegulariseSimultaneousFit += AliPID::kSPECIES - 2; // Fracs for all species in this bin except for electrons and muons
2785
2786 if( !(mode == kPMpT && slice >= electronFractionThresholdBinForFitting) )
2787 nParToRegulariseSimultaneousFit++; // Also regularise electrons in this bin (not fixed)
2788
2789 if( !(mode != kPMpT || slice >= muonFractionThresholdBinForFitting) )
2790 nParToRegulariseSimultaneousFit++; // Also regularise muons in this bin (not fixed)
2791
2792 numXBins++;
2793 }
2794 }
2795 }
2796 }
2797 AliTPCPIDmathFit* mathFit = 0x0;
2798
2799 if (regularisation > 0) {
2800 mathFit = (fitMethod == 2) ? AliTPCPIDmathFit::Instance(numXBins, 4, 1810)
2801 : AliTPCPIDmathFit::Instance(numXBins, 1, 1810);
2802 }
2803 else {
2804 mathFit = (fitMethod == 2) ? AliTPCPIDmathFit::Instance(1, 4, 1810)
2805 : AliTPCPIDmathFit::Instance(1, 1, 1810);
2806 }
2807
2808 mathFit->SetDebugLevel(0);
2809 mathFit->SetEpsilon(5e-05);
2810 mathFit->SetMaxCalls(1e8);
2811
2812 mathFit->SetMinimisationStrategy(minimisationStrategy);
2813
2814 mathFit->SetUseLogLikelihood(useLogLikelihood);
2815 mathFit->SetUseWeightsForLogLikelihood(useWeightsForLogLikelihood);
2816
2817 if (fitMethod == 2) {
2818 // If the deltaPrime range is large enough, we artificially get a factor 4 in statistics by looking at the four
2819 // different deltaPrimeSpecies, which have (except for binning effects) the same information.
2820 // Therefore, to get the "real" statistical error, we need to multiply the obtained error by sqrt(4) = 2
2821 mathFit->SetScaleFactorError(2.);
2822 }
2823
2824 mathFit->SetRegularisation(regularisation, regularisationFactor);
2825
2826 // Number of parameters for fitting
2827 const Int_t nPar = 11;
2828
2829 // Fracs of each species + total yield in x bin
2830 const Int_t nParSimultaneousFit = AliPID::kSPECIES + 1;
2831
2832 // Fracs of each species in x bin + tot yield in x bin
2833 const Int_t nParSimultaneousFitRegularised = numXBins * (AliPID::kSPECIES + 1);
2834
2835 if (regularisation > 0) {
2836 if (!mathFit->SetParametersToRegularise(nParToRegulariseSimultaneousFit, numParamsPerXbin, indexParametersToRegularise,
2837 lastNotFixedIndexOfParameters, xBinCentres, xBinStatisticalWeight,
2838 xBinStatisticalWeightError))
2839 return -1;
2840 }
2841
2842 delete xBinCentres;
2843 xBinCentres = 0x0;
2844
2845 delete xBinStatisticalWeight;
2846 xBinStatisticalWeight = 0x0;
2847
2848 delete xBinStatisticalWeightError;
2849 xBinStatisticalWeight = 0x0;
2850
2851 delete indexParametersToRegularise;
2852 indexParametersToRegularise = 0x0;
2853
2854 delete lastNotFixedIndexOfParameters;
2855 lastNotFixedIndexOfParameters = 0x0;
2856
2857
2858
2859 gFractionElectronsData = new TGraphErrors(numXBins);
2860
2861 // Fit each slice with sum of 4/5 shapes with means and sigmas fixed from last fitting step
2862 // For electrons: Fit up to certain pT bin and use constant value for higher momenta
2863
2864 // Two iterations required for regularisation
2865 Bool_t regularisedFitDone = kFALSE;
2866 Double_t reducedChiSquareRegularisation = -1;
2867
2868 Double_t gausParamsSimultaneousFitRegularised[nParSimultaneousFitRegularised];
2869 Double_t parameterErrorsOutRegularised[nParSimultaneousFitRegularised];
2870 Double_t lowParLimitsSimultaneousFitRegularised[nParSimultaneousFitRegularised];
2871 Double_t upParLimitsSimultaneousFitRegularised[nParSimultaneousFitRegularised];
2872 Double_t stepSizeSimultaneousFitRegularised[nParSimultaneousFitRegularised];
2873
2874 for (Int_t i = 0; i < nParSimultaneousFitRegularised; i++) {
2875 gausParamsSimultaneousFitRegularised[i] = 0;
2876 parameterErrorsOutRegularised[i] = 0;
2877 lowParLimitsSimultaneousFitRegularised[i] = 0;
2878 upParLimitsSimultaneousFitRegularised[i] = 0;
2879 stepSizeSimultaneousFitRegularised[i] = 0;
2880 }
2881
2882 mathFit->ClearRefHistos();
2883
2884
2885 const Int_t nParUsed = (fitMethod == 2) ? ((regularisation <= 0) ? nParSimultaneousFit: nParSimultaneousFitRegularised) : nPar;
2886 Double_t parameterErrorsOut[nParUsed];
2887 Double_t covMatrix[nParUsed][nParUsed];
2888
2889 for (Int_t iter = 0; iter < 2; iter++) {
2890 if (regularisation <= 0 && iter == 0)
2891 continue; // Only one iteration w/o regularisation
2892
2893 Int_t currXbin = 0;
2894
2895 for (Int_t slice = 0; (mode == kPMpT) ? slice < nPtBins : slice < hFractionPions->GetXaxis()->GetNbins(); slice++) {
2896 if (mode == kPMpT && (slice < pSliceLow || slice > pSliceHigh))
2897 continue;
2898
2899 // There won't (actually: shouldn't) be tracks with a pT larger than the jet pT
2900 if (mode == kPMpT && restrictJetPtAxis && binsPt[slice] >= actualUpperJetPt)
2901 continue;
2902
2903 if (regularisation <= 0) {
2904 if (mode == kPMpT)
2905 std::cout << "Fitting range " << binsPt[slice] << " GeV/c < Pt < " << binsPt[slice + 1] << " GeV/c..." << std::endl;
2906 else {
2907 std::cout << "Fitting range " << hFractionPions->GetXaxis()->GetBinLowEdge(slice + 1) << " < " << modeShortName[mode].Data() << " < ";
2908 std::cout << hFractionPions->GetXaxis()->GetBinUpEdge(slice + 1) << "..." << std::endl;
2909 }
2910 }
2911
2912 // Add/subtract some very small offset to be sure not to sit on the bin boundary, when looking for the integration/projection limits.
2913 const Int_t pBinLowProjLimit = (mode == kPMpT) ? hYieldPt->GetXaxis()->FindBin(binsPt[slice] + 1e-5) : slice + 1;
2914 const Int_t pBinUpProjLimit = (mode == kPMpT) ? hYieldPt->GetXaxis()->FindBin(binsPt[slice + 1]- 1e-5) : slice + 1;
2915
2916 // Also take into account bin width in delta(Prime) plots -> Multiply by binWidthFitHisto
2917 const Double_t totalYield = binWidthFitHisto * hYieldPt->Integral(pBinLowProjLimit, pBinUpProjLimit);
2918
2919 if (totalYield <= 0) {
2920 std::cout << "Skipped bin (yield is zero)!" << std::endl;
2921 continue;
2922 }
2923
2924 const Double_t allDeltaPion = hDeltaPi[slice]->Integral();
2925 const Double_t allDeltaElectron = hDeltaEl[slice]->Integral();
2926 const Double_t allDeltaKaon = hDeltaKa[slice]->Integral();
2927 const Double_t allDeltaProton = hDeltaPr[slice]->Integral();
2928
2929 // inverseBinWidth = 1.0, if the raw yield for each bin is requested.
2930 // If divided by the bin size, the histograms give "yield per unit pT in the corresponding bin" or dN/dpT
2931 Double_t inverseBinWidth = (mode == kPMpT) ? 1.0 / (binsPt[slice + 1] - binsPt[slice])
2932 : 1.0 / hYieldPt->GetBinWidth(slice + 1);
2933
2934 TH1D *hGenDeltaElForElProj = 0x0, *hGenDeltaKaForElProj = 0x0, *hGenDeltaPiForElProj = 0x0, *hGenDeltaPrForElProj = 0x0;
2935 TH1D *hGenDeltaElForKaProj = 0x0, *hGenDeltaKaForKaProj = 0x0, *hGenDeltaPiForKaProj = 0x0, *hGenDeltaPrForKaProj = 0x0;
2936 TH1D *hGenDeltaElForPiProj = 0x0, *hGenDeltaKaForPiProj = 0x0, *hGenDeltaPiForPiProj = 0x0, *hGenDeltaPrForPiProj = 0x0;
2937 TH1D *hGenDeltaElForMuProj = 0x0, *hGenDeltaKaForMuProj = 0x0, *hGenDeltaPiForMuProj = 0x0, *hGenDeltaPrForMuProj = 0x0;
2938 TH1D *hGenDeltaElForPrProj = 0x0, *hGenDeltaKaForPrProj = 0x0, *hGenDeltaPiForPrProj = 0x0, *hGenDeltaPrForPrProj = 0x0;
2939
2940 TH2D* hGenDeltaUsed[6][6];
2941 if (useIdentifiedGeneratedSpectra) {
2942 for (Int_t i = 0; i < 6; i++) {
2943 for (Int_t j = 0; j < 6; j++) {
2944 hGenDeltaUsed[i][j] = hGenDeltaMCid[i][j];
2945 }
2946 }
2947 }
2948 else {
2949 for (Int_t i = 0; i < 6; i++) {
2950 for (Int_t j = 0; j < 6; j++) {
2951 hGenDeltaUsed[i][j] = hGenDelta[i][j];
2952 }
2953 }
2954 }
2955
2956 hGenDeltaElForElProj =(TH1D*)hGenDeltaUsed[kEl][kEl]->ProjectionY(Form("hGenDeltaElForElProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2957 hGenDeltaKaForElProj =(TH1D*)hGenDeltaUsed[kKa][kEl]->ProjectionY(Form("hGenDeltaKaForElProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2958 hGenDeltaPiForElProj =(TH1D*)hGenDeltaUsed[kPi][kEl]->ProjectionY(Form("hGenDeltaPiForElProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2959 hGenDeltaPrForElProj =(TH1D*)hGenDeltaUsed[kPr][kEl]->ProjectionY(Form("hGenDeltaPrForElProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2960
2961 hGenDeltaElForKaProj =(TH1D*)hGenDeltaUsed[kEl][kKa]->ProjectionY(Form("hGenDeltaElForKaProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2962 hGenDeltaKaForKaProj =(TH1D*)hGenDeltaUsed[kKa][kKa]->ProjectionY(Form("hGenDeltaKaForKaProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2963 hGenDeltaPiForKaProj =(TH1D*)hGenDeltaUsed[kPi][kKa]->ProjectionY(Form("hGenDeltaPiForKaProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2964 hGenDeltaPrForKaProj =(TH1D*)hGenDeltaUsed[kPr][kKa]->ProjectionY(Form("hGenDeltaPrForKaProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2965
2966 hGenDeltaElForPiProj =(TH1D*)hGenDeltaUsed[kEl][kPi]->ProjectionY(Form("hGenDeltaElForPiProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2967 hGenDeltaKaForPiProj =(TH1D*)hGenDeltaUsed[kKa][kPi]->ProjectionY(Form("hGenDeltaKaForPiProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2968 hGenDeltaPiForPiProj =(TH1D*)hGenDeltaUsed[kPi][kPi]->ProjectionY(Form("hGenDeltaPiForPiProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2969 hGenDeltaPrForPiProj =(TH1D*)hGenDeltaUsed[kPr][kPi]->ProjectionY(Form("hGenDeltaPrForPiProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2970
2971 if (takeIntoAccountMuons) {
2972 hGenDeltaElForMuProj =(TH1D*)hGenDeltaUsed[kEl][kMu]->ProjectionY(Form("hGenDeltaElForMuProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2973 hGenDeltaKaForMuProj =(TH1D*)hGenDeltaUsed[kKa][kMu]->ProjectionY(Form("hGenDeltaKaForMuProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2974 hGenDeltaPiForMuProj =(TH1D*)hGenDeltaUsed[kPi][kMu]->ProjectionY(Form("hGenDeltaPiForMuProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2975 hGenDeltaPrForMuProj =(TH1D*)hGenDeltaUsed[kPr][kMu]->ProjectionY(Form("hGenDeltaPrForMuProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2976 }
2977
2978 hGenDeltaElForPrProj =(TH1D*)hGenDeltaUsed[kEl][kPr]->ProjectionY(Form("hGenDeltaElForPrProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2979 hGenDeltaKaForPrProj =(TH1D*)hGenDeltaUsed[kKa][kPr]->ProjectionY(Form("hGenDeltaKaForPrProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2980 hGenDeltaPiForPrProj =(TH1D*)hGenDeltaUsed[kPi][kPr]->ProjectionY(Form("hGenDeltaPiForPrProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2981 hGenDeltaPrForPrProj =(TH1D*)hGenDeltaUsed[kPr][kPr]->ProjectionY(Form("hGenDeltaPrForPrProj%d", slice), pBinLowProjLimit, pBinUpProjLimit, "e");
2982
2983
2984
2985 if (fitMethod == 2) {
2986 // Normalise generated histos to TOTAL number of GENERATED particles for this species (i.e. including
2987 // entries that lie in the under or overflow bin), so that situations in which the generated spectra lie
2988 // at least partly outside the histo are treated properly. To find the total number of generated particle
2989 // species X, one can just take the integral of the generated histo for DeltaX (which should include all
2990 // generated entries) and apply the same normalisation factor to all other DeltaSpecies.
2991 // Also set some cosmetics
2992
2993 // Generated electrons
2994 Double_t normEl = normaliseHist(hGenDeltaElForElProj, -1);
2995 normaliseHist(hGenDeltaKaForElProj, normEl);
2996 normaliseHist(hGenDeltaPiForElProj, normEl);
2997 normaliseHist(hGenDeltaPrForElProj, normEl);
2998
2999
3000 // Generated kaons
3001 Double_t normKa = normaliseHist(hGenDeltaKaForKaProj, -1);
3002 normaliseHist(hGenDeltaElForKaProj, normKa);
3003 normaliseHist(hGenDeltaPiForKaProj, normKa);
3004 normaliseHist(hGenDeltaPrForKaProj, normKa);
3005
3006
3007 // Generated pions
3008 Double_t normPi = normaliseHist(hGenDeltaPiForPiProj, -1);
3009 normaliseHist(hGenDeltaElForPiProj, normPi);
3010 normaliseHist(hGenDeltaKaForPiProj, normPi);
3011 normaliseHist(hGenDeltaPrForPiProj, normPi);
3012
3013
3014 Double_t normMu = 1;
3015 if (takeIntoAccountMuons) {
3016 // Generated pions
3017 // Since masses of muons and pions are so similar, the normalisation scheme should still work when looking at deltaPion instead
3018 normMu = normaliseHist(hGenDeltaPiForMuProj, -1);
3019 normaliseHist(hGenDeltaElForMuProj, normMu);
3020 normaliseHist(hGenDeltaKaForMuProj, normMu);
3021 normaliseHist(hGenDeltaPrForMuProj, normMu);
3022 }
3023
3024
3025 // Generated protons
3026 Double_t normPr = normaliseHist(hGenDeltaPrForPrProj, -1);
3027 normaliseHist(hGenDeltaElForPrProj, normPr);
3028 normaliseHist(hGenDeltaKaForPrProj, normPr);
3029 normaliseHist(hGenDeltaPiForPrProj, normPr);
3030 }
3031 else {
3032 // Normalise generated histos to total number of particles for this delta
3033 // and also set some cosmetics
3034
3035 // DeltaEl
3036 normaliseHist(hGenDeltaElForElProj);
3037 normaliseHist(hGenDeltaElForKaProj);
3038 normaliseHist(hGenDeltaElForPiProj);
3039 if (takeIntoAccountMuons)
3040 normaliseHist(hGenDeltaElForMuProj);
3041 normaliseHist(hGenDeltaElForPrProj);
3042
3043 // DeltaKa
3044 normaliseHist(hGenDeltaKaForElProj);
3045 normaliseHist(hGenDeltaKaForKaProj);
3046 normaliseHist(hGenDeltaKaForPiProj);
3047 if (takeIntoAccountMuons)
3048 normaliseHist(hGenDeltaKaForMuProj);
3049 normaliseHist(hGenDeltaKaForPrProj);
3050
3051 // DeltaPi
3052 normaliseHist(hGenDeltaPiForElProj);
3053 normaliseHist(hGenDeltaPiForKaProj);
3054 normaliseHist(hGenDeltaPiForPiProj);
3055 if (takeIntoAccountMuons)
3056 normaliseHist(hGenDeltaPiForMuProj);
3057 normaliseHist(hGenDeltaPiForPrProj);
3058
3059 // DeltaPr
3060 normaliseHist(hGenDeltaPrForElProj);
3061 normaliseHist(hGenDeltaPrForKaProj);
3062 normaliseHist(hGenDeltaPrForPiProj);
3063 if (takeIntoAccountMuons)
3064 normaliseHist(hGenDeltaPrForMuProj);
3065 normaliseHist(hGenDeltaPrForPrProj);
3066 }
3067
3068
3069 TF1* totalDeltaPion = 0x0;
3070 TF1* totalDeltaKaon = 0x0;
3071 TF1* totalDeltaProton = 0x0;
3072 TF1* totalDeltaElectron = 0x0;
3073
3074 TLegend* legend = 0x0;
3075
3076 if (iter == 1) { // Only needed for second iteration (= the only iteration w/o regularisation)
3077 // The number of parameters and their values will always be adjusted, such that using nPar parameters is fine
3078 totalDeltaPion = new TF1(Form("totalDeltaPion_slice%d", slice), (fitMethod == 2) ? multiGaussFitDeltaPi : multiGaussFit,
3079 xLow, xUp, nPar);
3080 setUpFitFunction(totalDeltaPion, nBins);
3081
3082 totalDeltaKaon = new TF1(Form("totalDeltaKaon_slice%d", slice), (fitMethod == 2) ? multiGaussFitDeltaKa : multiGaussFit,
3083 xLow, xUp, nPar);
3084 setUpFitFunction(totalDeltaKaon, nBins);
3085
3086 totalDeltaProton = new TF1(Form("totalDeltaProton_slice%d", slice), (fitMethod == 2) ? multiGaussFitDeltaPr : multiGaussFit,
3087 xLow, xUp, nPar);
3088 setUpFitFunction(totalDeltaProton, nBins);
3089
3090 totalDeltaElectron = new TF1(Form("totalDeltaElectron_slice%d", slice),
3091 (fitMethod == 2) ? multiGaussFitDeltaEl : multiGaussFit,
3092 xLow, xUp, nPar);
3093 setUpFitFunction(totalDeltaElectron, nBins);
3094
3095 // Legend is the same for all \Delta "species" plots
3096 legend = new TLegend(0.722126, 0.605932, 0.962069, 0.925932);
3097 legend->SetBorderSize(0);
3098 legend->SetFillColor(0);
3099 if (plotIdentifiedSpectra)
3100 legend->SetNColumns(2);
3101 legend->AddEntry((TObject*)0x0, "Fit", "");
3102 if (plotIdentifiedSpectra)
3103 legend->AddEntry((TObject*)0x0, identifiedLabels[isMC].Data(), "");
3104
3105 legend->AddEntry(hDeltaPi[slice], "Data", "Lp");
3106 if (plotIdentifiedSpectra)
3107 legend->AddEntry((TObject*)0x0, "", "");
3108
3109 legend->AddEntry(totalDeltaPion, "Multi-template fit", "L");
3110 if (plotIdentifiedSpectra)
3111 legend->AddEntry(hMCmuonsAndPionsDummy, "#mu + #pi", "Lp");
3112
3113 if (takeIntoAccountMuons)
3114 legend->AddEntry(hGenDeltaPiForMuProj, "#mu", "Lp");
3115 else if (plotIdentifiedSpectra)
3116 legend->AddEntry((TObject*)0x0, "", "");
3117 if (plotIdentifiedSpectra)
3118 legend->AddEntry(hDeltaPiMC[slice][kMu - 1], "#mu", "Lp");
3119
3120 legend->AddEntry(hGenDeltaPiForPiProj, takeIntoAccountMuons ? "#pi" : "#pi + #mu", "Lp");
3121 if (plotIdentifiedSpectra)
3122 legend->AddEntry(hDeltaPiMC[slice][kPi - 1], "#pi", "Lp");
3123
3124 legend->AddEntry(hGenDeltaPiForKaProj, "K", "Lp");
3125 if (plotIdentifiedSpectra)
3126 legend->AddEntry(hDeltaPiMC[slice][kKa - 1], "K", "Lp");
3127
3128 legend->AddEntry(hGenDeltaPiForPrProj, "p", "Lp");
3129 if (plotIdentifiedSpectra)
3130 legend->AddEntry(hDeltaPiMC[slice][kPr - 1], "p", "Lp");
3131
3132 legend->AddEntry(hGenDeltaPiForElProj, "e", "Lp");
3133 if (plotIdentifiedSpectra)
3134 legend->AddEntry(hDeltaPiMC[slice][kEl -1], "e", "Lp");
3135 }
3136
3137
3138 // Allow tolerance of +-2% (for delta -> assume dEdx = 80 and take +-2%)
3139 //const Double_t peakTolerance = (useDeltaPrime ? 0.8 : 1.0) / hGenDeltaElForElProj->GetXaxis()->GetBinWidth(1);
3140 //const Double_t shiftStepSize = 0.01;
3141 const Double_t peakTolerance = (useDeltaPrime ? 0.02 : 1.6);
3142 const Double_t shiftStepSize = 0.01;
3143
3144 // Assume fractions vs. pT to be smooth. Allow 1 sigma variations from bin to bin. For small pT, the error will be very small.
3145 // Therefore, allow at least a change of some percent.
3146 const Double_t nSigma = 1.;
3147 const Double_t minChange = 1.0; // This disables the sigma restriction
3148
3149 Double_t fractionPions = (muonContamination ? 0.87 : 0.88);
3150
3151 Double_t fractionErrorUpPions = 1.;
3152 Double_t fractionErrorLowPions = 0.;
3153
3154 Int_t xBinInit = 0;
3155 if (initialiseWithFractionsFromFile) {
3156 Double_t xBinCentre = (mode == kPMpT) ? (binsPt[slice + 1] + binsPt[slice]) / 2.
3157 : hYieldPt->GetXaxis()->GetBinCenter(slice + 1);
3158 xBinInit = hInitFracPi->GetXaxis()->FindBin(xBinCentre);
3159 fractionPions = hInitFracPi->GetBinContent(xBinInit) + (muonContamination ? hInitFracMu->GetBinContent(xBinInit) : 0.);
3160 }
3161 else {
3162 // Set found fraction from last slice, if available. Note: Current bin for slice = slice + 1
3163 // => Bin for last slice = slice
3164 if (hFractionPions->GetBinContent(slice) > 0 && hFractionPions->GetBinError(slice) > 0) {
3165 fractionPions = hFractionPions->GetBinContent(slice);
3166 fractionErrorUpPions = TMath::Min(1.0, fractionPions + TMath::Max(minChange, nSigma * hFractionPions->GetBinError(slice)));
3167 fractionErrorLowPions = TMath::Max(0.0, fractionPions - TMath::Max(minChange, nSigma * hFractionPions->GetBinError(slice)));
3168 }
3169 }
3170
3171 Double_t fractionKaons = 0.08;
3172 Double_t fractionErrorUpKaons = 1.;
3173 Double_t fractionErrorLowKaons = 0.;
3174
3175 if (initialiseWithFractionsFromFile) {
3176 fractionKaons = hInitFracKa->GetBinContent(xBinInit);
3177 }
3178 else {
3179 if (hFractionKaons->GetBinContent(slice) > 0 && hFractionKaons->GetBinError(slice) > 0) {
3180 fractionKaons = hFractionKaons->GetBinContent(slice);
3181 fractionErrorUpKaons = TMath::Min(1.0, fractionKaons + TMath::Max(minChange, nSigma * hFractionKaons->GetBinError(slice)));
3182 fractionErrorLowKaons = TMath::Max(0.0, fractionKaons - TMath::Max(minChange, nSigma * hFractionKaons->GetBinError(slice)));
3183 }
3184 }
3185
3186 Double_t fractionProtons = 0.02;
3187 Double_t fractionErrorUpProtons = 1.;
3188 Double_t fractionErrorLowProtons = 0.;
3189
3190 if (initialiseWithFractionsFromFile) {
3191 fractionProtons = hInitFracPr->GetBinContent(xBinInit);
3192 }
3193 else {
3194 if (hFractionProtons->GetBinContent(slice) > 0 && hFractionProtons->GetBinError(slice) > 0) {
3195 fractionProtons = hFractionProtons->GetBinContent(slice);
3196 fractionErrorUpProtons = TMath::Min(1.0, fractionProtons +
3197 TMath::Max(minChange, nSigma * hFractionProtons->GetBinError(slice)));
3198 fractionErrorLowProtons = TMath::Max(0.0, fractionProtons -
3199 TMath::Max(minChange, nSigma * hFractionProtons->GetBinError(slice)));
3200 }
3201 }
3202
3203 Double_t fractionElectrons = (takeIntoAccountMuons ? 0.01 : 0.02);
3204 Double_t fractionErrorUpElectrons = 1.;
3205 Double_t fractionErrorLowElectrons = 0.;
3206
3207 if (initialiseWithFractionsFromFile) {
3208 fractionElectrons = hInitFracEl->GetBinContent(xBinInit);
3209 }
3210 else {
3211 if (hFractionElectrons->GetBinContent(slice) > 0 && hFractionElectrons->GetBinError(slice) > 0) {
3212 fractionElectrons = hFractionElectrons->GetBinContent(slice);
3213 fractionErrorUpElectrons = TMath::Min(1.0, fractionElectrons +
3214 TMath::Max(minChange, nSigma * hFractionElectrons->GetBinError(slice)));
3215 fractionErrorLowElectrons = TMath::Max(0.0, fractionElectrons -
3216 TMath::Max(minChange, nSigma * hFractionElectrons->GetBinError(slice)));
3217 }
3218 }
3219
3220 Double_t fractionMuons = (takeIntoAccountMuons ? 0.01 : 0.);
3221 Double_t fractionErrorUpMuons = 1.;
3222 Double_t fractionErrorLowMuons = 0.;
3223 if (!takeIntoAccountMuons) {
3224 fractionErrorUpMuons = 0.;
3225 fractionErrorLowMuons = 0.;
3226 }
3227 else {
3228 if (initialiseWithFractionsFromFile) {
3229 fractionMuons = hInitFracMu->GetBinContent(xBinInit);
3230 }
3231 else {
3232 if (hFractionMuons->GetBinContent(slice) > 0 && hFractionMuons->GetBinError(slice) > 0) {
3233 fractionMuons = hFractionMuons->GetBinContent(slice);
3234 fractionErrorUpMuons = TMath::Min(1.0, fractionMuons + TMath::Max(minChange, nSigma * hFractionMuons->GetBinError(slice)));
3235 fractionErrorLowMuons = TMath::Max(0.0, fractionMuons - TMath::Max(minChange, nSigma * hFractionMuons->GetBinError(slice)));
3236 }
3237 }
3238 }
3239
3240 Double_t gausParamsPi[nPar] = {
3241 fractionPions,
3242 fractionKaons,
3243 fractionProtons,
3244 fractionElectrons,
3245 fractionMuons,
3246 allDeltaPion,
3247 0,
3248 0,
3249 0,
3250 0,
3251 0
3252 };
3253
3254 Double_t gausParamsEl[nPar] = {
3255 fractionPions,
3256 fractionKaons,
3257 fractionProtons,
3258 fractionElectrons,
3259 fractionMuons,
3260 allDeltaElectron,
3261 0,
3262 0,
3263 0,
3264 0,
3265 0
3266 };
3267
3268 Double_t gausParamsKa[nPar] = {
3269 fractionPions,
3270 fractionKaons,
3271 fractionProtons,
3272 fractionElectrons,
3273 fractionMuons,
3274 allDeltaKaon,
3275 0,
3276 0,
3277 0,
3278 0,
3279 0
3280 };
3281
3282 Double_t gausParamsPr[nPar] = {
3283 fractionPions,
3284 fractionKaons,
3285 fractionProtons,
3286 fractionElectrons,
3287 fractionMuons,
3288 allDeltaProton,
3289 0,
3290 0,
3291 0,
3292 0,
3293 0
3294 };
3295
3296 Double_t lowParLimitsPi[nPar] = {
3297 fractionErrorLowPions,
3298 fractionErrorLowKaons,
3299 fractionErrorLowProtons,
3300 fractionErrorLowElectrons,
3301 fractionErrorLowMuons,
3302 allDeltaPion,
3303 -peakTolerance,
3304 -peakTolerance,
3305 -peakTolerance,
3306 -peakTolerance,
3307 -peakTolerance
3308 };
3309
3310 Double_t lowParLimitsEl[nPar] = {
3311 fractionErrorLowPions,
3312 fractionErrorLowKaons,
3313 fractionErrorLowProtons,
3314 fractionErrorLowElectrons,
3315 fractionErrorLowMuons,
3316 allDeltaElectron,
3317 -peakTolerance,
3318 -peakTolerance,
3319 -peakTolerance,
3320 -peakTolerance,
3321 -peakTolerance
3322 };
3323
3324 Double_t lowParLimitsKa[nPar] = {
3325 fractionErrorLowPions,
3326 fractionErrorLowKaons,
3327 fractionErrorLowProtons,
3328 fractionErrorLowElectrons,
3329 fractionErrorLowMuons,
3330 allDeltaKaon,
3331 -peakTolerance,
3332 -peakTolerance,
3333 -peakTolerance,
3334 -peakTolerance,
3335 -peakTolerance
3336 };
3337
3338 Double_t lowParLimitsPr[nPar] = {
3339 fractionErrorLowPions,
3340 fractionErrorLowKaons,
3341 fractionErrorLowProtons,
3342 fractionErrorLowElectrons,
3343 fractionErrorLowMuons,
3344 allDeltaProton,
3345 -peakTolerance,
3346 -peakTolerance,
3347 -peakTolerance,
3348 -peakTolerance
3349 -peakTolerance
3350 };
3351
3352
3353 Double_t upParLimitsPi[nPar] = {
3354 fractionErrorUpPions,
3355 fractionErrorUpKaons,
3356 fractionErrorUpProtons,
3357 fractionErrorUpElectrons,
3358 fractionErrorUpMuons,
3359 allDeltaPion,
3360 peakTolerance,
3361 peakTolerance,
3362 peakTolerance,
3363 peakTolerance,
3364 peakTolerance
3365 };
3366
3367 Double_t upParLimitsEl[nPar] = {
3368 fractionErrorUpPions,
3369 fractionErrorUpKaons,
3370 fractionErrorUpProtons,
3371 fractionErrorUpElectrons,
3372 fractionErrorUpMuons,
3373 allDeltaElectron,
3374 peakTolerance,
3375 peakTolerance,
3376 peakTolerance,
3377 peakTolerance,
3378 peakTolerance
3379 };
3380
3381 Double_t upParLimitsKa[nPar] = {
3382 fractionErrorUpPions,
3383 fractionErrorUpKaons,
3384 fractionErrorUpProtons,
3385 fractionErrorUpElectrons,
3386 fractionErrorUpMuons,
3387 allDeltaKaon,
3388 peakTolerance,
3389 peakTolerance,
3390 peakTolerance,
3391 peakTolerance,
3392 peakTolerance
3393 };
3394
3395 Double_t upParLimitsPr[nPar] = {
3396 fractionErrorUpPions,
3397 fractionErrorUpKaons,
3398 fractionErrorUpProtons,
3399 fractionErrorUpElectrons,
3400 fractionErrorUpMuons,
3401 allDeltaProton,
3402 peakTolerance,
3403 peakTolerance,
3404 peakTolerance,
3405 peakTolerance,
3406 peakTolerance,
3407 };
3408
3409 Double_t stepSize[nPar] = {
3410 0.1,
3411 0.1,
3412 0.1,
3413 0.1,
3414 (takeIntoAccountMuons ? 0.1 : 0.),
3415
3416 0.0,
3417
3418 enableShift ? shiftStepSize : 0.,
3419 enableShift ? shiftStepSize : 0.,
3420 enableShift ? shiftStepSize : 0.,
3421 enableShift ? shiftStepSize : 0.,
3422 (enableShift && takeIntoAccountMuons) ? shiftStepSize : 0.
3423 };
3424
3425
3426 Double_t gausParamsSimultaneousFit[nParSimultaneousFit] = {
3427 fractionPions,
3428 fractionKaons,
3429 fractionProtons,
3430 fractionElectrons,
3431 fractionMuons,
3432 totalYield
3433 // No shifts because they do not make too much sense (different eta + possible deviations from Bethe-Bloch in one x-Bin)
3434 };
3435
3436 Double_t lowParLimitsSimultaneousFit[nParSimultaneousFit] = {
3437 fractionErrorLowPions,
3438 fractionErrorLowKaons,
3439 fractionErrorLowProtons,
3440 fractionErrorLowElectrons,
3441 fractionErrorLowMuons,
3442 totalYield
3443 };
3444
3445 Double_t upParLimitsSimultaneousFit[nParSimultaneousFit] = {
3446 fractionErrorUpPions,
3447 fractionErrorUpKaons,
3448 fractionErrorUpProtons,
3449 fractionErrorUpElectrons,
3450 fractionErrorUpMuons,
3451 totalYield
3452 };
3453
3454 Double_t stepSizeSimultaneousFit[nParSimultaneousFit] = {
3455 0.1,
3456 0.1,
3457 0.1,
3458 0.1,
3459 (takeIntoAccountMuons ? 0.1 : 0.),
3460
3461 0.0
3462 };
3463
3464 if (regularisation <= 0 && iter == 1) {
3465 // In case of no regularisation, do the fit of the electron fraction here (compare comment below)
3466 if (mode == kPMpT && slice == electronFractionThresholdBinForFitting)
3467 hFractionElectrons->Fit(fElectronFraction, "N", "", lowFittingBoundElectronFraction, electronFractionThresholdForFitting);
3468 }
3469
3470 if ((regularisation > 0 && iter == 0) || (regularisation <= 0 && iter == 1)) {
3471 // Set the electron fraction to the negative pT -> A function will be used
3472 // to evaluate the electron fraction for each bin above the threshold
3473 if(mode == kPMpT && slice >= electronFractionThresholdBinForFitting) {
3474 // In case of no regularisation, mathFit has no information about the fraction of other x bins.
3475 // Thus, the electron fraction is evaluated and set here. For the case w/ regularisation,
3476 // just "-pT" is set and the electron fraction will be evaluated during the fit.
3477 Double_t fixElectronFraction = (regularisation <= 0) ? fElectronFraction->Eval((binsPt[slice + 1] + binsPt[slice]) / 2.)
3478 : -(binsPt[slice + 1] + binsPt[slice]) / 2.;
3479
3480 if (regularisation <= 0) {
3481 fixElectronFraction = TMath::Min(1.0, fixElectronFraction);
3482 fixElectronFraction = TMath::Max(0.0, fixElectronFraction);
3483 }
3484
3485 gausParamsPi[3] = fixElectronFraction;
3486 lowParLimitsPi[3] = fixElectronFraction;
3487 upParLimitsPi[3] = fixElectronFraction;
3488
3489 gausParamsEl[3] = fixElectronFraction;
3490 lowParLimitsEl[3] = fixElectronFraction;
3491 upParLimitsEl[3] = fixElectronFraction;
3492
3493 gausParamsKa[3] = fixElectronFraction;
3494 lowParLimitsKa[3] = fixElectronFraction;
3495 upParLimitsKa[3] = fixElectronFraction;
3496
3497 gausParamsPr[3] = fixElectronFraction;
3498 lowParLimitsPr[3] = fixElectronFraction;
3499 upParLimitsPr[3] = fixElectronFraction;
3500
3501 stepSize[3] = 0.0;
3502
3503 gausParamsSimultaneousFit[3] = fixElectronFraction;
3504 lowParLimitsSimultaneousFit[3] = fixElectronFraction;
3505 upParLimitsSimultaneousFit[3] = fixElectronFraction;
3506
3507 stepSizeSimultaneousFit[3] = 0.0;
3508 }
3509
3510
3511 // Set muon fraction equal to (some modified) electron fraction above some threshold, which should be a reasonable approximation:
3512 // Fixed muon fraction < 0 does this job within the fitting functions
3513 if(mode != kPMpT || slice >= muonFractionThresholdBinForFitting) {
3514 // "Abuse" the muon fraction to forward the pT, which can then be used to get some modified electron fraction
3515 const Double_t fixedValue = -(binsPt[slice] + binsPt[slice + 1]) / 2.;
3516 gausParamsPi[4] = fixedValue;
3517 lowParLimitsPi[4] = fixedValue;
3518 upParLimitsPi[4] = fixedValue;
3519
3520 gausParamsEl[4] = fixedValue;
3521 lowParLimitsEl[4] = fixedValue;
3522 upParLimitsEl[4] = fixedValue;
3523
3524 gausParamsKa[4] = fixedValue;
3525 lowParLimitsKa[4] = fixedValue;
3526 upParLimitsKa[4] = fixedValue;
3527
3528 gausParamsPr[4] = fixedValue;
3529 lowParLimitsPr[4] = fixedValue;
3530 upParLimitsPr[4] = fixedValue;
3531
3532 stepSize[4] = 0.;
3533
3534 gausParamsSimultaneousFit[4] = fixedValue;
3535 lowParLimitsSimultaneousFit[4] = fixedValue;
3536 upParLimitsSimultaneousFit[4] = fixedValue;
3537
3538 stepSizeSimultaneousFit[4] = 0.0;
3539 }
3540 }
3541
3542 // iter 0 used for initialisation
3543 if (regularisation > 0 && iter == 0) {
3544 const Int_t offset = currXbin * mathFit->GetNumParametersPerXbin();
3545 for (Int_t i = 0; i < mathFit->GetNumParametersPerXbin(); i++) {
3546 gausParamsSimultaneousFitRegularised[offset + i] = gausParamsSimultaneousFit[i];
3547 lowParLimitsSimultaneousFitRegularised[offset + i] = lowParLimitsSimultaneousFit[i];
3548 upParLimitsSimultaneousFitRegularised[offset + i] = upParLimitsSimultaneousFit[i];
3549 stepSizeSimultaneousFitRegularised[offset + i] = stepSizeSimultaneousFit[i];
3550 }
3551 }
3552
3553
3554 if (iter == 1) {
3555 // The parameters are only used for fitMethod < 2. Thus, they can be set for these methods,
3556 // although a different method is used
3557 totalDeltaPion->SetParameters(gausParamsPi);
3558 totalDeltaElectron->SetParameters(gausParamsEl);
3559 totalDeltaKaon->SetParameters(gausParamsKa);
3560 totalDeltaProton->SetParameters(gausParamsPr);
3561 }
3562
3563 const TString binInfo = (mode == kPMpT) ? Form("%.2f_Pt_%.2f", binsPt[slice], binsPt[slice + 1])
3564 : Form("%.2f_%s_%.2f", hFractionPions->GetXaxis()->GetBinLowEdge(slice + 1),
3565 modeShortName[mode].Data(), hFractionPions->GetXaxis()->GetBinUpEdge(slice + 1));
3566
3567 const TString binInfoTitle = (mode == kPMpT) ? Form("%.2f < Pt <%.2f", binsPt[slice], binsPt[slice + 1])
3568 : Form("%.2f < %s < %.2f", hFractionPions->GetXaxis()->GetBinLowEdge(slice + 1),
3569 modeShortName[mode].Data(),
3570 hFractionPions->GetXaxis()->GetBinUpEdge(slice + 1));
3571
3572 const TString fitFuncSuffix = (mode == kPMpT) ? Form("%.3f_Pt_%.3f", binsPt[slice], binsPt[slice + 1])
3573 : Form("%.3f_%s_%.3f", hFractionPions->GetXaxis()->GetBinLowEdge(slice + 1),
3574 modeShortName[mode].Data(),
3575 hFractionPions->GetXaxis()->GetBinUpEdge(slice + 1));
3576
3577 if (iter == 1) {
3578 for (Int_t species = 0; species < 4; species++) {
3579 cSingleFit[slice][species] = new TCanvas(Form("cSingleFit_%s_%s", binInfo.Data(), speciesLabel[species].Data()),
3580 Form("single fit for %s (%s)", binInfoTitle.Data(), speciesLabel[species].Data()),
3581 1366, 768);
3582 cSingleFit[slice][species]->Divide(1, 2, 0.01, 0.);
3583 cSingleFit[slice][species]->GetPad(1)->SetRightMargin(0.001);
3584 cSingleFit[slice][species]->GetPad(2)->SetRightMargin(0.001);
3585 cSingleFit[slice][species]->GetPad(1)->SetTopMargin(0.001);
3586 cSingleFit[slice][species]->GetPad(2)->SetTopMargin(0.01);
3587 cSingleFit[slice][species]->GetPad(1)->SetBottomMargin(0.01);
3588
3589 cSingleFit[slice][species]->GetPad(1)->SetGridx(kTRUE);
3590 cSingleFit[slice][species]->GetPad(2)->SetGridx(kTRUE);
3591 cSingleFit[slice][species]->GetPad(1)->SetGridy(kTRUE);
3592 cSingleFit[slice][species]->GetPad(2)->SetGridy(kTRUE);
3593
3594 cSingleFit[slice][species]->GetPad(1)->SetLogy(kTRUE);
3595 cSingleFit[slice][species]->GetPad(1)->SetLogx(kTRUE);
3596 cSingleFit[slice][species]->GetPad(2)->SetLogx(kTRUE);
3597 }
3598 }
3599
3600 // Problem: For p < 0.5 GeV/c, the fractions cannot be simply taken from the parameters because
3601 // not all entries of the histogram are inside the considered range.
3602 // Also: Small deviations of summed fractions from one if taking the fractions from different Delta species histos.
3603 // Therefore: Add up the integrals of the individual fits (\Delta species) and take the fraction of the sum
3604 Double_t integralTotal = 0;
3605 Double_t integralPions = 0, integralKaons = 0, integralProtons = 0, integralElectrons = 0, integralMuons = 0;
3606
3607 Double_t integralPionsDeltaPion = 0, integralPionsDeltaElectron = 0, integralPionsDeltaKaon = 0, integralPionsDeltaProton = 0;
3608 Double_t integralElectronsDeltaPion = 0, integralElectronsDeltaElectron = 0, integralElectronsDeltaKaon = 0,
3609 integralElectronsDeltaProton = 0;
3610 Double_t integralKaonsDeltaPion = 0, integralKaonsDeltaElectron = 0, integralKaonsDeltaKaon = 0, integralKaonsDeltaProton = 0;
3611 Double_t integralProtonsDeltaPion = 0, integralProtonsDeltaElectron = 0, integralProtonsDeltaKaon = 0,
3612 integralProtonsDeltaProton = 0;
3613 Double_t integralMuonsDeltaPion = 0, integralMuonsDeltaElectron = 0, integralMuonsDeltaKaon = 0, integralMuonsDeltaProton = 0;
3614
3615 /*
3616 Double_t integralErrorPions = 0, integralErrorKaons = 0, integralErrorProtons = 0, integralErrorElectrons = 0;
3617
3618 Double_t integralErrorPionsDeltaPion = 0, integralErrorPionsDeltaElectron = 0, integralErrorPionsDeltaKaon = 0,
3619 integralErrorPionsDeltaProton = 0;
3620 Double_t integralErrorElectronsDeltaPion = 0, integralErrorElectronsDeltaElectron = 0, integralErrorElectronsDeltaKaon = 0,
3621 integralErrorElectronsDeltaProton = 0;
3622 Double_t integralErrorKaonsDeltaPion = 0, integralErrorKaonsDeltaElectron = 0, integralErrorKaonsDeltaKaon = 0,
3623 integralErrorKaonsDeltaProton = 0;
3624 Double_t integralErrorProtonsDeltaPion = 0, integralErrorProtonsDeltaElectron = 0, integralErrorProtonsDeltaKaon = 0,
3625 integralErrorProtonsDeltaProton = 0;
3626
3627 Double_t integralErrorTotalDeltaPion = 0, integralErrorTotalDeltaElectron = 0, integralErrorTotalDeltaKaon = 0;
3628 Double_t integralErrorTotalDeltaProton = 0;
3629 */
3630
3631 Int_t errFlag = 0;
3632
3633 // Reset temp arrays for next slice
3634 for (Int_t ind = 0; ind < nParUsed; ind++)
3635 parameterErrorsOut[ind] = 0;
3636
3637 // Do not reset, if regularisation is on and the fit is done because the covariance matrix
3638 // will not be changed anymore in this case. On the other hand it will only be calculated once,
3639 // so resetting it would mean that is not available anymore.
3640 if (regularisation <= 0 || !regularisedFitDone) {
3641 for (Int_t i = 0; i < nParUsed; i++) {
3642 for (Int_t j = 0; j < nParUsed; j++) {
3643 covMatrix[i][j] = 0;
3644 }
3645 }
3646 }
3647
3648 Double_t reducedChiSquare = -1;
3649
3650 if (fitMethod == 2) {
3651 if (regularisation <= 0 && iter == 1)
3652 std::cout << "Fitting data simultaneously...." << std::endl << std::endl;
3653
3654 // Add ref histos in initialisation step (w/ reg) or in the only loop (w/o reg)
3655 if ((regularisation > 0 && iter == 0) || (regularisation <= 0 && iter == 1)) {
3656
3657 if (regularisation <= 0)
3658 mathFit->ClearRefHistos();
3659
3660 mathFit->AddRefHisto(hGenDeltaPiForPiProj);
3661 mathFit->AddRefHisto(hGenDeltaPiForKaProj);
3662 mathFit->AddRefHisto(hGenDeltaPiForPrProj);
3663 mathFit->AddRefHisto(hGenDeltaPiForElProj);
3664 if (takeIntoAccountMuons)
3665 mathFit->AddRefHisto(hGenDeltaPiForMuProj);
3666
3667 mathFit->AddRefHisto(hGenDeltaKaForPiProj);
3668 mathFit->AddRefHisto(hGenDeltaKaForKaProj);
3669 mathFit->AddRefHisto(hGenDeltaKaForPrProj);
3670 mathFit->AddRefHisto(hGenDeltaKaForElProj);
3671 if (takeIntoAccountMuons)
3672 mathFit->AddRefHisto(hGenDeltaKaForMuProj);
3673
3674 mathFit->AddRefHisto(hGenDeltaPrForPiProj);
3675 mathFit->AddRefHisto(hGenDeltaPrForKaProj);
3676 mathFit->AddRefHisto(hGenDeltaPrForPrProj);
3677 mathFit->AddRefHisto(hGenDeltaPrForElProj);
3678 if (takeIntoAccountMuons)
3679 mathFit->AddRefHisto(hGenDeltaPrForMuProj);
3680
3681 mathFit->AddRefHisto(hGenDeltaElForPiProj);
3682 mathFit->AddRefHisto(hGenDeltaElForKaProj);
3683 mathFit->AddRefHisto(hGenDeltaElForPrProj);
3684 mathFit->AddRefHisto(hGenDeltaElForElProj);
3685 if (takeIntoAccountMuons)
3686 mathFit->AddRefHisto(hGenDeltaElForMuProj);
3687
3688 // In reg case, fill in the data for this bin and continue with the nex bin
3689 if (regularisation > 0) {
3690 TH1D* hDeltaSpecies[numSimultaneousFits] = { hDeltaPi[slice], hDeltaKa[slice], hDeltaPr[slice], hDeltaEl[slice] };
3691
3692 for (Int_t i = 0; i < numSimultaneousFits; i++) {
3693 mathFit->InputData(hDeltaSpecies[i], currXbin, i, xLow, xUp, -1., kFALSE);
3694 }
3695
3696 currXbin++;
3697 continue;
3698 }
3699 }
3700
3701 if (regularisation > 0 && iter == 1 && !regularisedFitDone) {
3702 std::cout << "Fitting data simultaneously with regularisation...." << std::endl << std::endl;
3703
3704 // TODO At the moment, the covariance matrix is NOT forwarded from TMinuit (has completely different dimensions)
3705 // -> Since it is not used at the moment, this is not necessary. If it is to be used in future,
3706 // this has to be implemented! But one has to be careful, since parameters from different bins then
3707 // depend on each other! Furthermore, there will be no errors for fixed parameters like muon fraction or electron fraction
3708 // above the corresponding threshold in the covariance matrix, but an estimated error will be set manually.
3709 errFlag = errFlag | doSimultaneousFitRegularised(nParSimultaneousFitRegularised, gausParamsSimultaneousFitRegularised,
3710 parameterErrorsOutRegularised, &covMatrix[0][0],
3711 stepSizeSimultaneousFitRegularised,
3712 lowParLimitsSimultaneousFitRegularised,
3713 upParLimitsSimultaneousFitRegularised, reducedChiSquare);
3714 if (errFlag != 0)
3715 std::cout << "errFlag " << errFlag << std::endl << std::endl;
3716
3717 reducedChiSquareRegularisation = reducedChiSquare;
3718
3719 // Since everything is fitted in one go, only do this for the first x bin
3720 // (more convenient to put the fitting in the x bin loop in order to intialise
3721 // the parameters in the same way they are initialised for the fit w/o regularisation.
3722 regularisedFitDone = kTRUE;
3723 }
3724
3725 if (regularisation > 0 && iter == 1) {
3726 // To allow for an identical processing, just forward the parameter results for the current xBin to the
3727 // array used by the standard simultaneous fit. The rest of the code is then the same for regularisation on and off
3728
3729 for (Int_t i = 0; i < mathFit->GetNumParametersPerXbin(); i++) {
3730 const Int_t iRegularised = i + currXbin * mathFit->GetNumParametersPerXbin();
3731
3732 gausParamsSimultaneousFit[i] = gausParamsSimultaneousFitRegularised[iRegularised];
3733 parameterErrorsOut[i] = parameterErrorsOutRegularised[iRegularised];
3734 }
3735
3736 // Same reducedChiSquare for all bins, since only one fit
3737 reducedChiSquare = reducedChiSquareRegularisation;
3738
3739
3740 // Also clear reference histos and load those for the current bin
3741 mathFit->ClearRefHistos();
3742
3743 mathFit->AddRefHisto(hGenDeltaPiForPiProj);
3744 mathFit->AddRefHisto(hGenDeltaPiForKaProj);
3745 mathFit->AddRefHisto(hGenDeltaPiForPrProj);
3746 mathFit->AddRefHisto(hGenDeltaPiForElProj);
3747 if (takeIntoAccountMuons)
3748 mathFit->AddRefHisto(hGenDeltaPiForMuProj);
3749
3750 mathFit->AddRefHisto(hGenDeltaKaForPiProj);
3751 mathFit->AddRefHisto(hGenDeltaKaForKaProj);
3752 mathFit->AddRefHisto(hGenDeltaKaForPrProj);
3753 mathFit->AddRefHisto(hGenDeltaKaForElProj);
3754 if (takeIntoAccountMuons)
3755 mathFit->AddRefHisto(hGenDeltaKaForMuProj);
3756
3757 mathFit->AddRefHisto(hGenDeltaPrForPiProj);
3758 mathFit->AddRefHisto(hGenDeltaPrForKaProj);
3759 mathFit->AddRefHisto(hGenDeltaPrForPrProj);
3760 mathFit->AddRefHisto(hGenDeltaPrForElProj);
3761 if (takeIntoAccountMuons)
3762 mathFit->AddRefHisto(hGenDeltaPrForMuProj);
3763
3764 mathFit->AddRefHisto(hGenDeltaElForPiProj);
3765 mathFit->AddRefHisto(hGenDeltaElForKaProj);
3766 mathFit->AddRefHisto(hGenDeltaElForPrProj);
3767 mathFit->AddRefHisto(hGenDeltaElForElProj);
3768 if (takeIntoAccountMuons)
3769 mathFit->AddRefHisto(hGenDeltaElForMuProj);
3770 }
3771
3772
3773 if (regularisation <= 0) {
3774 TH1D* hDeltaSpecies[numSimultaneousFits] = { hDeltaPi[slice], hDeltaKa[slice], hDeltaPr[slice], hDeltaEl[slice] };
3775 errFlag = errFlag |
3776 doSimultaneousFit(hDeltaSpecies, xLow, xUp, nParSimultaneousFit, gausParamsSimultaneousFit, parameterErrorsOut,
3777 &covMatrix[0][0], stepSizeSimultaneousFit, lowParLimitsSimultaneousFit,
3778 upParLimitsSimultaneousFit, reducedChiSquare);
3779 }
3780
3781 // Forward parameters to single fits
3782 for (Int_t parIndex = 0; parIndex < nPar; parIndex++) {
3783 // Fractions
3784 if (parIndex <= 4) {
3785 totalDeltaPion->SetParameter(parIndex, gausParamsSimultaneousFit[parIndex]);
3786 totalDeltaPion->SetParError(parIndex, parameterErrorsOut[parIndex]);
3787
3788 totalDeltaKaon->SetParameter(parIndex, gausParamsSimultaneousFit[parIndex]);
3789 totalDeltaKaon->SetParError(parIndex, parameterErrorsOut[parIndex]);
3790
3791 totalDeltaProton->SetParameter(parIndex, gausParamsSimultaneousFit[parIndex]);
3792 totalDeltaProton->SetParError(parIndex, parameterErrorsOut[parIndex]);
3793
3794 totalDeltaElectron->SetParameter(parIndex, gausParamsSimultaneousFit[parIndex]);
3795 totalDeltaElectron->SetParError(parIndex, parameterErrorsOut[parIndex]);
3796 }
3797 // Total yield
3798 else if (parIndex == 5) {
3799 totalDeltaPion->SetParameter(parIndex, totalYield);
3800 totalDeltaPion->SetParError(parIndex, 0);
3801
3802 totalDeltaKaon->SetParameter(parIndex, totalYield);
3803 totalDeltaKaon->SetParError(parIndex, 0);
3804
3805 totalDeltaProton->SetParameter(parIndex, totalYield);
3806 totalDeltaProton->SetParError(parIndex, 0);
3807
3808 totalDeltaElectron->SetParameter(parIndex, totalYield);
3809 totalDeltaElectron->SetParError(parIndex, 0);
3810 }
3811 // Hist shifts
3812 else {
3813 totalDeltaPion->SetParameter(parIndex, 0);
3814 totalDeltaPion->SetParError(parIndex, 0);
3815
3816 totalDeltaKaon->SetParameter(parIndex, 0);
3817 totalDeltaKaon->SetParError(parIndex, 0);
3818
3819 totalDeltaProton->SetParameter(parIndex, 0);
3820 totalDeltaProton->SetParError(parIndex, 0);
3821
3822 totalDeltaElectron->SetParameter(parIndex, 0);
3823 totalDeltaElectron->SetParError(parIndex, 0);
3824 }
3825 }
3826
3827 const Bool_t useRegularisation = regularisation > 0;
3828
3829 // Plot single fits
3830
3831 Int_t binLow = -1;
3832 Int_t binHigh = -1;
3833
3834 // DeltaPions
3835 cSingleFit[slice][2]->cd(1);
3836
3837 hDeltaPi[slice]->SetTitle("");
3838 SetReasonableXaxisRange(hDeltaPi[slice], binLow, binHigh);
3839 hDeltaPi[slice]->Draw("e");
3840
3841 fitFuncTotalDeltaPion[slice] = (TF1*)totalDeltaPion->Clone(Form("Fit_Total_DeltaPion_%s", fitFuncSuffix.Data()));
3842
3843 hDeltaPiFitQA[slice] = (TH1D*)hDeltaPi[slice]->Clone(Form("hDeltaPiFitQA_%d", slice));
3844 hDeltaPiFitQA[slice]->GetYaxis()->SetTitle("(Data - Fit) / Data");
3845 hDeltaPiFitQA[slice]->Add(fitFuncTotalDeltaPion[slice], -1);
3846 hDeltaPiFitQA[slice]->Divide(hDeltaPi[slice]);
3847
3848 hDeltaPi[slice]->GetListOfFunctions()->Add(fitFuncTotalDeltaPion[slice]);
3849 fitFuncTotalDeltaPion[slice]->Draw("same");
3850
3851 Double_t* parametersOut = &totalDeltaPion->GetParameters()[0];
3852
3853 hGenDeltaPiForPiProj->Scale(parametersOut[5] * (parametersOut[0] + (muonContamination ? parametersOut[3] : 0)));
3854 shiftHist(hGenDeltaPiForPiProj, parametersOut[6], useRegularisation);
3855 hGenDeltaPiForPiProj->Draw("same");
3856
3857 hGenDeltaPiForKaProj->Scale(parametersOut[5] * parametersOut[1]);
3858 shiftHist(hGenDeltaPiForKaProj, parametersOut[7], useRegularisation);
3859 hGenDeltaPiForKaProj->Draw("same");
3860
3861 hGenDeltaPiForPrProj->Scale(parametersOut[5] * parametersOut[2]);
3862 shiftHist(hGenDeltaPiForPrProj, parametersOut[8], useRegularisation);
3863 hGenDeltaPiForPrProj->Draw("same");
3864
3865 hGenDeltaPiForElProj->Scale(parametersOut[5] * parametersOut[3]);
3866 shiftHist(hGenDeltaPiForElProj, parametersOut[9], useRegularisation);
3867 hGenDeltaPiForElProj->Draw("same");
3868
3869 if (takeIntoAccountMuons) {
3870 hGenDeltaPiForMuProj->Scale(parametersOut[5] * parametersOut[4]);
3871 shiftHist(hGenDeltaPiForMuProj, parametersOut[10], useRegularisation);
3872 hGenDeltaPiForMuProj->Draw("same");
3873 }
3874
3875 if (plotIdentifiedSpectra) {
3876 for (Int_t species = 0; species < 5; species++)
3877 hDeltaPiMC[slice][species]->Draw("same");
3878
3879 // Draw histo for sum of MC muons and pions
3880 TH1D* hMCmuonsAndPions = new TH1D(*hDeltaPiMC[slice][kPi - 1]);
3881 hMCmuonsAndPions->Add(hDeltaPiMC[slice][kMu - 1]);
3882 hMCmuonsAndPions->SetLineColor(getLineColor(kMuPlusPi));
3883 hMCmuonsAndPions->SetMarkerColor(getLineColor(kMuPlusPi));
3884 hMCmuonsAndPions->SetName(Form("%s_muonsAdded", hDeltaPiMC[slice][kPi - 1]->GetName()));
3885 hMCmuonsAndPions->Draw("same");
3886 }
3887
3888 hDeltaPi[slice]->Draw("esame");
3889
3890 legend->Draw();
3891
3892 cSingleFit[slice][2]->cd(2);
3893 hDeltaPiFitQA[slice]->GetYaxis()->SetRangeUser(fitQAaxisLowBound, fitQAaxisUpBound);
3894 hDeltaPiFitQA[slice]->Draw("e");
3895
3896 hReducedChiSquarePt->SetBinContent(slice + 1, 3, reducedChiSquare);
3897
3898 // TMatrixDSym covMatrixPi(nParUsed, &covMatrix[0][0]);
3899
3900 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kPi, parametersOut, parameterErrorsOut, hFractionPions,
3901 hFractionPionsDeltaPion, hFractionElectronsDeltaPion, hFractionKaonsDeltaPion,
3902 hFractionProtonsDeltaPion, hFractionMuonsDeltaPion, hYieldPions, hYieldPionsDeltaPion, hYieldElectronsDeltaPion,
3903 hYieldKaonsDeltaPion, hYieldProtonsDeltaPion, hYieldMuonsDeltaPion, normaliseResults);
3904
3905 // Also set specific muon fractions and yields -> The deltaSpecies histos are not needed here: They will be set together with
3906 // the fraction and yields for all other species
3907 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kMu, parametersOut, parameterErrorsOut, hFractionMuons,
3908 0x0, 0x0, 0x0, 0x0, 0x0, hYieldMuons, 0x0, 0x0, 0x0, 0x0, 0x0, normaliseResults);
3909
3910
3911 // DeltaElectrons
3912 cSingleFit[slice][0]->cd(1);
3913
3914 hDeltaEl[slice]->SetTitle("");
3915 SetReasonableXaxisRange(hDeltaEl[slice], binLow, binHigh);
3916 hDeltaEl[slice]->Draw("e");
3917
3918 fitFuncTotalDeltaElectron[slice] = (TF1*)totalDeltaElectron->Clone(Form("Fit_Total_DeltaElectron_%s", fitFuncSuffix.Data()));
3919
3920 hDeltaElFitQA[slice] = (TH1D*)hDeltaEl[slice]->Clone(Form("hDeltaElFitQA_%d", slice));
3921 hDeltaElFitQA[slice]->GetYaxis()->SetTitle("(Data - Fit) / Data");
3922 hDeltaElFitQA[slice]->Add(fitFuncTotalDeltaElectron[slice], -1);
3923 hDeltaElFitQA[slice]->Divide(hDeltaEl[slice]);
3924
3925 hDeltaEl[slice]->GetListOfFunctions()->Add(fitFuncTotalDeltaElectron[slice]);
3926 fitFuncTotalDeltaElectron[slice]->Draw("same");
3927
3928 parametersOut = &totalDeltaElectron->GetParameters()[0];
3929
3930 hGenDeltaElForPiProj->Scale(parametersOut[5] * (parametersOut[0] + (muonContamination ? parametersOut[3] : 0)));
3931 shiftHist(hGenDeltaElForPiProj, parametersOut[6], useRegularisation);
3932 hGenDeltaElForPiProj->Draw("same");
3933
3934 hGenDeltaElForKaProj->Scale(parametersOut[5] * parametersOut[1]);
3935 shiftHist(hGenDeltaElForKaProj, parametersOut[7], useRegularisation);
3936 hGenDeltaElForKaProj->Draw("same");
3937
3938 hGenDeltaElForPrProj->Scale(parametersOut[5] * parametersOut[2]);
3939 shiftHist(hGenDeltaElForPrProj, parametersOut[8], useRegularisation);
3940 hGenDeltaElForPrProj->Draw("same");
3941
3942 hGenDeltaElForElProj->Scale(parametersOut[5] * parametersOut[3]);
3943 shiftHist(hGenDeltaElForElProj, parametersOut[9], useRegularisation);
3944 hGenDeltaElForElProj->Draw("same");
3945
3946 if (takeIntoAccountMuons) {
3947 hGenDeltaElForMuProj->Scale(parametersOut[5] * parametersOut[4]);
3948 shiftHist(hGenDeltaElForMuProj, parametersOut[10], useRegularisation);
3949 hGenDeltaElForMuProj->Draw("same");
3950 }
3951
3952 if (plotIdentifiedSpectra) {
3953 for (Int_t species = 0; species < 5; species++)
3954 hDeltaElMC[slice][species]->Draw("same");
3955
3956 // Draw histo for sum of MC muons and pions
3957 TH1D* hMCmuonsAndPions = new TH1D(*hDeltaElMC[slice][kPi - 1]);
3958 hMCmuonsAndPions->Add(hDeltaElMC[slice][kMu - 1]);
3959 hMCmuonsAndPions->SetLineColor(getLineColor(kMuPlusPi));
3960 hMCmuonsAndPions->SetMarkerColor(getLineColor(kMuPlusPi));
3961 hMCmuonsAndPions->SetName(Form("%s_muonsAdded", hDeltaElMC[slice][kPi - 1]->GetName()));
3962 hMCmuonsAndPions->Draw("same");
3963 }
3964
3965 hDeltaEl[slice]->Draw("esame");
3966
3967 legend->Draw();
3968
3969 cSingleFit[slice][0]->cd(2);
3970 hDeltaElFitQA[slice]->GetYaxis()->SetRangeUser(fitQAaxisLowBound, fitQAaxisUpBound);
3971 hDeltaElFitQA[slice]->Draw("e");
3972
3973 hReducedChiSquarePt->SetBinContent(slice + 1, 1, reducedChiSquare);
3974
3975 //TMatrixDSym covMatrixEl(nParUsed, &covMatrix[0][0]);
3976
3977 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kEl, parametersOut, parameterErrorsOut, hFractionElectrons,
3978 hFractionPionsDeltaElectron, hFractionElectronsDeltaElectron, hFractionKaonsDeltaElectron,
3979 hFractionProtonsDeltaElectron, hFractionMuonsDeltaElectron, hYieldElectrons, hYieldPionsDeltaElectron,
3980 hYieldElectronsDeltaElectron, hYieldKaonsDeltaElectron, hYieldProtonsDeltaElectron, hYieldMuonsDeltaElectron,
3981 normaliseResults);
3982
3983
3984
3985 // DeltaKaons
3986 cSingleFit[slice][1]->cd(1);
3987
3988 hDeltaKa[slice]->SetTitle("");
3989 SetReasonableXaxisRange(hDeltaKa[slice], binLow, binHigh);
3990 hDeltaKa[slice]->Draw("e");
3991
3992 fitFuncTotalDeltaKaon[slice] = (TF1*)totalDeltaKaon->Clone(Form("Fit_Total_DeltaKaon_%s", fitFuncSuffix.Data()));
3993
3994 hDeltaKaFitQA[slice] = (TH1D*)hDeltaKa[slice]->Clone(Form("hDeltaKaFitQA_%d", slice));
3995 hDeltaKaFitQA[slice]->GetYaxis()->SetTitle("(Data - Fit) / Data");
3996 hDeltaKaFitQA[slice]->Add(fitFuncTotalDeltaKaon[slice], -1);
3997 hDeltaKaFitQA[slice]->Divide(hDeltaKa[slice]);
3998
3999 hDeltaKa[slice]->GetListOfFunctions()->Add(fitFuncTotalDeltaKaon[slice]);
4000 fitFuncTotalDeltaKaon[slice]->Draw("same");
4001
4002 parametersOut = &totalDeltaKaon->GetParameters()[0];
4003
4004 hGenDeltaKaForPiProj->Scale(parametersOut[5] * (parametersOut[0] + (muonContamination ? parametersOut[3] : 0)));
4005 shiftHist(hGenDeltaKaForPiProj, parametersOut[6], useRegularisation);
4006 hGenDeltaKaForPiProj->Draw("same");
4007
4008 hGenDeltaKaForKaProj->Scale(parametersOut[5] * parametersOut[1]);
4009 shiftHist(hGenDeltaKaForKaProj, parametersOut[7], useRegularisation);
4010 hGenDeltaKaForKaProj->Draw("same");
4011
4012 hGenDeltaKaForPrProj->Scale(parametersOut[5] * parametersOut[2]);
4013 shiftHist(hGenDeltaKaForPrProj, parametersOut[8], useRegularisation);
4014 hGenDeltaKaForPrProj->Draw("same");
4015
4016 hGenDeltaKaForElProj->Scale(parametersOut[5] * parametersOut[3]);
4017 shiftHist(hGenDeltaKaForElProj, parametersOut[9], useRegularisation);
4018 hGenDeltaKaForElProj->Draw("same");
4019
4020 if (takeIntoAccountMuons) {
4021 hGenDeltaKaForMuProj->Scale(parametersOut[5] * parametersOut[4]);
4022 shiftHist(hGenDeltaKaForMuProj, parametersOut[10], useRegularisation);
4023 hGenDeltaKaForMuProj->Draw("same");
4024 }
4025
4026 if (plotIdentifiedSpectra) {
4027 for (Int_t species = 0; species < 5; species++)
4028 hDeltaKaMC[slice][species]->Draw("same");
4029
4030 // Draw histo for sum of MC muons and pions
4031 TH1D* hMCmuonsAndPions = new TH1D(*hDeltaKaMC[slice][kPi - 1]);
4032 hMCmuonsAndPions->Add(hDeltaKaMC[slice][kMu - 1]);
4033 hMCmuonsAndPions->SetLineColor(getLineColor(kMuPlusPi));
4034 hMCmuonsAndPions->SetMarkerColor(getLineColor(kMuPlusPi));
4035 hMCmuonsAndPions->SetName(Form("%s_muonsAdded", hDeltaKaMC[slice][kPi - 1]->GetName()));
4036 hMCmuonsAndPions->Draw("same");
4037 }
4038
4039 hDeltaKa[slice]->Draw("esame");
4040
4041 legend->Draw();
4042
4043 cSingleFit[slice][1]->cd(2);
4044 hDeltaKaFitQA[slice]->GetYaxis()->SetRangeUser(fitQAaxisLowBound, fitQAaxisUpBound);
4045 hDeltaKaFitQA[slice]->Draw("e");
4046
4047 hReducedChiSquarePt->SetBinContent(slice + 1, 2, reducedChiSquare);
4048
4049 //TMatrixDSym covMatrixKa(nParUsed, &covMatrix[0][0]);
4050
4051 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kKa, parametersOut, parameterErrorsOut, hFractionKaons,
4052 hFractionPionsDeltaKaon, hFractionElectronsDeltaKaon, hFractionKaonsDeltaKaon, hFractionProtonsDeltaKaon,
4053 hFractionMuonsDeltaKaon, hYieldKaons, hYieldPionsDeltaKaon, hYieldElectronsDeltaKaon, hYieldKaonsDeltaKaon,
4054 hYieldProtonsDeltaKaon, hYieldMuonsDeltaKaon, normaliseResults);
4055
4056
4057
4058 // DeltaProtons
4059 cSingleFit[slice][3]->cd(1);
4060
4061 hDeltaPr[slice]->SetTitle("");
4062 SetReasonableXaxisRange(hDeltaPr[slice], binLow, binHigh);
4063 hDeltaPr[slice]->Draw("e");
4064
4065 fitFuncTotalDeltaProton[slice] = (TF1*)totalDeltaProton->Clone(Form("Fit_Total_DeltaProton_%s", fitFuncSuffix.Data()));
4066
4067 hDeltaPrFitQA[slice] = (TH1D*)hDeltaPr[slice]->Clone(Form("hDeltaPrFitQA_%d", slice));
4068 hDeltaPrFitQA[slice]->GetYaxis()->SetTitle("(Data - Fit) / Data");
4069 hDeltaPrFitQA[slice]->Add(fitFuncTotalDeltaProton[slice], -1);
4070 hDeltaPrFitQA[slice]->Divide(hDeltaPr[slice]);
4071
4072 hDeltaPr[slice]->GetListOfFunctions()->Add(fitFuncTotalDeltaProton[slice]);
4073
4074 fitFuncTotalDeltaProton[slice]->Draw("same");
4075
4076 parametersOut = &totalDeltaProton->GetParameters()[0];
4077
4078 hGenDeltaPrForPiProj->Scale(parametersOut[5] * (parametersOut[0] + (muonContamination ? parametersOut[3] : 0)));
4079 shiftHist(hGenDeltaPrForPiProj, parametersOut[6], useRegularisation);
4080 hGenDeltaPrForPiProj->Draw("same");
4081
4082 hGenDeltaPrForKaProj->Scale(parametersOut[5] * parametersOut[1]);
4083 shiftHist(hGenDeltaPrForKaProj, parametersOut[7], useRegularisation);
4084 hGenDeltaPrForKaProj->Draw("same");
4085
4086 hGenDeltaPrForPrProj->Scale(parametersOut[5] * parametersOut[2]);
4087 shiftHist(hGenDeltaPrForPrProj, parametersOut[8], useRegularisation);
4088 hGenDeltaPrForPrProj->Draw("same");
4089
4090 hGenDeltaPrForElProj->Scale(parametersOut[5] * parametersOut[3]);
4091 shiftHist(hGenDeltaPrForElProj, parametersOut[9], useRegularisation);
4092 hGenDeltaPrForElProj->Draw("same");
4093
4094 if (takeIntoAccountMuons) {
4095 hGenDeltaPrForMuProj->Scale(parametersOut[5] * parametersOut[4]);
4096 shiftHist(hGenDeltaPrForMuProj, parametersOut[10], useRegularisation);
4097 hGenDeltaPrForMuProj->Draw("same");
4098 }
4099
4100 if (plotIdentifiedSpectra) {
4101 for (Int_t species = 0; species < 5; species++)
4102 hDeltaPrMC[slice][species]->Draw("same");
4103
4104 // Draw histo for sum of MC muons and pions
4105 TH1D* hMCmuonsAndPions = new TH1D(*hDeltaPrMC[slice][kPi - 1]);
4106 hMCmuonsAndPions->Add(hDeltaPrMC[slice][kMu - 1]);
4107 hMCmuonsAndPions->SetLineColor(getLineColor(kMuPlusPi));
4108 hMCmuonsAndPions->SetMarkerColor(getLineColor(kMuPlusPi));
4109 hMCmuonsAndPions->SetName(Form("%s_muonsAdded", hDeltaPrMC[slice][kPi - 1]->GetName()));
4110 hMCmuonsAndPions->Draw("same");
4111 }
4112
4113 hDeltaPr[slice]->Draw("esame");
4114
4115 legend->Draw();
4116
4117 cSingleFit[slice][3]->cd(2);
4118 hDeltaPrFitQA[slice]->GetYaxis()->SetRangeUser(fitQAaxisLowBound, fitQAaxisUpBound);
4119 hDeltaPrFitQA[slice]->Draw("e");
4120
4121 hReducedChiSquarePt->SetBinContent(slice + 1, 4, reducedChiSquare);
4122
4123 //TMatrixDSym covMatrixPr(nParUsed, &covMatrix[0][0]);
4124
4125 Double_t normalisationFactor = 1.0;
4126 normalisationFactor = setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kPr, parametersOut, parameterErrorsOut,
4127 hFractionProtons, hFractionPionsDeltaProton, hFractionElectronsDeltaProton,
4128 hFractionKaonsDeltaProton, hFractionProtonsDeltaProton, hFractionMuonsDeltaProton,
4129 hYieldProtons, hYieldPionsDeltaProton, hYieldElectronsDeltaProton,
4130 hYieldKaonsDeltaProton, hYieldProtonsDeltaProton, hYieldMuonsDeltaProton,
4131 normaliseResults);
4132
4133 // Fractions are the same for all plots -> just take deltaPion as default
4134 Double_t sumFractions = hFractionPionsDeltaPion->GetBinContent(slice + 1) +
4135 hFractionElectronsDeltaPion->GetBinContent(slice + 1) + (takeIntoAccountMuons ? hFractionMuonsDeltaPion->GetBinContent(slice + 1) : 0.) +
4136 hFractionKaonsDeltaPion->GetBinContent(slice + 1) + hFractionProtonsDeltaPion->GetBinContent(slice + 1);
4137
4138 hFractionSummed->SetBinContent(slice + 1, sumFractions);
4139 hFractionSummed->SetBinError(slice + 1,
4140 TMath::Sqrt(TMath::Power(hFractionPionsDeltaPion->GetBinError(slice + 1), 2) +
4141 TMath::Power(hFractionElectronsDeltaPion->GetBinError(slice + 1), 2) +
4142 (takeIntoAccountMuons ? TMath::Power(hFractionMuonsDeltaPion->GetBinError(slice + 1), 2) : 0.) +
4143 TMath::Power(hFractionKaonsDeltaPion->GetBinError(slice + 1), 2) +
4144 TMath::Power(hFractionProtonsDeltaPion->GetBinError(slice + 1), 2)));
4145
4146 for (Int_t species = 0; species < 4; species++) {
4147 cSingleFit[slice][species]->Modified();
4148 cSingleFit[slice][species]->Update();
4149 }
4150
4151
4152 // Compute the to-pi ratios with proper error for the current slice
4153 // NOTE: error and covariance matrix are already scaled for the simultaneous fit
4154 // by mathFit (it was checked that all (i.e. also off-diagonal) matrix elements grow by fScaleError^2
4155 // NOTE 2: take the fractions and error from the histogram (takes correct muon and electrons fractions with errors set manually
4156 // in case of fixed fraction; the parameters are fixed, so the elements of the off-diagonal elements of the covariance matrix
4157 // remain zero!). The fractions are then also scaled to sum up to 1 (but correction factor usually close to unity).
4158 // The covariance matrix is NOT scaled like this. Therefore, scale the matrix elements accordingly.
4159 // If the normalisation is not done for the fractions, then this factor is unity by construction.
4160
4161
4162
4163 Double_t covMatrixElementToPiForEl = 0.;
4164 Double_t covMatrixElementToPiForMu = 0.;
4165 Double_t covMatrixElementToPiForKa = 0.;
4166 Double_t covMatrixElementToPiForPr = 0.;
4167
4168 // Get the correct covariance matrix elements and apply the normalisation factor
4169 Int_t parOffset = 0;
4170
4171 // In case of regularisation, there is an offset with respect to the current slice
4172 if (useRegularisation)
4173 parOffset = currXbin * numParamsPerXbin;
4174
4175
4176 covMatrixElementToPiForEl = covMatrix[3 + parOffset][0 + parOffset] * normalisationFactor * normalisationFactor;
4177 covMatrixElementToPiForMu = covMatrix[4 + parOffset][0 + parOffset] * normalisationFactor * normalisationFactor;
4178 covMatrixElementToPiForKa = covMatrix[1 + parOffset][0 + parOffset] * normalisationFactor * normalisationFactor;
4179 covMatrixElementToPiForPr = covMatrix[2 + parOffset][0 + parOffset] * normalisationFactor * normalisationFactor;
4180
4181 Double_t ratio = -999.;
4182 Double_t ratioError = 999.;
4183 Double_t currFractionSpecies = 0.;
4184 Double_t currFractionPions = 0.;
4185 Double_t currFractionErrorSpecies = 0.;
4186 Double_t currFractionErrorPions = 0.;
4187 Double_t covMatrixElementAB = 0.; // NOTE that there is only one covariance matrix (simultaneous fit!)
4188
4189 currFractionPions = hFractionPions->GetBinContent(slice + 1);
4190 currFractionErrorPions = hFractionPions->GetBinError(slice + 1);
4191
4192 // NOTE: Even in case of regularisation, when fractions of different bins become correlated, this does NOT change
4193 // the formula. Only the covariance matrix element for the considered fraction in the SAME slice needs to be taken
4194 // into account. Explanation: f = f(fracA_slice, fracB_slice), this means that \dell f / \dell fracA_slice+-1 = 0 (etc.).
4195 // So, the formula is the same, although the correlation between different slices is contained in the covariance matrix.
4196
4197 // el-to-pi ratio
4198 currFractionSpecies = hFractionElectrons->GetBinContent(slice + 1);
4199 currFractionErrorSpecies = hFractionElectrons->GetBinError(slice + 1);
4200 covMatrixElementAB = covMatrixElementToPiForEl;
4201
4202 GetRatioWithCorrelatedError(currFractionSpecies, currFractionPions, currFractionErrorSpecies, currFractionErrorPions,
4203 covMatrixElementAB, ratio, ratioError);
4204
4205 hRatioToPiElectrons->SetBinContent(slice + 1, ratio);
4206 hRatioToPiElectrons->SetBinError(slice + 1, ratioError);
4207
4208 // mu-to-pi ratio
4209 currFractionSpecies = hFractionMuons->GetBinContent(slice + 1);
4210 currFractionErrorSpecies = hFractionMuons->GetBinError(slice + 1);
4211 covMatrixElementAB = covMatrixElementToPiForMu;
4212
4213 GetRatioWithCorrelatedError(currFractionSpecies, currFractionPions, currFractionErrorSpecies, currFractionErrorPions,
4214 covMatrixElementAB, ratio, ratioError);
4215
4216 hRatioToPiMuons->SetBinContent(slice + 1, ratio);
4217 hRatioToPiMuons->SetBinError(slice + 1, ratioError);
4218
4219
4220 // K-to-pi ratio
4221 currFractionSpecies = hFractionKaons->GetBinContent(slice + 1);
4222 currFractionErrorSpecies = hFractionKaons->GetBinError(slice + 1);
4223 covMatrixElementAB = covMatrixElementToPiForKa;
4224
4225 GetRatioWithCorrelatedError(currFractionSpecies, currFractionPions, currFractionErrorSpecies, currFractionErrorPions,
4226 covMatrixElementAB, ratio, ratioError);
4227
4228 hRatioToPiKaons->SetBinContent(slice + 1, ratio);
4229 hRatioToPiKaons->SetBinError(slice + 1, ratioError);
4230
4231
4232 // p-to-pi ratio
4233 currFractionSpecies = hFractionProtons->GetBinContent(slice + 1);
4234 currFractionErrorSpecies = hFractionProtons->GetBinError(slice + 1);
4235 covMatrixElementAB = covMatrixElementToPiForPr;
4236
4237 GetRatioWithCorrelatedError(currFractionSpecies, currFractionPions, currFractionErrorSpecies, currFractionErrorPions,
4238 covMatrixElementAB, ratio, ratioError);
4239
4240 hRatioToPiProtons->SetBinContent(slice + 1, ratio);
4241 hRatioToPiProtons->SetBinError(slice + 1, ratioError);
4242
4243 /*
4244 for (Int_t i = 0; i < nParUsed; i++) {
4245 for (Int_t j = 0; j < nParUsed; j++) {
4246 printf("\t%e", covMatrix[i][j]);
4247 }
4248 printf("\n");
4249 }
4250 */
4251
4252 currXbin++;
4253 }
4254 //_____________________________________________________________________
4255 // Other methods without simultaneous fitting
4256 else {
4257 Int_t binLow = -1;
4258 Int_t binHigh = -1;
4259
4260 // DeltaPions
4261
4262 std::cout << "Fitting deltaPion...." << std::endl << std::endl;
4263
4264 cSingleFit[slice][2]->cd(1);
4265
4266 mathFit->ClearRefHistos();
4267 mathFit->AddRefHisto(hGenDeltaPiForPiProj);
4268 mathFit->AddRefHisto(hGenDeltaPiForKaProj);
4269 mathFit->AddRefHisto(hGenDeltaPiForPrProj);
4270 mathFit->AddRefHisto(hGenDeltaPiForElProj);
4271 if (takeIntoAccountMuons)
4272 mathFit->AddRefHisto(hGenDeltaPiForMuProj);
4273
4274 errFlag = errFlag |
4275 doFit(hDeltaPi[slice], xLow, xUp, nPar, gausParamsPi, parameterErrorsOut, &covMatrix[0][0],
4276 stepSize, lowParLimitsPi, upParLimitsPi, totalDeltaPion, reducedChiSquare);
4277
4278 hDeltaPi[slice]->SetTitle("");
4279 SetReasonableXaxisRange(hDeltaPi[slice], binLow, binHigh);
4280 hDeltaPi[slice]->Draw("e");
4281
4282 fitFuncTotalDeltaPion[slice] = (TF1*)totalDeltaPion->Clone(Form("Fit_Total_DeltaPion_%s", fitFuncSuffix.Data()));
4283
4284 hDeltaPiFitQA[slice] = (TH1D*)hDeltaPi[slice]->Clone(Form("hDeltaPiFitQA_%d", slice));
4285 hDeltaPiFitQA[slice]->GetYaxis()->SetTitle("(Data - Fit) / Data");
4286 hDeltaPiFitQA[slice]->Add(fitFuncTotalDeltaPion[slice], -1);
4287 hDeltaPiFitQA[slice]->Divide(hDeltaPi[slice]);
4288
4289 hDeltaPi[slice]->GetListOfFunctions()->Add(fitFuncTotalDeltaPion[slice]);
4290 fitFuncTotalDeltaPion[slice]->Draw("same");
4291
4292 Double_t* parametersOut = &gausParamsPi[0];
4293
4294 hGenDeltaPiForPiProj->Scale(gausParamsPi[5] * (gausParamsPi[0] + (muonContamination ? gausParamsPi[3] : 0)));
4295 shiftHist(hGenDeltaPiForPiProj, gausParamsPi[6]);
4296 hGenDeltaPiForPiProj->Draw("same");
4297
4298 hGenDeltaPiForKaProj->Scale(gausParamsPi[5] * gausParamsPi[1]);
4299 shiftHist(hGenDeltaPiForKaProj, gausParamsPi[7]);
4300 hGenDeltaPiForKaProj->Draw("same");
4301
4302 hGenDeltaPiForPrProj->Scale(gausParamsPi[5] * gausParamsPi[2]);
4303 shiftHist(hGenDeltaPiForPrProj, gausParamsPi[8]);
4304 hGenDeltaPiForPrProj->Draw("same");
4305
4306 hGenDeltaPiForElProj->Scale(gausParamsPi[5] * gausParamsPi[3]);
4307 shiftHist(hGenDeltaPiForElProj, gausParamsPi[9]);
4308 hGenDeltaPiForElProj->Draw("same");
4309
4310 if (takeIntoAccountMuons) {
4311 hGenDeltaPiForMuProj->Scale(gausParamsPi[5] * gausParamsPi[4]);
4312 shiftHist(hGenDeltaPiForMuProj, gausParamsPi[10]);
4313 hGenDeltaPiForMuProj->Draw("same");
4314 }
4315
4316 if (plotIdentifiedSpectra) {
4317 for (Int_t species = 0; species < 5; species++)
4318 hDeltaPiMC[slice][species]->Draw("same");
4319
4320 // Draw histo for sum of MC muons and pions
4321 TH1D* hMCmuonsAndPions = new TH1D(*hDeltaPiMC[slice][kPi - 1]);
4322 hMCmuonsAndPions->Add(hDeltaPiMC[slice][kMu - 1]);
4323 hMCmuonsAndPions->SetLineColor(getLineColor(kMuPlusPi));
4324 hMCmuonsAndPions->SetMarkerColor(getLineColor(kMuPlusPi));
4325 hMCmuonsAndPions->SetName(Form("%s_muonsAdded", hDeltaPiMC[slice][kPi - 1]->GetName()));
4326 hMCmuonsAndPions->Draw("same");
4327 }
4328
4329 hDeltaPi[slice]->Draw("esame");
4330
4331 legend->Draw();
4332
4333 cSingleFit[slice][2]->cd(2);
4334 hDeltaPiFitQA[slice]->GetYaxis()->SetRangeUser(fitQAaxisLowBound, fitQAaxisUpBound);
4335 hDeltaPiFitQA[slice]->Draw("e");
4336
4337 hReducedChiSquarePt->SetBinContent(slice + 1, 3, reducedChiSquare);
4338
4339 TMatrixDSym covMatrixPi(nParUsed, &covMatrix[0][0]);
4340
4341 if (fitMethod == 1) {
4342 // Histos are normalised => expression equals integral
4343 integralPions = allDeltaPion * (parametersOut[0] + (muonContamination ? parametersOut[3] : 0));
4344 integralTotal += integralPions;
4345 if (takeIntoAccountMuons) {
4346 integralMuons = allDeltaPion * parametersOut[4];
4347 integralTotal += integralMuons;
4348 }
4349
4350 /*
4351 integralErrorTotalDeltaPion = getErrorOfTotalIntegral(covMatrixPi) * allDeltaPion;
4352
4353 integralErrorPions = getErrorOfPionIntegral(covMatrixPi) * allDeltaPion;
4354 */
4355
4356 integralPionsDeltaPion = integralPions;
4357
4358 // Compare comment above
4359 integralElectronsDeltaPion = allDeltaPion * parametersOut[3];
4360 integralKaonsDeltaPion = allDeltaPion * parametersOut[1];
4361 integralProtonsDeltaPion = allDeltaPion * parametersOut[2];
4362 integralMuonsDeltaPion = allDeltaPion * parametersOut[4];
4363
4364 /*
4365 integralErrorPionsDeltaPion = integralErrorPions;
4366
4367 integralErrorElectronsDeltaPion = allDeltaPion * parameterErrorsOut[3];
4368 integralErrorKaonsDeltaPion = allDeltaPion * parameterErrorsOut[1];
4369 integralErrorProtonsDeltaPion = allDeltaPion * parameterErrorsOut[2];
4370 */
4371 }
4372 else {
4373 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kPi, parametersOut, parameterErrorsOut, hFractionPions,
4374 hFractionPionsDeltaPion, hFractionElectronsDeltaPion, hFractionKaonsDeltaPion,
4375 hFractionProtonsDeltaPion, hFractionMuonsDeltaPion, hYieldPions, hYieldPionsDeltaPion, hYieldElectronsDeltaPion,
4376 hYieldKaonsDeltaPion, hYieldProtonsDeltaPion, hYieldMuonsDeltaPion);
4377
4378 // Also set specific muon fractions and yields -> The deltaSpecies histos are not needed here: They will be set together with
4379 // the fraction and yields for all other species
4380 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kMu, parametersOut, parameterErrorsOut, hFractionMuons,
4381 0x0, 0x0, 0x0, 0x0, 0x0, hYieldMuons, 0x0, 0x0, 0x0, 0x0, 0x0);
4382 }
4383
4384
4385 std::cout << std::endl << std::endl;
4386
4387
4388 // DeltaElectrons
4389
4390 std::cout << "Fitting deltaElectron...." << std::endl << std::endl;
4391
4392 cSingleFit[slice][0]->cd(1);
4393
4394 mathFit->ClearRefHistos();
4395 mathFit->AddRefHisto(hGenDeltaElForPiProj);
4396 mathFit->AddRefHisto(hGenDeltaElForKaProj);
4397 mathFit->AddRefHisto(hGenDeltaElForPrProj);
4398 mathFit->AddRefHisto(hGenDeltaElForElProj);
4399 if (takeIntoAccountMuons)
4400 mathFit->AddRefHisto(hGenDeltaElForMuProj);
4401
4402 errFlag = errFlag |
4403 doFit(hDeltaEl[slice], xLow, xUp, nPar, gausParamsEl, parameterErrorsOut, &covMatrix[0][0],
4404 stepSize, lowParLimitsEl, upParLimitsEl, totalDeltaElectron, reducedChiSquare);
4405
4406 hDeltaEl[slice]->SetTitle("");
4407 SetReasonableXaxisRange(hDeltaEl[slice], binLow, binHigh);
4408 hDeltaEl[slice]->Draw("e");
4409
4410 fitFuncTotalDeltaElectron[slice] = (TF1*)totalDeltaElectron->Clone(Form("Fit_Total_DeltaElectron_%s", fitFuncSuffix.Data()));
4411
4412 hDeltaElFitQA[slice] = (TH1D*)hDeltaEl[slice]->Clone(Form("hDeltaElFitQA_%d", slice));
4413 hDeltaElFitQA[slice]->GetYaxis()->SetTitle("(Data - Fit) / Data");
4414 hDeltaElFitQA[slice]->Add(fitFuncTotalDeltaElectron[slice], -1);
4415 hDeltaElFitQA[slice]->Divide(hDeltaEl[slice]);
4416
4417 hDeltaEl[slice]->GetListOfFunctions()->Add(fitFuncTotalDeltaElectron[slice]);
4418 fitFuncTotalDeltaElectron[slice]->Draw("same");
4419
4420 parametersOut = &gausParamsEl[0];
4421
4422 hGenDeltaElForPiProj->Scale(gausParamsEl[5] * (gausParamsEl[0] + (muonContamination ? gausParamsEl[3] : 0)));
4423 shiftHist(hGenDeltaElForPiProj, gausParamsEl[6]);
4424 hGenDeltaElForPiProj->Draw("same");
4425
4426 hGenDeltaElForKaProj->Scale(gausParamsEl[5] * gausParamsEl[1]);
4427 shiftHist(hGenDeltaElForKaProj, gausParamsEl[7]);
4428 hGenDeltaElForKaProj->Draw("same");
4429
4430 hGenDeltaElForPrProj->Scale(gausParamsEl[5] * gausParamsEl[2]);
4431 shiftHist(hGenDeltaElForPrProj, gausParamsEl[8]);
4432 hGenDeltaElForPrProj->Draw("same");
4433
4434 hGenDeltaElForElProj->Scale(gausParamsEl[5] * gausParamsEl[3]);
4435 shiftHist(hGenDeltaElForElProj, gausParamsEl[9]);
4436 hGenDeltaElForElProj->Draw("same");
4437
4438 if (takeIntoAccountMuons) {
4439 hGenDeltaElForMuProj->Scale(gausParamsEl[5] * gausParamsEl[4]);
4440 shiftHist(hGenDeltaElForMuProj, gausParamsEl[10]);
4441 hGenDeltaElForMuProj->Draw("same");
4442 }
4443
4444 if (plotIdentifiedSpectra) {
4445 for (Int_t species = 0; species < 5; species++)
4446 hDeltaElMC[slice][species]->Draw("same");
4447
4448 // Draw histo for sum of MC muons and pions
4449 TH1D* hMCmuonsAndPions = new TH1D(*hDeltaElMC[slice][kPi - 1]);
4450 hMCmuonsAndPions->Add(hDeltaElMC[slice][kMu - 1]);
4451 hMCmuonsAndPions->SetLineColor(getLineColor(kMuPlusPi));
4452 hMCmuonsAndPions->SetMarkerColor(getLineColor(kMuPlusPi));
4453 hMCmuonsAndPions->SetName(Form("%s_muonsAdded", hDeltaElMC[slice][kPi - 1]->GetName()));
4454 hMCmuonsAndPions->Draw("same");
4455 }
4456
4457 hDeltaEl[slice]->Draw("esame");
4458
4459 legend->Draw();
4460
4461 cSingleFit[slice][0]->cd(2);
4462 hDeltaElFitQA[slice]->GetYaxis()->SetRangeUser(fitQAaxisLowBound, fitQAaxisUpBound);
4463 hDeltaElFitQA[slice]->Draw("e");
4464
4465 hReducedChiSquarePt->SetBinContent(slice + 1, 1, reducedChiSquare);
4466
4467 TMatrixDSym covMatrixEl(nParUsed, &covMatrix[0][0]);
4468
4469 if (fitMethod == 1) {
4470 integralElectrons = allDeltaElectron * parametersOut[3]; // Histos are normalised => expression equals integral
4471 integralTotal += integralElectrons;
4472
4473 /*
4474 integralErrorTotalDeltaElectron = getErrorOfTotalIntegral(covMatrixEl) * allDeltaElectron;
4475
4476 integralErrorElectrons = allDeltaElectron * parameterErrorsOut[3];
4477 */
4478
4479 // Factor 2 in case of takeIntoAccountMuons will be applied below
4480 integralElectronsDeltaElectron = integralElectrons;
4481
4482 // Compare comment above
4483 integralPionsDeltaElectron = allDeltaElectron * (parametersOut[0] + (muonContamination ? parametersOut[3] : 0));
4484 integralKaonsDeltaElectron = allDeltaElectron * parametersOut[1];
4485 integralProtonsDeltaElectron = allDeltaElectron * parametersOut[2];
4486 integralMuonsDeltaElectron = allDeltaElectron * parametersOut[4];
4487
4488
4489 /*
4490 integralErrorElectronsDeltaElectron = integralErrorElectrons;
4491
4492 integralErrorPionsDeltaElectron = getErrorOfPionIntegral(covMatrixEl) * allDeltaElectron;
4493 integralErrorKaonsDeltaElectron = allDeltaElectron * parameterErrorsOut[1];
4494 integralErrorProtonsDeltaElectron = allDeltaElectron * parameterErrorsOut[2];
4495 */
4496 }
4497 else {
4498 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kEl, parametersOut, parameterErrorsOut, hFractionElectrons,
4499 hFractionPionsDeltaElectron, hFractionElectronsDeltaElectron, hFractionKaonsDeltaElectron,
4500 hFractionProtonsDeltaElectron, hFractionMuonsDeltaElectron, hYieldElectrons, hYieldPionsDeltaElectron,
4501 hYieldElectronsDeltaElectron, hYieldKaonsDeltaElectron, hYieldProtonsDeltaElectron, hYieldMuonsDeltaElectron);
4502 }
4503
4504 std::cout << std::endl << std::endl;
4505
4506 // DeltaKaons
4507
4508 std::cout << "Fitting deltaKaon...." << std::endl << std::endl;
4509
4510 cSingleFit[slice][1]->cd(1);
4511
4512 mathFit->ClearRefHistos();
4513 mathFit->AddRefHisto(hGenDeltaKaForPiProj);
4514 mathFit->AddRefHisto(hGenDeltaKaForKaProj);
4515 mathFit->AddRefHisto(hGenDeltaKaForPrProj);
4516 mathFit->AddRefHisto(hGenDeltaKaForElProj);
4517 if (takeIntoAccountMuons)
4518 mathFit->AddRefHisto(hGenDeltaKaForMuProj);
4519
4520 errFlag = errFlag |
4521 doFit(hDeltaKa[slice], xLow, xUp, nPar, gausParamsKa, parameterErrorsOut, &covMatrix[0][0],
4522 stepSize, lowParLimitsKa, upParLimitsKa, totalDeltaKaon, reducedChiSquare);
4523
4524 hDeltaKa[slice]->SetTitle("");
4525 SetReasonableXaxisRange(hDeltaKa[slice], binLow, binHigh);
4526 hDeltaKa[slice]->Draw("e");
4527
4528 fitFuncTotalDeltaKaon[slice] = (TF1*)totalDeltaKaon->Clone(Form("Fit_Total_DeltaKaon_%s", fitFuncSuffix.Data()));
4529
4530 hDeltaKaFitQA[slice] = (TH1D*)hDeltaKa[slice]->Clone(Form("hDeltaKaFitQA_%d", slice));
4531 hDeltaKaFitQA[slice]->GetYaxis()->SetTitle("(Data - Fit) / Data");
4532 hDeltaKaFitQA[slice]->Add(fitFuncTotalDeltaKaon[slice], -1);
4533 hDeltaKaFitQA[slice]->Divide(hDeltaKa[slice]);
4534
4535 hDeltaKa[slice]->GetListOfFunctions()->Add(fitFuncTotalDeltaKaon[slice]);
4536 fitFuncTotalDeltaKaon[slice]->Draw("same");
4537
4538 parametersOut = &gausParamsKa[0];
4539
4540 hGenDeltaKaForPiProj->Scale(gausParamsKa[5] * (gausParamsKa[0] + (muonContamination ? gausParamsKa[3] : 0)));
4541 shiftHist(hGenDeltaKaForPiProj, gausParamsKa[6]);
4542 hGenDeltaKaForPiProj->Draw("same");
4543
4544 hGenDeltaKaForKaProj->Scale(gausParamsKa[5] * gausParamsKa[1]);
4545 shiftHist(hGenDeltaKaForKaProj, gausParamsKa[7]);
4546 hGenDeltaKaForKaProj->Draw("same");
4547
4548 hGenDeltaKaForPrProj->Scale(gausParamsKa[5] * gausParamsKa[2]);
4549 shiftHist(hGenDeltaKaForPrProj, gausParamsKa[8]);
4550 hGenDeltaKaForPrProj->Draw("same");
4551
4552 hGenDeltaKaForElProj->Scale(gausParamsKa[5] * gausParamsKa[3]);
4553 shiftHist(hGenDeltaKaForElProj, gausParamsKa[9]);
4554 hGenDeltaKaForElProj->Draw("same");
4555
4556 if (takeIntoAccountMuons) {
4557 hGenDeltaKaForMuProj->Scale(gausParamsKa[5] * gausParamsKa[4]);
4558 shiftHist(hGenDeltaKaForMuProj, gausParamsKa[10]);
4559 hGenDeltaKaForMuProj->Draw("same");
4560 }
4561
4562 if (plotIdentifiedSpectra) {
4563 for (Int_t species = 0; species < 5; species++)
4564 hDeltaKaMC[slice][species]->Draw("same");
4565
4566 // Draw histo for sum of MC muons and pions
4567 TH1D* hMCmuonsAndPions = new TH1D(*hDeltaKaMC[slice][kPi - 1]);
4568 hMCmuonsAndPions->Add(hDeltaKaMC[slice][kMu - 1]);
4569 hMCmuonsAndPions->SetLineColor(getLineColor(kMuPlusPi));
4570 hMCmuonsAndPions->SetMarkerColor(getLineColor(kMuPlusPi));
4571 hMCmuonsAndPions->SetName(Form("%s_muonsAdded", hDeltaKaMC[slice][kPi - 1]->GetName()));
4572 hMCmuonsAndPions->Draw("same");
4573 }
4574
4575 hDeltaKa[slice]->Draw("esame");
4576
4577 legend->Draw();
4578
4579 cSingleFit[slice][1]->cd(2);
4580 hDeltaKaFitQA[slice]->GetYaxis()->SetRangeUser(fitQAaxisLowBound, fitQAaxisUpBound);
4581 hDeltaKaFitQA[slice]->Draw("e");
4582
4583 hReducedChiSquarePt->SetBinContent(slice + 1, 2, reducedChiSquare);
4584
4585 TMatrixDSym covMatrixKa(nParUsed, &covMatrix[0][0]);
4586
4587 if (fitMethod == 1) {
4588 integralKaons = allDeltaKaon * parametersOut[1]; // Histos are normalised => expression equals integral
4589 integralTotal += integralKaons;
4590 /*
4591 integralErrorTotalDeltaKaon = getErrorOfTotalIntegral(covMatrixKa) * allDeltaKaon;
4592
4593 integralErrorKaons = allDeltaKaon * parameterErrorsOut[1];
4594 */
4595
4596
4597 integralKaonsDeltaKaon = integralKaons;
4598
4599 // Compare comment above
4600 integralPionsDeltaKaon = allDeltaKaon * (parametersOut[0] + (muonContamination ? parametersOut[3] : 0));
4601 integralElectronsDeltaKaon = allDeltaKaon * parametersOut[3];
4602 integralProtonsDeltaKaon = allDeltaKaon * parametersOut[2];
4603 integralMuonsDeltaKaon = allDeltaKaon * parametersOut[4];
4604
4605 /*
4606 integralErrorKaonsDeltaKaon = integralErrorKaons;
4607
4608 integralErrorPionsDeltaKaon = getErrorOfPionIntegral(covMatrixKa) * allDeltaKaon;
4609 integralErrorElectronsDeltaKaon = allDeltaKaon * parameterErrorsOut[3];
4610 integralErrorProtonsDeltaKaon = allDeltaKaon * parameterErrorsOut[2];
4611 */
4612 }
4613 else {
4614 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kKa, parametersOut, parameterErrorsOut, hFractionKaons,
4615 hFractionPionsDeltaKaon, hFractionElectronsDeltaKaon, hFractionKaonsDeltaKaon, hFractionProtonsDeltaKaon,
4616 hFractionMuonsDeltaKaon, hYieldKaons, hYieldPionsDeltaKaon, hYieldElectronsDeltaKaon, hYieldKaonsDeltaKaon,
4617 hYieldProtonsDeltaKaon, hYieldMuonsDeltaKaon);
4618 }
4619
4620 std::cout << std::endl << std::endl;
4621
4622
4623 // DeltaProtons
4624
4625 std::cout << "Fitting deltaProton...." << std::endl << std::endl;
4626
4627 cSingleFit[slice][3]->cd(1);
4628
4629 mathFit->ClearRefHistos();
4630 mathFit->AddRefHisto(hGenDeltaPrForPiProj);
4631 mathFit->AddRefHisto(hGenDeltaPrForKaProj);
4632 mathFit->AddRefHisto(hGenDeltaPrForPrProj);
4633 mathFit->AddRefHisto(hGenDeltaPrForElProj);
4634 if (takeIntoAccountMuons)
4635 mathFit->AddRefHisto(hGenDeltaPrForMuProj);
4636
4637 errFlag = errFlag |
4638 doFit(hDeltaPr[slice], xLow, xUp, nPar, gausParamsPr, parameterErrorsOut, &covMatrix[0][0],
4639 stepSize, lowParLimitsPr, upParLimitsPr, totalDeltaProton, reducedChiSquare);
4640
4641 hDeltaPr[slice]->SetTitle("");
4642 SetReasonableXaxisRange(hDeltaPr[slice], binLow, binHigh);
4643 hDeltaPr[slice]->Draw("e");
4644
4645 fitFuncTotalDeltaProton[slice] = (TF1*)totalDeltaProton->Clone(Form("Fit_Total_DeltaProton_%s", fitFuncSuffix.Data()));
4646
4647 hDeltaPrFitQA[slice] = (TH1D*)hDeltaPr[slice]->Clone(Form("hDeltaPrFitQA_%d", slice));
4648 hDeltaPrFitQA[slice]->GetYaxis()->SetTitle("(Data - Fit) / Data");
4649 hDeltaPrFitQA[slice]->Add(fitFuncTotalDeltaProton[slice], -1);
4650 hDeltaPrFitQA[slice]->Divide(hDeltaPr[slice]);
4651
4652 hDeltaPr[slice]->GetListOfFunctions()->Add(fitFuncTotalDeltaProton[slice]);
4653
4654 fitFuncTotalDeltaProton[slice]->Draw("same");
4655
4656 parametersOut = &gausParamsPr[0];
4657
4658 hGenDeltaPrForPiProj->Scale(gausParamsPr[5] * (gausParamsPr[0] + (muonContamination ? gausParamsPr[3] : 0)));
4659 shiftHist(hGenDeltaPrForPiProj, gausParamsPr[6]);
4660 hGenDeltaPrForPiProj->Draw("same");
4661
4662 hGenDeltaPrForKaProj->Scale(gausParamsPr[5] * gausParamsPr[1]);
4663 shiftHist(hGenDeltaPrForKaProj, gausParamsPr[7]);
4664 hGenDeltaPrForKaProj->Draw("same");
4665
4666 hGenDeltaPrForPrProj->Scale(gausParamsPr[5] * gausParamsPr[2]);
4667 shiftHist(hGenDeltaPrForPrProj, gausParamsPr[8]);
4668 hGenDeltaPrForPrProj->Draw("same");
4669
4670 hGenDeltaPrForElProj->Scale(gausParamsPr[5] * gausParamsPr[3]);
4671 shiftHist(hGenDeltaPrForElProj, gausParamsPr[9]);
4672 hGenDeltaPrForElProj->Draw("same");
4673
4674 if (takeIntoAccountMuons) {
4675 hGenDeltaPrForMuProj->Scale(gausParamsPr[5] * gausParamsPr[4]);
4676 shiftHist(hGenDeltaPrForMuProj, gausParamsPr[10]);
4677 hGenDeltaPrForMuProj->Draw("same");
4678 }
4679
4680 if (plotIdentifiedSpectra) {
4681 for (Int_t species = 0; species < 5; species++)
4682 hDeltaPrMC[slice][species]->Draw("same");
4683
4684 // Draw histo for sum of MC muons and pions
4685 TH1D* hMCmuonsAndPions = new TH1D(*hDeltaPrMC[slice][kPi - 1]);
4686 hMCmuonsAndPions->Add(hDeltaPrMC[slice][kMu - 1]);
4687 hMCmuonsAndPions->SetLineColor(getLineColor(kMuPlusPi));
4688 hMCmuonsAndPions->SetMarkerColor(getLineColor(kMuPlusPi));
4689 hMCmuonsAndPions->SetName(Form("%s_muonsAdded", hDeltaPrMC[slice][kPi - 1]->GetName()));
4690 hMCmuonsAndPions->Draw("same");
4691 }
4692
4693 hDeltaPr[slice]->Draw("esame");
4694
4695 legend->Draw();
4696
4697 cSingleFit[slice][3]->cd(2);
4698 hDeltaPrFitQA[slice]->GetYaxis()->SetRangeUser(fitQAaxisLowBound, fitQAaxisUpBound);
4699 hDeltaPrFitQA[slice]->Draw("e");
4700
4701 hReducedChiSquarePt->SetBinContent(slice + 1, 4, reducedChiSquare);
4702
4703 TMatrixDSym covMatrixPr(nParUsed, &covMatrix[0][0]);
4704
4705 if (fitMethod == 1) {
4706 integralProtons = allDeltaProton * parametersOut[2]; // Histos are normalised => expression equals integral
4707 integralTotal += integralProtons;
4708 /*
4709 integralErrorTotalDeltaProton = getErrorOfTotalIntegral(covMatrixPr) * allDeltaProton;
4710
4711 integralErrorProtons = allDeltaProton * parameterErrorsOut[2];
4712 */
4713
4714 integralProtonsDeltaProton = integralProtons;
4715
4716 // Compare comment above
4717 integralPionsDeltaProton = allDeltaProton * (parametersOut[0] + (muonContamination ? parametersOut[3] : 0));
4718 integralElectronsDeltaProton = allDeltaProton * parametersOut[3];
4719 integralKaonsDeltaProton = allDeltaProton * parametersOut[1];
4720 integralMuonsDeltaProton = allDeltaProton * parametersOut[4];
4721
4722
4723 /*
4724 integralErrorProtonsDeltaProton = integralErrorProtons;
4725
4726 integralErrorPionsDeltaProton = getErrorOfPionIntegral(covMatrixPr) * allDeltaProton;
4727 integralErrorElectronsDeltaProton = allDeltaProton * parameterErrorsOut[3];
4728 integralErrorKaonsDeltaProton = allDeltaProton * parameterErrorsOut[1];
4729 */
4730 }
4731 else {
4732 setFractionsAndYields(slice, inverseBinWidth, binWidthFitHisto, kPr, parametersOut, parameterErrorsOut, hFractionProtons,
4733 hFractionPionsDeltaProton, hFractionElectronsDeltaProton, hFractionKaonsDeltaProton,
4734 hFractionProtonsDeltaProton, hFractionMuonsDeltaProton, hYieldProtons, hYieldPionsDeltaProton,
4735 hYieldElectronsDeltaProton, hYieldKaonsDeltaProton, hYieldProtonsDeltaProton, hYieldMuonsDeltaProton);
4736 }
4737
4738 std::cout << std::endl << std::endl;
4739
4740
4741 if (fitMethod == 1) {
4742 // Calculate fractions and yields for method 1
4743 if (integralTotal > 0) {
4744
4745 Double_t sumOfParticles = 0;
4746
4747 // Check fraction and yield determination for systematics
4748 // DeltaPion
4749 Double_t integralTotalDeltaPion = integralPionsDeltaPion + integralElectronsDeltaPion +
4750 (takeIntoAccountMuons ? integralMuonsDeltaPion : 0.) +
4751 integralKaonsDeltaPion + integralProtonsDeltaPion;
4752 totalDeltaPion->GetParameters(parametersOut);
4753
4754 Double_t pionFractionDeltaPion = saveDivide(integralPionsDeltaPion, integralTotalDeltaPion);
4755 Double_t pionFractionErrorDeltaPion = getErrorOfPionFraction(parametersOut, covMatrixPi);
4756 hFractionPionsDeltaPion->SetBinContent(slice + 1, pionFractionDeltaPion);
4757 hFractionPionsDeltaPion->SetBinError(slice + 1, pionFractionErrorDeltaPion);
4758
4759 Double_t electronFractionDeltaPion = saveDivide(integralElectronsDeltaPion, integralTotalDeltaPion);
4760 Double_t electronFractionErrorDeltaPion = getErrorOfElectronFraction(parametersOut, covMatrixPi);
4761 hFractionElectronsDeltaPion->SetBinContent(slice + 1, electronFractionDeltaPion);
4762 hFractionElectronsDeltaPion->SetBinError(slice + 1, electronFractionErrorDeltaPion);
4763
4764 Double_t kaonFractionDeltaPion = saveDivide(integralKaonsDeltaPion, integralTotalDeltaPion);
4765 Double_t kaonFractionErrorDeltaPion = getErrorOfKaonFraction(parametersOut, covMatrixPi);
4766 hFractionKaonsDeltaPion->SetBinContent(slice + 1, kaonFractionDeltaPion);
4767 hFractionKaonsDeltaPion->SetBinError(slice + 1, kaonFractionErrorDeltaPion);
4768
4769 Double_t protonFractionDeltaPion = saveDivide(integralProtonsDeltaPion, integralTotalDeltaPion);
4770 Double_t protonFractionErrorDeltaPion = getErrorOfProtonFraction(parametersOut, covMatrixPi);
4771 hFractionProtonsDeltaPion->SetBinContent(slice + 1, protonFractionDeltaPion);
4772 hFractionProtonsDeltaPion->SetBinError(slice + 1, protonFractionErrorDeltaPion);
4773
4774 Double_t muonFractionDeltaPion = saveDivide(integralMuonsDeltaPion, integralTotalDeltaPion);
4775 // TODO Error is anyway not implemented correctly. Just take electron error as an approximation
4776 Double_t muonFractionErrorDeltaPion = getErrorOfElectronFraction(parametersOut, covMatrixPi);
4777 hFractionMuonsDeltaPion->SetBinContent(slice + 1, muonFractionDeltaPion);
4778 hFractionMuonsDeltaPion->SetBinError(slice + 1, muonFractionErrorDeltaPion);
4779
4780 sumOfParticles = inverseBinWidth * gausParamsPi[5] / binWidthFitHisto; // Divide by binWidthFitHisto, since gausParamsXX includes this width
4781
4782 hYieldPionsDeltaPion->SetBinContent(slice + 1, sumOfParticles * hFractionPionsDeltaPion->GetBinContent(slice + 1));
4783 hYieldPionsDeltaPion->SetBinError(slice + 1, sumOfParticles * hFractionPionsDeltaPion->GetBinError(slice + 1));
4784 hYieldElectronsDeltaPion->SetBinContent(slice + 1, sumOfParticles * hFractionElectronsDeltaPion->GetBinContent(slice + 1));
4785 hYieldElectronsDeltaPion->SetBinError(slice + 1, sumOfParticles * hFractionElectronsDeltaPion->GetBinError(slice + 1));
4786 hYieldKaonsDeltaPion->SetBinContent(slice + 1, sumOfParticles * hFractionKaonsDeltaPion->GetBinContent(slice + 1));
4787 hYieldKaonsDeltaPion->SetBinError(slice + 1, sumOfParticles * hFractionKaonsDeltaPion->GetBinError(slice + 1));
4788 hYieldProtonsDeltaPion->SetBinContent(slice + 1, sumOfParticles * hFractionProtonsDeltaPion->GetBinContent(slice + 1));
4789 hYieldProtonsDeltaPion->SetBinError(slice + 1, sumOfParticles * hFractionProtonsDeltaPion->GetBinError(slice + 1));
4790 hYieldMuonsDeltaPion->SetBinContent(slice + 1, sumOfParticles * hFractionMuonsDeltaPion->GetBinContent(slice + 1));
4791 hYieldMuonsDeltaPion->SetBinError(slice + 1, sumOfParticles * hFractionMuonsDeltaPion->GetBinError(slice + 1));
4792
4793
4794 // DeltaElectron
4795 Double_t integralTotalDeltaElectron = integralPionsDeltaElectron + integralElectronsDeltaElectron +
4796 (takeIntoAccountMuons ? integralMuonsDeltaElectron : 0.) +
4797 integralKaonsDeltaElectron + integralProtonsDeltaElectron;
4798 totalDeltaElectron->GetParameters(parametersOut);
4799
4800 Double_t pionFractionDeltaElectron = saveDivide(integralPionsDeltaElectron, integralTotalDeltaElectron);
4801 Double_t pionFractionErrorDeltaElectron = getErrorOfPionFraction(parametersOut, covMatrixEl);
4802 hFractionPionsDeltaElectron->SetBinContent(slice + 1, pionFractionDeltaElectron);
4803 hFractionPionsDeltaElectron->SetBinError(slice + 1, pionFractionErrorDeltaElectron);
4804
4805 Double_t electronFractionDeltaElectron = saveDivide(integralElectronsDeltaElectron, integralTotalDeltaElectron);
4806 Double_t electronFractionErrorDeltaElectron = getErrorOfElectronFraction(parametersOut, covMatrixEl);
4807 hFractionElectronsDeltaElectron->SetBinContent(slice + 1, electronFractionDeltaElectron);
4808 hFractionElectronsDeltaElectron->SetBinError(slice + 1, electronFractionErrorDeltaElectron);
4809
4810 Double_t kaonFractionDeltaElectron = saveDivide(integralKaonsDeltaElectron, integralTotalDeltaElectron);
4811 Double_t kaonFractionErrorDeltaElectron = getErrorOfKaonFraction(parametersOut, covMatrixEl);
4812 hFractionKaonsDeltaElectron->SetBinContent(slice + 1, kaonFractionDeltaElectron);
4813 hFractionKaonsDeltaElectron->SetBinError(slice + 1, kaonFractionErrorDeltaElectron);
4814
4815 Double_t protonFractionDeltaElectron = saveDivide(integralProtonsDeltaElectron, integralTotalDeltaElectron);
4816 Double_t protonFractionErrorDeltaElectron = getErrorOfProtonFraction(parametersOut, covMatrixEl);
4817 hFractionProtonsDeltaElectron->SetBinContent(slice + 1, protonFractionDeltaElectron);
4818 hFractionProtonsDeltaElectron->SetBinError(slice + 1, protonFractionErrorDeltaElectron);
4819
4820 Double_t muonFractionDeltaElectron = saveDivide(integralMuonsDeltaElectron, integralTotalDeltaElectron);
4821 // TODO Error is anyway not implemented correctly. Just take electron error as an approximation
4822 Double_t muonFractionErrorDeltaElectron = getErrorOfElectronFraction(parametersOut, covMatrixEl);
4823 hFractionMuonsDeltaElectron->SetBinContent(slice + 1, muonFractionDeltaElectron);
4824 hFractionMuonsDeltaElectron->SetBinError(slice + 1, muonFractionErrorDeltaElectron);
4825
4826 sumOfParticles = inverseBinWidth * gausParamsEl[5] / binWidthFitHisto; // Divide by binWidthFitHisto, since gausParamsXX includes this width
4827
4828 hYieldPionsDeltaElectron->SetBinContent(slice + 1, sumOfParticles * hFractionPionsDeltaElectron->GetBinContent(slice + 1));
4829 hYieldPionsDeltaElectron->SetBinError(slice + 1, sumOfParticles * hFractionPionsDeltaElectron->GetBinError(slice + 1));
4830 hYieldElectronsDeltaElectron->SetBinContent(slice + 1, sumOfParticles * hFractionElectronsDeltaElectron->GetBinContent(slice + 1));
4831 hYieldElectronsDeltaElectron->SetBinError(slice + 1, sumOfParticles * hFractionElectronsDeltaElectron->GetBinError(slice + 1));
4832 hYieldKaonsDeltaElectron->SetBinContent(slice + 1, sumOfParticles * hFractionKaonsDeltaElectron->GetBinContent(slice + 1));
4833 hYieldKaonsDeltaElectron->SetBinError(slice + 1, sumOfParticles * hFractionKaonsDeltaElectron->GetBinError(slice + 1));
4834 hYieldProtonsDeltaElectron->SetBinContent(slice + 1, sumOfParticles * hFractionProtonsDeltaElectron->GetBinContent(slice + 1));
4835 hYieldProtonsDeltaElectron->SetBinError(slice + 1, sumOfParticles * hFractionProtonsDeltaElectron->GetBinError(slice + 1));
4836 hYieldMuonsDeltaElectron->SetBinContent(slice + 1, sumOfParticles * hFractionMuonsDeltaElectron->GetBinContent(slice + 1));
4837 hYieldMuonsDeltaElectron->SetBinError(slice + 1, sumOfParticles * hFractionMuonsDeltaElectron->GetBinError(slice + 1));
4838
4839
4840 // DeltaKaon
4841 Double_t integralTotalDeltaKaon = integralPionsDeltaKaon + integralElectronsDeltaKaon +
4842 (takeIntoAccountMuons ? integralMuonsDeltaKaon : 0.) +
4843 integralKaonsDeltaKaon + integralProtonsDeltaKaon;
4844 totalDeltaKaon->GetParameters(parametersOut);
4845
4846 Double_t pionFractionDeltaKaon = saveDivide(integralPionsDeltaKaon, integralTotalDeltaKaon);
4847 Double_t pionFractionErrorDeltaKaon = getErrorOfPionFraction(parametersOut, covMatrixKa);
4848 hFractionPionsDeltaKaon->SetBinContent(slice + 1, pionFractionDeltaKaon);
4849 hFractionPionsDeltaKaon->SetBinError(slice + 1, pionFractionErrorDeltaKaon);
4850
4851 Double_t electronFractionDeltaKaon = saveDivide(integralElectronsDeltaKaon, integralTotalDeltaKaon);
4852 Double_t electronFractionErrorDeltaKaon = getErrorOfElectronFraction(parametersOut, covMatrixKa);
4853 hFractionElectronsDeltaKaon->SetBinContent(slice + 1, electronFractionDeltaKaon);
4854 hFractionElectronsDeltaKaon->SetBinError(slice + 1, electronFractionErrorDeltaKaon);
4855
4856 Double_t kaonFractionDeltaKaon = saveDivide(integralKaonsDeltaKaon, integralTotalDeltaKaon);
4857 Double_t kaonFractionErrorDeltaKaon = getErrorOfKaonFraction(parametersOut, covMatrixKa);
4858 hFractionKaonsDeltaKaon->SetBinContent(slice + 1, kaonFractionDeltaKaon);
4859 hFractionKaonsDeltaKaon->SetBinError(slice + 1, kaonFractionErrorDeltaKaon);
4860
4861 Double_t protonFractionDeltaKaon = saveDivide(integralProtonsDeltaKaon, integralTotalDeltaKaon);
4862 Double_t protonFractionErrorDeltaKaon = getErrorOfProtonFraction(parametersOut, covMatrixKa);
4863 hFractionProtonsDeltaKaon->SetBinContent(slice + 1, protonFractionDeltaKaon);
4864 hFractionProtonsDeltaKaon->SetBinError(slice + 1, protonFractionErrorDeltaKaon);
4865
4866 Double_t muonFractionDeltaKaon = saveDivide(integralMuonsDeltaKaon, integralTotalDeltaKaon);
4867 // TODO Error is anyway not implemented correctly. Just take electron error as an approximation
4868 Double_t muonFractionErrorDeltaKaon = getErrorOfElectronFraction(parametersOut, covMatrixKa);
4869 hFractionMuonsDeltaKaon->SetBinContent(slice + 1, muonFractionDeltaKaon);
4870 hFractionMuonsDeltaKaon->SetBinError(slice + 1, muonFractionErrorDeltaKaon);
4871
4872 sumOfParticles = inverseBinWidth * gausParamsKa[5] / binWidthFitHisto; // Divide by binWidthFitHisto, since gausParamsXX includes this width
4873
4874 hYieldPionsDeltaKaon->SetBinContent(slice + 1, sumOfParticles * hFractionPionsDeltaKaon->GetBinContent(slice + 1));
4875 hYieldPionsDeltaKaon->SetBinError(slice + 1, sumOfParticles * hFractionPionsDeltaKaon->GetBinError(slice + 1));
4876 hYieldElectronsDeltaKaon->SetBinContent(slice + 1, sumOfParticles * hFractionElectronsDeltaKaon->GetBinContent(slice + 1));
4877 hYieldElectronsDeltaKaon->SetBinError(slice + 1, sumOfParticles * hFractionElectronsDeltaKaon->GetBinError(slice + 1));
4878 hYieldKaonsDeltaKaon->SetBinContent(slice + 1, sumOfParticles * hFractionKaonsDeltaKaon->GetBinContent(slice + 1));
4879 hYieldKaonsDeltaKaon->SetBinError(slice + 1, sumOfParticles * hFractionKaonsDeltaKaon->GetBinError(slice + 1));
4880 hYieldProtonsDeltaKaon->SetBinContent(slice + 1, sumOfParticles * hFractionProtonsDeltaKaon->GetBinContent(slice + 1));
4881 hYieldProtonsDeltaKaon->SetBinError(slice + 1, sumOfParticles * hFractionProtonsDeltaKaon->GetBinError(slice + 1));
4882 hYieldMuonsDeltaKaon->SetBinContent(slice + 1, sumOfParticles * hFractionMuonsDeltaKaon->GetBinContent(slice + 1));
4883 hYieldMuonsDeltaKaon->SetBinError(slice + 1, sumOfParticles * hFractionMuonsDeltaKaon->GetBinError(slice + 1));
4884
4885
4886
4887 // DeltaProton
4888 Double_t integralTotalDeltaProton = integralPionsDeltaProton + integralElectronsDeltaProton +
4889 (takeIntoAccountMuons ? integralMuonsDeltaProton : 0.) +
4890 integralKaonsDeltaProton + integralProtonsDeltaProton;
4891 totalDeltaProton->GetParameters(parametersOut);
4892
4893 Double_t pionFractionDeltaProton = saveDivide(integralPionsDeltaProton, integralTotalDeltaProton);
4894 Double_t pionFractionErrorDeltaProton = getErrorOfPionFraction(parametersOut, covMatrixPr);
4895 hFractionPionsDeltaProton->SetBinContent(slice + 1, pionFractionDeltaProton);
4896 hFractionPionsDeltaProton->SetBinError(slice + 1, pionFractionErrorDeltaProton);
4897
4898 Double_t electronFractionDeltaProton = saveDivide(integralElectronsDeltaProton, integralTotalDeltaProton);
4899 Double_t electronFractionErrorDeltaProton = getErrorOfElectronFraction(parametersOut, covMatrixPr);
4900 hFractionElectronsDeltaProton->SetBinContent(slice + 1, electronFractionDeltaProton);
4901 hFractionElectronsDeltaProton->SetBinError(slice + 1, electronFractionErrorDeltaProton);
4902
4903 Double_t kaonFractionDeltaProton = saveDivide(integralKaonsDeltaProton, integralTotalDeltaProton);
4904 Double_t kaonFractionErrorDeltaProton = getErrorOfKaonFraction(parametersOut, covMatrixPr);
4905 hFractionKaonsDeltaProton->SetBinContent(slice + 1, kaonFractionDeltaProton);
4906 hFractionKaonsDeltaProton->SetBinError(slice + 1, kaonFractionErrorDeltaProton);
4907
4908 Double_t protonFractionDeltaProton = saveDivide(integralProtonsDeltaProton, integralTotalDeltaProton);
4909 Double_t protonFractionErrorDeltaProton = getErrorOfProtonFraction(parametersOut, covMatrixPr);
4910 hFractionProtonsDeltaProton->SetBinContent(slice + 1, protonFractionDeltaProton);
4911 hFractionProtonsDeltaProton->SetBinError(slice + 1, protonFractionErrorDeltaProton);
4912
4913 Double_t muonFractionDeltaProton = saveDivide(integralMuonsDeltaProton, integralTotalDeltaProton);
4914 // TODO Error is anyway not implemented correctly. Just take electron error as an approximation
4915 Double_t muonFractionErrorDeltaProton = getErrorOfElectronFraction(parametersOut, covMatrixPr);
4916 hFractionMuonsDeltaProton->SetBinContent(slice + 1, muonFractionDeltaProton);
4917 hFractionMuonsDeltaProton->SetBinError(slice + 1, muonFractionErrorDeltaProton);
4918
4919 sumOfParticles = inverseBinWidth * gausParamsPr[5] / binWidthFitHisto; // Divide by binWidthFitHisto, since gausParamsXX includes this width
4920
4921 hYieldPionsDeltaProton->SetBinContent(slice + 1, sumOfParticles * hFractionPionsDeltaProton->GetBinContent(slice + 1));
4922 hYieldPionsDeltaProton->SetBinError(slice + 1, sumOfParticles * hFractionPionsDeltaProton->GetBinError(slice + 1));
4923 hYieldElectronsDeltaProton->SetBinContent(slice + 1, sumOfParticles * hFractionElectronsDeltaProton->GetBinContent(slice + 1));
4924 hYieldElectronsDeltaProton->SetBinError(slice + 1, sumOfParticles * hFractionElectronsDeltaProton->GetBinError(slice + 1));
4925 hYieldKaonsDeltaProton->SetBinContent(slice + 1, sumOfParticles * hFractionKaonsDeltaProton->GetBinContent(slice + 1));
4926 hYieldKaonsDeltaProton->SetBinError(slice + 1, sumOfParticles * hFractionKaonsDeltaProton->GetBinError(slice + 1));
4927 hYieldProtonsDeltaProton->SetBinContent(slice + 1, sumOfParticles * hFractionProtonsDeltaProton->GetBinContent(slice + 1));
4928 hYieldProtonsDeltaProton->SetBinError(slice + 1, sumOfParticles * hFractionProtonsDeltaProton->GetBinError(slice + 1));
4929 hYieldMuonsDeltaProton->SetBinContent(slice + 1, sumOfParticles * hFractionMuonsDeltaProton->GetBinContent(slice + 1));
4930 hYieldMuonsDeltaProton->SetBinError(slice + 1, sumOfParticles * hFractionMuonsDeltaProton->GetBinError(slice + 1));
4931
4932
4933
4934 // Take for XXXXfractionError the median of XXXXfractionErrorYYYY and do not take into account errors
4935 // with value zero, since the should correspond to a failed fit (but the other fits can still converge).
4936 // Same for the yields
4937 Double_t pionFraction = saveDivide(integralPions, integralTotal);
4938 Double_t errorsPions[4] = { pionFractionErrorDeltaPion, pionFractionErrorDeltaElectron,
4939 pionFractionErrorDeltaKaon, pionFractionErrorDeltaProton };
4940 Double_t pionFractionError = getMedianOfNonZeros(errorsPions);
4941
4942 Double_t electronFraction = saveDivide(integralElectrons, integralTotal);
4943 Double_t errorsElectrons[4] = { electronFractionErrorDeltaPion, electronFractionErrorDeltaElectron,
4944 electronFractionErrorDeltaKaon, electronFractionErrorDeltaProton };
4945 Double_t electronFractionError = getMedianOfNonZeros(errorsElectrons);
4946
4947 Double_t kaonFraction = saveDivide(integralKaons, integralTotal);
4948 Double_t errorsKaons[4] = { kaonFractionErrorDeltaPion, kaonFractionErrorDeltaElectron,
4949 kaonFractionErrorDeltaKaon, kaonFractionErrorDeltaProton };
4950 Double_t kaonFractionError = getMedianOfNonZeros(errorsKaons);
4951
4952 Double_t protonFraction = saveDivide(integralProtons, integralTotal);
4953 Double_t errorsProtons[4] = { protonFractionErrorDeltaPion, protonFractionErrorDeltaElectron,
4954 protonFractionErrorDeltaKaon, protonFractionErrorDeltaProton };
4955 Double_t protonFractionError = getMedianOfNonZeros(errorsProtons);
4956
4957 Double_t muonFraction = saveDivide(integralMuons, integralTotal);
4958 Double_t errorsMuons[4] = { muonFractionErrorDeltaPion, muonFractionErrorDeltaElectron,
4959 muonFractionErrorDeltaKaon, muonFractionErrorDeltaProton };
4960 Double_t muonFractionError = getMedianOfNonZeros(errorsMuons);
4961
4962 hFractionPions->SetBinContent(slice + 1, pionFraction);
4963 hFractionPions->SetBinError(slice + 1, pionFractionError);
4964 hFractionElectrons->SetBinContent(slice + 1, electronFraction);
4965 hFractionElectrons->SetBinError(slice + 1, electronFractionError);
4966 hFractionKaons->SetBinContent(slice + 1, kaonFraction);
4967 hFractionKaons->SetBinError(slice + 1, kaonFractionError);
4968 hFractionProtons->SetBinContent(slice + 1, protonFraction);
4969 hFractionProtons->SetBinError(slice + 1, protonFractionError);
4970 hFractionMuons->SetBinContent(slice + 1, muonFraction);
4971 hFractionMuons->SetBinError(slice + 1, muonFractionError);
4972
4973 hFractionSummed->SetBinContent(slice + 1, pionFraction + electronFraction + (takeIntoAccountMuons ? muonFraction : 0.) +
4974 kaonFraction + protonFraction);
4975 hFractionSummed->SetBinError(slice + 1,
4976 TMath::Sqrt(TMath::Power(pionFractionError, 2) +
4977 TMath::Power(electronFractionError, 2) +
4978 (takeIntoAccountMuons ? TMath::Power(muonFractionError, 2) : 0.) +
4979 TMath::Power(kaonFractionError, 2) +
4980 TMath::Power(protonFractionError, 2)));
4981
4982 sumOfParticles = inverseBinWidth * integralTotal / binWidthFitHisto; // Divide by binWidthFitHisto, since integralTotal includes this width
4983
4984 hYieldPions->SetBinContent(slice + 1, sumOfParticles * hFractionPions->GetBinContent(slice + 1));
4985 hYieldPions->SetBinError(slice + 1, sumOfParticles * hFractionPions->GetBinError(slice + 1));
4986 hYieldElectrons->SetBinContent(slice + 1, sumOfParticles * hFractionElectrons->GetBinContent(slice + 1));
4987 hYieldElectrons->SetBinError(slice + 1, sumOfParticles * hFractionElectrons->GetBinError(slice + 1));
4988 hYieldKaons->SetBinContent(slice + 1, sumOfParticles * hFractionKaons->GetBinContent(slice + 1));
4989 hYieldKaons->SetBinError(slice + 1, sumOfParticles * hFractionKaons->GetBinError(slice + 1));
4990 hYieldProtons->SetBinContent(slice + 1, sumOfParticles * hFractionProtons->GetBinContent(slice + 1));
4991 hYieldProtons->SetBinError(slice + 1, sumOfParticles * hFractionProtons->GetBinError(slice + 1));
4992 hYieldMuons->SetBinContent(slice + 1, sumOfParticles * hFractionMuons->GetBinContent(slice + 1));
4993 hYieldMuons->SetBinError(slice + 1, sumOfParticles * hFractionMuons->GetBinError(slice + 1));
4994 }
4995 }
4996 else {
4997 Double_t SumFractionsDeltaElectron = hFractionPionsDeltaElectron->GetBinContent(slice + 1) +
4998 hFractionElectronsDeltaElectron->GetBinContent(slice + 1) +
4999 (takeIntoAccountMuons ? hFractionMuonsDeltaElectron->GetBinContent(slice + 1) : 0.) +
5000 hFractionKaonsDeltaElectron->GetBinContent(slice + 1) + hFractionProtonsDeltaElectron->GetBinContent(slice + 1);
5001
5002 Double_t SumFractionsDeltaKaon = hFractionPionsDeltaKaon->GetBinContent(slice + 1) +
5003 hFractionElectronsDeltaKaon->GetBinContent(slice + 1) +
5004 (takeIntoAccountMuons ? hFractionMuonsDeltaKaon->GetBinContent(slice + 1) : 0.) +
5005 hFractionKaonsDeltaKaon->GetBinContent(slice + 1) + hFractionProtonsDeltaKaon->GetBinContent(slice + 1);
5006
5007 Double_t SumFractionsDeltaPion = hFractionPionsDeltaPion->GetBinContent(slice + 1) +
5008 hFractionElectronsDeltaPion->GetBinContent(slice + 1) +
5009 (takeIntoAccountMuons ? hFractionMuonsDeltaPion->GetBinContent(slice + 1) : 0.) +
5010 hFractionKaonsDeltaPion->GetBinContent(slice + 1) + hFractionProtonsDeltaPion->GetBinContent(slice + 1);
5011
5012 Double_t SumFractionsDeltaProton = hFractionPionsDeltaProton->GetBinContent(slice + 1) +
5013 hFractionElectronsDeltaProton->GetBinContent(slice + 1) +
5014 (takeIntoAccountMuons ? hFractionMuonsDeltaProton->GetBinContent(slice + 1) : 0.) +
5015 hFractionKaonsDeltaProton->GetBinContent(slice + 1) + hFractionProtonsDeltaProton->GetBinContent(slice + 1);
5016
5017 Double_t SumFractionsUsed = hFractionPionsDeltaPion->GetBinContent(slice + 1) +
5018 hFractionElectronsDeltaElectron->GetBinContent(slice + 1) +
5019 (takeIntoAccountMuons ? hFractionMuonsDeltaPion->GetBinContent(slice + 1) : 0.) +
5020 hFractionKaonsDeltaKaon->GetBinContent(slice + 1) + hFractionProtonsDeltaProton->GetBinContent(slice + 1);
5021
5022 hFractionSummed->SetBinContent(slice + 1, SumFractionsUsed);
5023 hFractionSummed->SetBinError(slice + 1,
5024 TMath::Sqrt(TMath::Power(hFractionPionsDeltaPion->GetBinError(slice + 1), 2) +
5025 TMath::Power(hFractionElectronsDeltaElectron->GetBinError(slice + 1), 2) +
5026 (takeIntoAccountMuons ? TMath::Power(hFractionMuonsDeltaPion->GetBinError(slice + 1),
5027 2) : 0.) +
5028 TMath::Power(hFractionKaonsDeltaKaon->GetBinError(slice + 1), 2) +
5029 TMath::Power(hFractionProtonsDeltaProton->GetBinError(slice + 1), 2)));
5030
5031
5032 std::cout << "Sum Fractions DeltaElectron: " << SumFractionsDeltaElectron;
5033 std::cout << (TMath::Abs(SumFractionsDeltaElectron - 1) >= 0.001 ? " WARNING: Deviation >= 0.001" : "") << std::endl;
5034
5035 std::cout << "Sum Fractions DeltaKaon: " << SumFractionsDeltaKaon;
5036 std::cout << (TMath::Abs(SumFractionsDeltaKaon - 1) >= 0.001 ? " WARNING: Deviation >= 0.001" : "") << std::endl;
5037
5038 std::cout << "Sum Fractions DeltaPion: " << SumFractionsDeltaPion;
5039 std::cout << (TMath::Abs(SumFractionsDeltaPion - 1) >= 0.001 ? " WARNING: Deviation >= 0.001" : "") << std::endl;
5040
5041 std::cout << "Sum fractions DeltaProton: " << SumFractionsDeltaProton;
5042 std::cout << (TMath::Abs(SumFractionsDeltaProton - 1) >= 0.001 ? " WARNING: Deviation >= 0.001" : "") << std::endl;
5043
5044 std::cout << "Sum fractions used: " << SumFractionsUsed;
5045 std::cout << (TMath::Abs(SumFractionsUsed - 1) >= 0.001 ? " WARNING: Deviation >= 0.001" : "") << std::endl;
5046 }
5047
5048 for (Int_t species = 0; species < 4; species++) {
5049 cSingleFit[slice][species]->Modified();
5050 cSingleFit[slice][species]->Update();
5051 }
5052
5053
5054 }
5055
5056 if (regularisation <= 0)
5057 std::cout << std::endl << std::endl;
5058
5059
5060 // MC results
5061 Double_t MCtotal = -1, MCelectrons = -1, MCkaons = -1, MCmuons = -1, MCpions = -1, MCprotons = -1;
5062 Double_t MCelectronsErr = 0, MCkaonsErr = 0, MCmuonsErr = 0, MCpionsErr = 0, MCprotonsErr = 0;
5063
5064 MCelectrons = hMCdata->IntegralAndError(pBinLowProjLimit, pBinUpProjLimit, 1, 1, MCelectronsErr) * inverseBinWidth;
5065 MCkaons = hMCdata->IntegralAndError(pBinLowProjLimit, pBinUpProjLimit, 2, 2, MCkaonsErr) * inverseBinWidth;
5066 MCmuons = hMCdata->IntegralAndError(pBinLowProjLimit, pBinUpProjLimit, 3, 3, MCmuonsErr) * inverseBinWidth;
5067 MCpions = hMCdata->IntegralAndError(pBinLowProjLimit, pBinUpProjLimit, 4, 4, MCpionsErr) * inverseBinWidth;
5068 MCprotons = hMCdata->IntegralAndError(pBinLowProjLimit, pBinUpProjLimit, 5, 5, MCprotonsErr) * inverseBinWidth;
5069
5070 MCelectronsErr *= inverseBinWidth;
5071 MCkaonsErr *= inverseBinWidth;
5072 MCmuonsErr *= inverseBinWidth;
5073 MCpionsErr *= inverseBinWidth;
5074 MCprotonsErr *= inverseBinWidth;
5075
5076 MCtotal = MCelectrons + MCkaons + MCpions + MCprotons + MCmuons;
5077
5078 if (MCtotal > 0) {
5079 hYieldElectronsMC->SetBinContent(slice + 1, MCelectrons);
5080 hYieldElectronsMC->SetBinError(slice + 1, MCelectronsErr);
5081
5082 hYieldMuonsMC->SetBinContent(slice + 1, MCmuons);
5083 hYieldMuonsMC->SetBinError(slice + 1, MCmuonsErr);
5084
5085 hYieldKaonsMC->SetBinContent(slice + 1, MCkaons);
5086 hYieldKaonsMC->SetBinError(slice + 1, MCkaonsErr);
5087
5088 hYieldPionsMC->SetBinContent(slice + 1, MCpions);
5089 hYieldPionsMC->SetBinError(slice + 1, MCpionsErr);
5090
5091 hYieldProtonsMC->SetBinContent(slice + 1, MCprotons);
5092 hYieldProtonsMC->SetBinError(slice + 1, MCprotonsErr);
5093
5094 hYieldSummedMC->SetBinContent(slice + 1, hYieldElectronsMC->GetBinContent(slice + 1) +
5095 hYieldKaonsMC->GetBinContent(slice + 1) +
5096 hYieldPionsMC->GetBinContent(slice + 1) +
5097 hYieldProtonsMC->GetBinContent(slice + 1) +
5098 hYieldMuonsMC->GetBinContent(slice + 1));
5099 hYieldSummedMC->SetBinError(slice + 1, TMath::Sqrt(TMath::Power(hYieldPionsMC->GetBinError(slice + 1), 2) +
5100 TMath::Power(hYieldElectronsMC->GetBinError(slice + 1), 2) +
5101 TMath::Power(hYieldKaonsMC->GetBinError(slice + 1), 2) +
5102 TMath::Power(hYieldProtonsMC->GetBinError(slice + 1), 2) +
5103 TMath::Power(hYieldMuonsMC->GetBinError(slice + 1), 2)));
5104
5105 // MCspecies and MCtotal are correlated. This can be taken into account via using the binomial error in the division
5106 hFractionElectronsMC->Divide(hYieldElectronsMC, hYieldSummedMC, 1., 1., "B");
5107 hFractionMuonsMC->Divide(hYieldMuonsMC, hYieldSummedMC, 1., 1., "B");
5108 hFractionKaonsMC->Divide(hYieldKaonsMC, hYieldSummedMC, 1., 1., "B");
5109 hFractionPionsMC->Divide(hYieldPionsMC, hYieldSummedMC, 1., 1., "B");
5110 hFractionProtonsMC->Divide(hYieldProtonsMC, hYieldSummedMC, 1., 1., "B");
5111 }
5112
5113 // Save further results
5114 if (slice % 18 == 0 || slice == pSliceLow) {
5115 saveF->cd();
5116
5117 if (hFractionElectrons)
5118 hFractionElectrons->Write(0, TObject::kWriteDelete);
5119
5120 if (hFractionKaons)
5121 hFractionKaons->Write(0, TObject::kWriteDelete);
5122
5123 if (hFractionPions)
5124 hFractionPions->Write(0, TObject::kWriteDelete);
5125
5126 if (hFractionProtons)
5127 hFractionProtons->Write(0, TObject::kWriteDelete);
5128
5129 if (hFractionMuons)
5130 hFractionMuons->Write(0, TObject::kWriteDelete);
5131
5132 if (hFractionSummed)
5133 hFractionSummed->Write(0, TObject::kWriteDelete);
5134
5135
5136 if (hFractionElectronsDeltaElectron)
5137 hFractionElectronsDeltaElectron->Write(0, TObject::kWriteDelete);
5138
5139 if (hFractionKaonsDeltaElectron)
5140 hFractionKaonsDeltaElectron->Write(0, TObject::kWriteDelete);
5141
5142 if (hFractionPionsDeltaElectron)
5143 hFractionPionsDeltaElectron->Write(0, TObject::kWriteDelete);
5144
5145 if (hFractionProtonsDeltaElectron)
5146 hFractionProtonsDeltaElectron->Write(0, TObject::kWriteDelete);
5147
5148 if (hFractionMuonsDeltaElectron)
5149 hFractionMuonsDeltaElectron->Write(0, TObject::kWriteDelete);
5150
5151
5152 if (hFractionElectronsDeltaPion)
5153 hFractionElectronsDeltaPion->Write(0, TObject::kWriteDelete);
5154
5155 if (hFractionKaonsDeltaPion)
5156 hFractionKaonsDeltaPion->Write(0, TObject::kWriteDelete);
5157
5158 if (hFractionPionsDeltaPion)
5159 hFractionPionsDeltaPion->Write(0, TObject::kWriteDelete);
5160
5161 if (hFractionProtonsDeltaPion)
5162 hFractionProtonsDeltaPion->Write(0, TObject::kWriteDelete);
5163
5164 if (hFractionMuonsDeltaPion)
5165 hFractionMuonsDeltaPion->Write(0, TObject::kWriteDelete);
5166
5167
5168 if (hFractionElectronsDeltaKaon)
5169 hFractionElectronsDeltaKaon->Write(0, TObject::kWriteDelete);
5170
5171 if (hFractionKaonsDeltaKaon)
5172 hFractionKaonsDeltaKaon->Write(0, TObject::kWriteDelete);
5173
5174 if (hFractionPionsDeltaKaon)
5175 hFractionPionsDeltaKaon->Write(0, TObject::kWriteDelete);
5176
5177 if (hFractionProtonsDeltaKaon)
5178 hFractionProtonsDeltaKaon->Write(0, TObject::kWriteDelete);
5179
5180 if (hFractionMuonsDeltaKaon)
5181 hFractionMuonsDeltaKaon->Write(0, TObject::kWriteDelete);
5182
5183
5184 if (hFractionElectronsDeltaProton)
5185 hFractionElectronsDeltaProton->Write(0, TObject::kWriteDelete);
5186
5187 if (hFractionKaonsDeltaProton)
5188 hFractionKaonsDeltaProton->Write(0, TObject::kWriteDelete);
5189
5190 if (hFractionPionsDeltaProton)
5191 hFractionPionsDeltaProton->Write(0, TObject::kWriteDelete);
5192
5193 if (hFractionProtonsDeltaProton)
5194 hFractionProtonsDeltaProton->Write(0, TObject::kWriteDelete);
5195
5196 if (hFractionMuonsDeltaProton)
5197 hFractionMuonsDeltaProton->Write(0, TObject::kWriteDelete);
5198
5199
5200 if (hFractionElectronsMC)
5201 hFractionElectronsMC->Write(0, TObject::kWriteDelete);
5202
5203 if (hFractionKaonsMC)
5204 hFractionKaonsMC->Write(0, TObject::kWriteDelete);
5205
5206 if (hFractionPionsMC)
5207 hFractionPionsMC->Write(0, TObject::kWriteDelete);
5208
5209 if (hFractionMuonsMC)
5210 hFractionMuonsMC->Write(0, TObject::kWriteDelete);
5211
5212 if (hFractionProtonsMC)
5213 hFractionProtonsMC->Write(0, TObject::kWriteDelete);
5214
5215
5216
5217
5218 if (hYieldElectrons)
5219 hYieldElectrons->Write(0, TObject::kWriteDelete);
5220
5221 if (hYieldKaons)
5222 hYieldKaons->Write(0, TObject::kWriteDelete);
5223
5224 if (hYieldPions)
5225 hYieldPions->Write(0, TObject::kWriteDelete);
5226
5227 if (hYieldProtons)
5228 hYieldProtons->Write(0, TObject::kWriteDelete);
5229
5230 if (hYieldMuons)
5231 hYieldMuons->Write(0, TObject::kWriteDelete);
5232
5233
5234 if (hYieldElectronsDeltaElectron)
5235 hYieldElectronsDeltaElectron->Write(0, TObject::kWriteDelete);
5236
5237 if (hYieldKaonsDeltaElectron)
5238 hYieldKaonsDeltaElectron->Write(0, TObject::kWriteDelete);
5239
5240 if (hYieldPionsDeltaElectron)
5241 hYieldPionsDeltaElectron->Write(0, TObject::kWriteDelete);
5242
5243 if (hYieldProtonsDeltaElectron)
5244 hYieldProtonsDeltaElectron->Write(0, TObject::kWriteDelete);
5245
5246 if (hYieldMuonsDeltaElectron)
5247 hYieldMuonsDeltaElectron->Write(0, TObject::kWriteDelete);
5248
5249
5250 if (hYieldElectronsDeltaPion)
5251 hYieldElectronsDeltaPion->Write(0, TObject::kWriteDelete);
5252
5253 if (hYieldKaonsDeltaPion)
5254 hYieldKaonsDeltaPion->Write(0, TObject::kWriteDelete);
5255
5256 if (hYieldPionsDeltaPion)
5257 hYieldPionsDeltaPion->Write(0, TObject::kWriteDelete);
5258
5259 if (hYieldProtonsDeltaPion)
5260 hYieldProtonsDeltaPion->Write(0, TObject::kWriteDelete);
5261
5262 if (hYieldMuonsDeltaPion)
5263 hYieldMuonsDeltaPion->Write(0, TObject::kWriteDelete);
5264
5265
5266 if (hYieldElectronsDeltaKaon)
5267 hYieldElectronsDeltaKaon->Write(0, TObject::kWriteDelete);
5268
5269 if (hYieldKaonsDeltaKaon)
5270 hYieldKaonsDeltaKaon->Write(0, TObject::kWriteDelete);
5271
5272 if (hYieldPionsDeltaKaon)
5273 hYieldPionsDeltaKaon->Write(0, TObject::kWriteDelete);
5274
5275 if (hYieldProtonsDeltaKaon)
5276 hYieldProtonsDeltaKaon->Write(0, TObject::kWriteDelete);
5277
5278 if (hYieldMuonsDeltaKaon)
5279 hYieldMuonsDeltaKaon->Write(0, TObject::kWriteDelete);
5280
5281
5282 if (hYieldElectronsDeltaProton)
5283 hYieldElectronsDeltaProton->Write(0, TObject::kWriteDelete);
5284
5285 if (hYieldKaonsDeltaProton)
5286 hYieldKaonsDeltaProton->Write(0, TObject::kWriteDelete);
5287
5288 if (hYieldPionsDeltaProton)
5289 hYieldPionsDeltaProton->Write(0, TObject::kWriteDelete);
5290
5291 if (hYieldProtonsDeltaProton)
5292 hYieldProtonsDeltaProton->Write(0, TObject::kWriteDelete);
5293
5294 if (hYieldMuonsDeltaProton)
5295 hYieldMuonsDeltaProton->Write(0, TObject::kWriteDelete);
5296
5297
5298 if (hYieldElectronsMC)
5299 hYieldElectronsMC->Write(0, TObject::kWriteDelete);
5300
5301 if (hYieldKaonsMC)
5302 hYieldKaonsMC->Write(0, TObject::kWriteDelete);
5303
5304 if (hYieldPionsMC)
5305 hYieldPionsMC->Write(0, TObject::kWriteDelete);
5306
5307 if (hYieldMuonsMC)
5308 hYieldMuonsMC->Write(0, TObject::kWriteDelete);
5309
5310 if (hYieldProtonsMC)
5311 hYieldProtonsMC->Write(0, TObject::kWriteDelete);
5312
5313 if (hYieldSummedMC)
5314 hYieldSummedMC->Write(0, TObject::kWriteDelete);
5315 }
5316
5317 TString saveDir = (mode == kPMpT) ? Form("SingleFit_%.2f_Pt_%.2f", binsPt[slice], binsPt[slice + 1])
5318 : Form("SingleFit_%.2f_%s_%.2f", hFractionPions->GetXaxis()->GetBinLowEdge(slice + 1),
5319 modeShortName[mode].Data(), hFractionPions->GetXaxis()->GetBinUpEdge(slice + 1));
5320 saveF->mkdir(saveDir.Data());
5321 saveF->cd(saveDir.Data());
5322
5323 for (Int_t species = 0; species < 4; species++) {
5324 if (cSingleFit[slice][species]) {
5325 cSingleFit[slice][species]->Write();
5326 delete cSingleFit[slice][species];
5327 }
5328 }
5329
5330 if (hDeltaPi[slice])
5331 hDeltaPi[slice]->Write();
5332
5333 if (hDeltaEl[slice])
5334 hDeltaEl[slice]->Write();
5335
5336 if (hDeltaKa[slice])
5337 hDeltaKa[slice]->Write();
5338
5339 if (hDeltaPr[slice])
5340 hDeltaPr[slice]->Write();
5341
5342
5343 if (hDeltaPiFitQA[slice])
5344 hDeltaPiFitQA[slice]->Write();
5345 delete hDeltaPiFitQA[slice];
5346
5347 if (hDeltaElFitQA[slice])
5348 hDeltaElFitQA[slice]->Write();
5349 delete hDeltaElFitQA[slice];
5350
5351 if (hDeltaKaFitQA[slice])
5352 hDeltaKaFitQA[slice]->Write();
5353 delete hDeltaKaFitQA[slice];
5354
5355 if (hDeltaPrFitQA[slice])
5356 hDeltaPrFitQA[slice]->Write();
5357 delete hDeltaPrFitQA[slice];
5358
5359 if (hGenDeltaElForElProj)
5360 hGenDeltaElForElProj->Write();
5361 delete hGenDeltaElForElProj;
5362
5363 if (hGenDeltaElForKaProj)
5364 hGenDeltaElForKaProj->Write();
5365 delete hGenDeltaElForKaProj;
5366
5367 if (hGenDeltaElForPiProj)
5368 hGenDeltaElForPiProj->Write();
5369 delete hGenDeltaElForPiProj;
5370
5371 if (hGenDeltaElForPrProj)
5372 hGenDeltaElForPrProj->Write();
5373 delete hGenDeltaElForPrProj;
5374
5375 if (hGenDeltaElForMuProj)
5376 hGenDeltaElForMuProj->Write();
5377 delete hGenDeltaElForMuProj;
5378
5379 //if (fitFuncTotalDeltaElectron[slice])
5380 // fitFuncTotalDeltaElectron[slice]->Write();
5381 delete fitFuncTotalDeltaElectron[slice];
5382
5383 if (hGenDeltaKaForElProj)
5384 hGenDeltaKaForElProj->Write();
5385 delete hGenDeltaKaForElProj;
5386
5387 if (hGenDeltaKaForKaProj)
5388 hGenDeltaKaForKaProj->Write();
5389 delete hGenDeltaKaForKaProj;
5390
5391 if (hGenDeltaKaForPiProj)
5392 hGenDeltaKaForPiProj->Write();
5393 delete hGenDeltaKaForPiProj;
5394
5395 if (hGenDeltaKaForPrProj)
5396 hGenDeltaKaForPrProj->Write();
5397 delete hGenDeltaKaForPrProj;
5398
5399 if (hGenDeltaKaForMuProj)
5400 hGenDeltaKaForMuProj->Write();
5401 delete hGenDeltaKaForMuProj;
5402
5403 //if (fitFuncTotalDeltaKaon[slice])
5404 // fitFuncTotalDeltaKaon[slice]->Write();
5405 delete fitFuncTotalDeltaKaon[slice];
5406
5407
5408 if (hGenDeltaPiForElProj)
5409 hGenDeltaPiForElProj->Write();
5410 delete hGenDeltaPiForElProj;
5411
5412 if (hGenDeltaPiForKaProj)
5413 hGenDeltaPiForKaProj->Write();
5414 delete hGenDeltaPiForKaProj;
5415
5416 if (hGenDeltaPiForPiProj)
5417 hGenDeltaPiForPiProj->Write();
5418 delete hGenDeltaPiForPiProj;
5419
5420 if (hGenDeltaPiForPrProj)
5421 hGenDeltaPiForPrProj->Write();
5422 delete hGenDeltaPiForPrProj;
5423
5424 if (hGenDeltaPiForMuProj)
5425 hGenDeltaPiForMuProj->Write();
5426 delete hGenDeltaPiForMuProj;
5427
5428 //if (fitFuncTotalDeltaPion[slice])
5429 // fitFuncTotalDeltaPion[slice]->Write();
5430 delete fitFuncTotalDeltaPion[slice];
5431
5432
5433 if (hGenDeltaPrForElProj)
5434 hGenDeltaPrForElProj->Write();
5435 delete hGenDeltaPrForElProj;
5436
5437 if (hGenDeltaPrForKaProj)
5438 hGenDeltaPrForKaProj->Write();
5439 delete hGenDeltaPrForKaProj;
5440
5441 if (hGenDeltaPrForPiProj)
5442 hGenDeltaPrForPiProj->Write();
5443 delete hGenDeltaPrForPiProj;
5444
5445 if (hGenDeltaPrForPrProj)
5446 hGenDeltaPrForPrProj->Write();
5447 delete hGenDeltaPrForPrProj;
5448
5449 if (hGenDeltaPrForMuProj)
5450 hGenDeltaPrForMuProj->Write();
5451 delete hGenDeltaPrForMuProj;
5452
5453 //if (fitFuncTotalDeltaProton[slice])
5454 // fitFuncTotalDeltaProton[slice]->Write();
5455 delete fitFuncTotalDeltaProton[slice];
5456
5457 delete totalDeltaElectron;
5458 delete totalDeltaKaon;
5459 delete totalDeltaPion;
5460 delete totalDeltaProton;
5461
5462 delete legend;
5463
5464 if (errFlag != 0)
5465 std::cout << "errFlag " << errFlag << std::endl << std::endl;
5466 }
5467 }
5468
5469 // Calculate MC to-pi ratios -> In MC the yields are uncorrelated, so just divide the histos to get the correct result
5470 hRatioToPiElectronsMC->Divide(hYieldElectronsMC, hYieldPionsMC);
5471 hRatioToPiMuonsMC->Divide(hYieldMuonsMC, hYieldPionsMC);
5472 hRatioToPiKaonsMC->Divide(hYieldKaonsMC, hYieldPionsMC);
5473 hRatioToPiProtonsMC->Divide(hYieldProtonsMC, hYieldPionsMC);
5474
5475
5476 TCanvas* cFractions = new TCanvas("cFractions", "Particle fractions",100,10,1200,800);
5477 cFractions->SetGridx(1);
5478 cFractions->SetGridy(1);
5479 cFractions->SetLogx(mode == kPMpT);
5480 hFractionPions->GetYaxis()->SetRangeUser(0.0, 1.0);
5481 SetReasonableAxisRange(hFractionPions->GetXaxis(), mode, pLow, pHigh);
5482 hFractionPions->GetXaxis()->SetMoreLogLabels(kTRUE);
5483 hFractionPions->GetXaxis()->SetNoExponent(kTRUE);
5484 hFractionPions->Draw("e p");
5485 if (plotIdentifiedSpectra) {
5486 SetReasonableAxisRange(hFractionPionsMC->GetXaxis(), mode, pLow, pHigh);
5487 hFractionPionsMC->Draw("e p same");
5488 }
5489
5490 SetReasonableAxisRange(hFractionKaons->GetXaxis(), mode, pLow, pHigh);
5491 hFractionKaons->Draw("e p same");
5492 if (plotIdentifiedSpectra) {
5493 SetReasonableAxisRange(hFractionKaonsMC->GetXaxis(), mode, pLow, pHigh);
5494 hFractionKaonsMC->Draw("e p same");
5495 }
5496
5497 SetReasonableAxisRange(hFractionProtons->GetXaxis(), mode, pLow, pHigh);
5498 hFractionProtons->Draw("e p same");
5499 if (plotIdentifiedSpectra) {
5500 SetReasonableAxisRange(hFractionProtonsMC->GetXaxis(), mode, pLow, pHigh);
5501 hFractionProtonsMC->Draw("e p same");
5502 }
5503
5504 SetReasonableAxisRange(hFractionElectrons->GetXaxis(), mode, pLow, pHigh);
5505 hFractionElectrons->Draw("e p same");
5506 if (plotIdentifiedSpectra) {
5507 SetReasonableAxisRange(hFractionElectronsMC->GetXaxis(), mode, pLow, pHigh);
5508 hFractionElectronsMC->Draw("e p same");
5509 }
5510
5511 if (takeIntoAccountMuons) {
5512 SetReasonableAxisRange(hFractionMuons->GetXaxis(), mode, pLow, pHigh);
5513 hFractionMuons->Draw("e p same");
5514 }
5515 if (plotIdentifiedSpectra) {
5516 SetReasonableAxisRange(hFractionMuonsMC->GetXaxis(), mode, pLow, pHigh);
5517 hFractionMuonsMC->Draw("e p same");
5518 }
5519
5520 hFractionSummed->Draw("e p same");
5521
5522 if (mode == kPMpT) {
5523 fElectronFraction->SetRange(lowFittingBoundElectronFraction, pHigh);
5524 fElectronFraction->Draw("same");
5525 }
5526
5527 TLegend* legend = new TLegend(0.622126, 0.605932, 0.862069, 0.855932);
5528 legend->SetBorderSize(0);
5529 legend->SetFillColor(0);
5530 if (plotIdentifiedSpectra)
5531 legend->SetNColumns(2);
5532 if (plotIdentifiedSpectra)
5533 legend->AddEntry((TObject*)0x0, "Fit", "");
5534 if (plotIdentifiedSpectra)
5535 legend->AddEntry((TObject*)0x0, identifiedLabels[isMC].Data(), "");
5536 legend->AddEntry(hFractionPions, "#pi", "p");
5537 if (plotIdentifiedSpectra)
5538 legend->AddEntry(hFractionPionsMC, "#pi", "p");
5539 legend->AddEntry(hFractionKaons, "K", "p");
5540 if (plotIdentifiedSpectra)
5541 legend->AddEntry(hFractionKaonsMC, "K", "p");
5542 legend->AddEntry(hFractionProtons, "p", "p");
5543 if (plotIdentifiedSpectra)
5544 legend->AddEntry(hFractionProtonsMC, "p", "p");
5545 legend->AddEntry(hFractionElectrons, "e", "p");
5546 if (plotIdentifiedSpectra)
5547 legend->AddEntry(hFractionElectronsMC, "e", "p");
5548 if (takeIntoAccountMuons)
5549 legend->AddEntry(hFractionMuons, "#mu", "p");
5550 else
5551 legend->AddEntry((TObject*)0x0, "", "");
5552 if (plotIdentifiedSpectra)
5553 legend->AddEntry(hFractionMuonsMC, "#mu", "p");
5554 legend->AddEntry(hFractionSummed, "Total", "p");
5555 legend->Draw();
5556
5557 ClearTitleFromHistoInCanvas(cFractions);
5558
5559
5560 // Compare data points with MC
5561 for (Int_t i = 1; i <= hFractionComparisonPions->GetNbinsX(); i++) {
5562 hFractionComparisonPions->SetBinContent(i, hFractionPions->GetBinContent(i));
5563 hFractionComparisonPions->SetBinError(i, hFractionPions->GetBinError(i));
5564
5565 hFractionComparisonElectrons->SetBinContent(i, hFractionElectrons->GetBinContent(i));
5566 hFractionComparisonElectrons->SetBinError(i, hFractionElectrons->GetBinError(i));
5567
5568 if (takeIntoAccountMuons) {
5569 hFractionComparisonMuons->SetBinContent(i, hFractionMuons->GetBinContent(i));
5570 hFractionComparisonMuons->SetBinError(i, hFractionMuons->GetBinError(i));
5571 }
5572
5573 hFractionComparisonKaons->SetBinContent(i, hFractionKaons->GetBinContent(i));
5574 hFractionComparisonKaons->SetBinError(i, hFractionKaons->GetBinError(i));
5575
5576 hFractionComparisonProtons->SetBinContent(i, hFractionProtons->GetBinContent(i));
5577 hFractionComparisonProtons->SetBinError(i, hFractionProtons->GetBinError(i));
5578
5579 hFractionComparisonTotal->SetBinContent(i, hFractionSummed->GetBinContent(i));
5580 hFractionComparisonTotal->SetBinError(i, hFractionSummed->GetBinError(i));
5581 }
5582
5583 hFractionComparisonPions->Divide(hFractionPionsMC);
5584 hFractionComparisonElectrons->Divide(hFractionElectronsMC);
5585 if (takeIntoAccountMuons)
5586 hFractionComparisonMuons->Divide(hFractionMuonsMC);
5587 hFractionComparisonKaons->Divide(hFractionKaonsMC);
5588 hFractionComparisonProtons->Divide(hFractionProtonsMC);
5589
5590
5591 TCanvas* cFractionComparisons = new TCanvas("cFractionComparisons", "Particle fraction comparisons",100,10,1200,800);
5592 cFractionComparisons->SetGridx(1);
5593 cFractionComparisons->SetGridy(1);
5594 cFractionComparisons->SetLogx(mode == kPMpT);
5595 hFractionComparisonPions->GetYaxis()->SetRangeUser(0.0, 10.0);
5596 SetReasonableAxisRange(hFractionComparisonPions->GetXaxis(), mode, pLow, pHigh);
5597 hFractionComparisonPions->GetXaxis()->SetMoreLogLabels(kTRUE);
5598 hFractionComparisonPions->GetXaxis()->SetNoExponent(kTRUE);
5599 hFractionComparisonPions->Draw("e p");
5600
5601 hFractionComparisonElectrons->GetYaxis()->SetRangeUser(0.0, 10.0);
5602 SetReasonableAxisRange(hFractionComparisonElectrons->GetXaxis(), mode, pLow, pHigh);
5603 hFractionComparisonElectrons->Draw("e p same");
5604
5605 if (takeIntoAccountMuons) {
5606 hFractionComparisonMuons->GetYaxis()->SetRangeUser(0.0, 10.0);
5607 SetReasonableAxisRange(hFractionComparisonMuons->GetXaxis(), mode, pLow, pHigh);
5608 hFractionComparisonMuons->Draw("e p same");
5609 }
5610
5611 hFractionComparisonKaons->GetYaxis()->SetRangeUser(0.0, 10.0);
5612 SetReasonableAxisRange(hFractionComparisonKaons->GetXaxis(), mode, pLow, pHigh);
5613 hFractionComparisonKaons->Draw("e p same");
5614
5615 hFractionComparisonProtons->GetYaxis()->SetRangeUser(0.0, 10.0);
5616 SetReasonableAxisRange(hFractionComparisonProtons->GetXaxis(), mode, pLow, pHigh);
5617 hFractionComparisonProtons->Draw("e p same");
5618
5619 hFractionComparisonTotal->GetYaxis()->SetRangeUser(0.0, 10.0);
5620 SetReasonableAxisRange(hFractionComparisonTotal->GetXaxis(), mode, pLow, pHigh);
5621 hFractionComparisonTotal->Draw("e p same");
5622
5623 TLegend* legend2 = new TLegend(0.622126, 0.605932, 0.862069, 0.855932);
5624 legend2->SetBorderSize(0);
5625 legend2->SetFillColor(0);
5626 legend2->SetNColumns(2);
5627 legend2->AddEntry(hFractionComparisonPions, "#pi", "p");
5628 legend2->AddEntry(hFractionComparisonKaons, "K", "p");
5629 legend2->AddEntry(hFractionComparisonProtons, "p", "p");
5630 legend2->AddEntry(hFractionComparisonElectrons, "e", "p");
5631 if (takeIntoAccountMuons)
5632 legend2->AddEntry(hFractionComparisonMuons, "#mu", "p");
5633 legend2->AddEntry(hFractionComparisonTotal, "Total", "p");
5634 legend2->Draw();
5635
5636 ClearTitleFromHistoInCanvas(cFractionComparisons);
5637
5638 // Normalise the yields
5639 normaliseYieldHist(hYieldPions, numEvents, deta);
5640 normaliseYieldHist(hYieldPionsMC, numEvents, deta);
5641 normaliseYieldHist(hYieldPionsDeltaElectron, numEvents, deta);
5642 normaliseYieldHist(hYieldPionsDeltaPion, numEvents, deta);
5643 normaliseYieldHist(hYieldPionsDeltaKaon, numEvents, deta);
5644 normaliseYieldHist(hYieldPionsDeltaProton, numEvents, deta);
5645
5646 normaliseYieldHist(hYieldElectrons, numEvents, deta);
5647 normaliseYieldHist(hYieldElectronsMC, numEvents, deta);
5648 normaliseYieldHist(hYieldElectronsDeltaElectron, numEvents, deta);
5649 normaliseYieldHist(hYieldElectronsDeltaPion, numEvents, deta);
5650 normaliseYieldHist(hYieldElectronsDeltaKaon, numEvents, deta);
5651 normaliseYieldHist(hYieldElectronsDeltaProton, numEvents, deta);
5652
5653 normaliseYieldHist(hYieldMuons, numEvents, deta);
5654 normaliseYieldHist(hYieldMuonsMC, numEvents, deta);
5655 normaliseYieldHist(hYieldMuonsDeltaElectron, numEvents, deta);
5656 normaliseYieldHist(hYieldMuonsDeltaPion, numEvents, deta);
5657 normaliseYieldHist(hYieldMuonsDeltaKaon, numEvents, deta);
5658 normaliseYieldHist(hYieldMuonsDeltaProton, numEvents, deta);
5659
5660 normaliseYieldHist(hYieldKaons, numEvents, deta);
5661 normaliseYieldHist(hYieldKaonsMC, numEvents, deta);
5662 normaliseYieldHist(hYieldKaonsDeltaElectron, numEvents, deta);
5663 normaliseYieldHist(hYieldKaonsDeltaPion, numEvents, deta);
5664 normaliseYieldHist(hYieldKaonsDeltaKaon, numEvents, deta);
5665 normaliseYieldHist(hYieldKaonsDeltaProton, numEvents, deta);
5666
5667 normaliseYieldHist(hYieldProtons, numEvents, deta);
5668 normaliseYieldHist(hYieldProtonsMC, numEvents, deta);
5669 normaliseYieldHist(hYieldProtonsDeltaElectron, numEvents, deta);
5670 normaliseYieldHist(hYieldProtonsDeltaPion, numEvents, deta);
5671 normaliseYieldHist(hYieldProtonsDeltaKaon, numEvents, deta);
5672 normaliseYieldHist(hYieldProtonsDeltaProton, numEvents, deta);
5673
5674 normaliseYieldHist(hYieldSummedMC, numEvents, deta);
5675
5676 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
5677 if (hMCgenYieldsPrimSpecies[i]) {
5678 Int_t color = kBlack;
5679
5680 switch (i) {
5681 case AliPID::kElectron:
5682 color = getLineColor(kEl);
5683 break;
5684 case AliPID::kKaon:
5685 color = getLineColor(kKa);
5686 break;
5687 case AliPID::kMuon:
5688 color = getLineColor(kMu);
5689 break;
5690 case AliPID::kPion:
5691 color = getLineColor(kPi);
5692 break;
5693 case AliPID::kProton:
5694 color = getLineColor(kPr);
5695 break;
5696 }
5697
5698 hMCgenYieldsPrimSpecies[i]->SetLineColor(color);
5699 hMCgenYieldsPrimSpecies[i]->SetMarkerColor(color);
5700 hMCgenYieldsPrimSpecies[i]->SetMarkerStyle(28);
5701 hMCgenYieldsPrimSpecies[i]->SetLineStyle(1);
5702 hMCgenYieldsPrimSpecies[i]->GetXaxis()->SetTitleOffset(1.0);
5703 hMCgenYieldsPrimSpecies[i]->SetStats(kFALSE);
5704
5705 SetReasonableAxisRange(hMCgenYieldsPrimSpecies[i]->GetXaxis(), kPMpT, pLow, pHigh);
5706 normaliseGenYieldMCtruthHist(hMCgenYieldsPrimSpecies[i], numEvents, deta);
5707 }
5708 }
5709
5710
5711 // Compare data points with MC (yield)
5712 for (Int_t i = 1; i <= hYieldComparisonPions->GetNbinsX(); i++) {
5713 hYieldComparisonPions->SetBinContent(i, hYieldPions->GetBinContent(i));
5714 hYieldComparisonPions->SetBinError(i, hYieldPions->GetBinError(i));
5715
5716 hYieldComparisonElectrons->SetBinContent(i, hYieldElectrons->GetBinContent(i));
5717 hYieldComparisonElectrons->SetBinError(i, hYieldElectrons->GetBinError(i));
5718
5719 if (takeIntoAccountMuons) {
5720 hYieldComparisonMuons->SetBinContent(i, hYieldMuons->GetBinContent(i));
5721 hYieldComparisonMuons->SetBinError(i, hYieldMuons->GetBinError(i));
5722 }
5723
5724 hYieldComparisonKaons->SetBinContent(i, hYieldKaons->GetBinContent(i));
5725 hYieldComparisonKaons->SetBinError(i, hYieldKaons->GetBinError(i));
5726
5727 hYieldComparisonProtons->SetBinContent(i, hYieldProtons->GetBinContent(i));
5728 hYieldComparisonProtons->SetBinError(i, hYieldProtons->GetBinError(i));
5729 }
5730
5731 hYieldComparisonPions->Divide(hYieldPionsMC);
5732 hYieldComparisonElectrons->Divide(hYieldElectronsMC);
5733 if (takeIntoAccountMuons)
5734 hYieldComparisonMuons->Divide(hYieldMuonsMC);
5735 hYieldComparisonKaons->Divide(hYieldKaonsMC);
5736 hYieldComparisonProtons->Divide(hYieldProtonsMC);
5737
5738
5739 TCanvas* cYieldComparisons = new TCanvas("cYieldComparisons", "Particle yield comparisons",100,10,1200,800);
5740 cYieldComparisons->SetGridx(1);
5741 cYieldComparisons->SetGridy(1);
5742 cYieldComparisons->SetLogx(mode == kPMpT);
5743 hYieldComparisonPions->GetYaxis()->SetRangeUser(0.0, 10.0);
5744 SetReasonableAxisRange(hYieldComparisonPions->GetXaxis(), mode, pLow, pHigh);
5745 hYieldComparisonPions->GetXaxis()->SetMoreLogLabels(kTRUE);
5746 hYieldComparisonPions->GetXaxis()->SetNoExponent(kTRUE);
5747 hYieldComparisonPions->Draw("e p");
5748
5749 hYieldComparisonElectrons->GetYaxis()->SetRangeUser(0.0, 10.0);
5750 SetReasonableAxisRange(hYieldComparisonElectrons->GetXaxis(), mode, pLow, pHigh);
5751 hYieldComparisonElectrons->Draw("e p same");
5752
5753 if (takeIntoAccountMuons) {
5754 hYieldComparisonMuons->GetYaxis()->SetRangeUser(0.0, 10.0);
5755 SetReasonableAxisRange(hYieldComparisonMuons->GetXaxis(), mode, pLow, pHigh);
5756 hYieldComparisonMuons->Draw("e p same");
5757 }
5758
5759 hYieldComparisonKaons->GetYaxis()->SetRangeUser(0.0, 10.0);
5760 SetReasonableAxisRange(hYieldComparisonKaons->GetXaxis(), mode, pLow, pHigh);
5761 hYieldComparisonKaons->Draw("e p same");
5762
5763 hYieldComparisonProtons->GetYaxis()->SetRangeUser(0.0, 10.0);
5764 SetReasonableAxisRange(hYieldComparisonProtons->GetXaxis(), mode, pLow, pHigh);
5765 hYieldComparisonProtons->Draw("e p same");
5766
5767 TLegend* legend3 = new TLegend(0.622126, 0.605932, 0.862069, 0.855932);
5768 legend3->SetBorderSize(0);
5769 legend3->SetFillColor(0);
5770 legend3->SetNColumns(2);
5771 legend3->AddEntry(hYieldComparisonPions, "#pi", "p");
5772 legend3->AddEntry(hYieldComparisonKaons, "K", "p");
5773 legend3->AddEntry(hYieldComparisonProtons, "p", "p");
5774 legend3->AddEntry(hYieldComparisonElectrons, "e", "p");
5775 if (takeIntoAccountMuons)
5776 legend3->AddEntry(hYieldComparisonMuons, "#mu", "p");
5777 legend3->Draw();
5778
5779 ClearTitleFromHistoInCanvas(cYieldComparisons);
5780
5781
5782
5783
5784 TCanvas* cFractionsPions = drawFractionHistos("cFractionsPions", "Pion fractions", mode, pLow, pHigh, hFractionPionsDeltaPion,
5785 hFractionPionsDeltaElectron, hFractionPionsDeltaKaon, hFractionPionsDeltaProton,
5786 hFractionPionsMC, plotIdentifiedSpectra);
5787
5788
5789 TCanvas* cFractionsElectrons = drawFractionHistos("cFractionsElectrons", "Electron fractions", mode, pLow, pHigh,
5790 hFractionElectronsDeltaPion, hFractionElectronsDeltaElectron,
5791 hFractionElectronsDeltaKaon, hFractionElectronsDeltaProton, hFractionElectronsMC,
5792 plotIdentifiedSpectra);
5793
5794 TCanvas* cFractionsKaons = drawFractionHistos("cFractionsKaons", "Kaon fractions", mode, pLow, pHigh, hFractionKaonsDeltaPion,
5795 hFractionKaonsDeltaElectron, hFractionKaonsDeltaKaon, hFractionKaonsDeltaProton,
5796 hFractionKaonsMC, plotIdentifiedSpectra);
5797
5798 TCanvas* cFractionsProtons = drawFractionHistos("cFractionsProtons", "Proton fractions", mode, pLow, pHigh, hFractionProtonsDeltaPion,
5799 hFractionProtonsDeltaElectron, hFractionProtonsDeltaKaon, hFractionProtonsDeltaProton,
5800 hFractionProtonsMC, plotIdentifiedSpectra);
5801
5802 TCanvas* cFractionsMuons = drawFractionHistos("cFractionsMuons", "Muon fractions", mode, pLow, pHigh, hFractionMuonsDeltaPion,
5803 hFractionMuonsDeltaElectron, hFractionMuonsDeltaKaon, hFractionMuonsDeltaProton,
5804 hFractionMuonsMC, plotIdentifiedSpectra);
5805
5806
5807
5808 TCanvas* cYields = new TCanvas("cYields", "Particle yields",100,10,1200,800);
5809 cYields->SetGridx(1);
5810 cYields->SetGridy(1);
5811 cYields->SetLogx(mode == kPMpT);
5812 cYields->SetLogy(1);
5813 hYieldPions->GetYaxis()->SetRangeUser(hYieldElectrons->GetBinContent(hYieldElectrons->FindLastBinAbove(0.)) / 10.,
5814 hYieldPions->GetBinContent(hYieldPions->GetMaximumBin()) * 10.);
5815 SetReasonableAxisRange(hYieldPions->GetXaxis(), mode, pLow, pHigh);
5816 hYieldPions->GetXaxis()->SetMoreLogLabels(kTRUE);
5817 hYieldPions->GetXaxis()->SetNoExponent(kTRUE);
5818 hYieldPions->Draw("e p");
5819 if (plotIdentifiedSpectra) {
5820 SetReasonableAxisRange(hYieldPionsMC->GetXaxis(), mode, pLow, pHigh);
5821 hYieldPionsMC->Draw("e p same");
5822 }
5823
5824 SetReasonableAxisRange(hYieldKaons->GetXaxis(), mode, pLow, pHigh);
5825 hYieldKaons->Draw("e p same");
5826 if (plotIdentifiedSpectra) {
5827 SetReasonableAxisRange(hYieldKaonsMC->GetXaxis(), mode, pLow, pHigh);
5828 hYieldKaonsMC->Draw("e p same");
5829 }
5830
5831 SetReasonableAxisRange(hYieldProtons->GetXaxis(), mode, pLow, pHigh);
5832 hYieldProtons->Draw("e p same");
5833 if (plotIdentifiedSpectra) {
5834 SetReasonableAxisRange(hYieldProtonsMC->GetXaxis(), mode, pLow, pHigh);
5835 hYieldProtonsMC->Draw("e p same");
5836 }
5837
5838 if (takeIntoAccountMuons) {
5839 SetReasonableAxisRange(hYieldMuons->GetXaxis(), mode, pLow, pHigh);
5840 hYieldMuons->Draw("e p same");
5841 if (plotIdentifiedSpectra) {
5842 SetReasonableAxisRange(hYieldMuonsMC->GetXaxis(), mode, pLow, pHigh);
5843 hYieldMuonsMC->Draw("e p same");
5844 }
5845 }
5846
5847 SetReasonableAxisRange(hYieldElectrons->GetXaxis(), mode, pLow, pHigh);
5848 hYieldElectrons->Draw("e p same");
5849 if (plotIdentifiedSpectra) {
5850 SetReasonableAxisRange(hYieldElectronsMC->GetXaxis(), mode, pLow, pHigh);
5851 hYieldElectronsMC->Draw("e p same");
5852 }
5853
5854 TLegend* legendYields = new TLegend(0.622126, 0.605932, 0.862069, 0.855932);
5855 legendYields->SetBorderSize(0);
5856 legendYields->SetFillColor(0);
5857 if (plotIdentifiedSpectra)
5858 legendYields->SetNColumns(2);
5859 if (plotIdentifiedSpectra)
5860 legendYields->AddEntry((TObject*)0x0, "Fit", "");
5861 if (plotIdentifiedSpectra)
5862 legendYields->AddEntry((TObject*)0x0, identifiedLabels[isMC].Data(), "");
5863 legendYields->AddEntry(hYieldPions, "#pi", "p");
5864 if (plotIdentifiedSpectra)
5865 legendYields->AddEntry(hYieldPionsMC, "#pi", "p");
5866 legendYields->AddEntry(hYieldKaons, "K", "p");
5867 if (plotIdentifiedSpectra)
5868 legendYields->AddEntry(hYieldKaonsMC, "K", "p");
5869 legendYields->AddEntry(hYieldProtons, "p", "p");
5870 if (plotIdentifiedSpectra)
5871 legendYields->AddEntry(hYieldProtonsMC, "p", "p");
5872 legendYields->AddEntry(hYieldElectrons, "e", "p");
5873 if (plotIdentifiedSpectra)
5874 legendYields->AddEntry(hYieldElectronsMC, "e", "p");
5875 if (takeIntoAccountMuons)
5876 legendYields->AddEntry(hYieldMuons, "#mu", "p");
5877 else
5878 legendYields->AddEntry((TObject*)0x0, "", "");
5879 if (plotIdentifiedSpectra)
5880 legendYields->AddEntry(hYieldMuonsMC, "#mu", "p");
5881 legendYields->Draw();
5882
5883 ClearTitleFromHistoInCanvas(cYields);
5884
5885
5886 TCanvas* cYieldsPions = drawYieldHistos("cYieldsPions", "Pion yields", mode, pLow, pHigh, hYieldPionsDeltaPion, hYieldPionsDeltaElectron,
5887 hYieldPionsDeltaKaon, hYieldPionsDeltaProton, hYieldPionsMC, plotIdentifiedSpectra);
5888
5889
5890 TCanvas* cYieldsElectrons = drawYieldHistos("cYieldsElectrons", "Electron yields", mode, pLow, pHigh, hYieldElectronsDeltaPion,
5891 hYieldElectronsDeltaElectron, hYieldElectronsDeltaKaon, hYieldElectronsDeltaProton, hYieldElectronsMC,
5892 plotIdentifiedSpectra);
5893
5894 TCanvas* cYieldsKaons = drawYieldHistos("cYieldsKaons", "Kaon yields", mode, pLow, pHigh, hYieldKaonsDeltaPion, hYieldKaonsDeltaElectron,
5895 hYieldKaonsDeltaKaon, hYieldKaonsDeltaProton, hYieldKaonsMC, plotIdentifiedSpectra);
5896
5897 TCanvas* cYieldsProtons = drawYieldHistos("cYieldsProtons", "Proton yields", mode, pLow, pHigh, hYieldProtonsDeltaPion, hYieldProtonsDeltaElectron,
5898 hYieldProtonsDeltaKaon, hYieldProtonsDeltaProton, hYieldProtonsMC, plotIdentifiedSpectra);
5899
5900 TCanvas* cYieldsMuons = drawYieldHistos("cYieldsMuons", "Muon yields", mode, pLow, pHigh, hYieldMuonsDeltaPion, hYieldMuonsDeltaElectron,
5901 hYieldMuonsDeltaKaon, hYieldMuonsDeltaProton, hYieldMuonsMC, plotIdentifiedSpectra);
5902
5903
5904 // Save final results
5905 saveF->cd();
5906
5907 if (fElectronFraction)
5908 fElectronFraction->Write();
5909
5910 if (hFractionElectrons)
5911 hFractionElectrons->Write(0, TObject::kWriteDelete);
5912
5913 if (hFractionKaons)
5914 hFractionKaons->Write(0, TObject::kWriteDelete);
5915
5916 if (hFractionPions)
5917 hFractionPions->Write(0, TObject::kWriteDelete);
5918
5919 if (hFractionProtons)
5920 hFractionProtons->Write(0, TObject::kWriteDelete);
5921
5922 if (hFractionMuons)
5923 hFractionMuons->Write(0, TObject::kWriteDelete);
5924
5925 if (hFractionSummed)
5926 hFractionSummed->Write(0, TObject::kWriteDelete);
5927
5928
5929 if (hFractionElectronsDeltaElectron)
5930 hFractionElectronsDeltaElectron->Write(0, TObject::kWriteDelete);
5931
5932 if (hFractionKaonsDeltaElectron)
5933 hFractionKaonsDeltaElectron->Write(0, TObject::kWriteDelete);
5934
5935 if (hFractionPionsDeltaElectron)
5936 hFractionPionsDeltaElectron->Write(0, TObject::kWriteDelete);
5937
5938 if (hFractionProtonsDeltaElectron)
5939 hFractionProtonsDeltaElectron->Write(0, TObject::kWriteDelete);
5940
5941 if (hFractionMuonsDeltaElectron)
5942 hFractionMuonsDeltaElectron->Write(0, TObject::kWriteDelete);
5943
5944
5945 if (hFractionElectronsDeltaPion)
5946 hFractionElectronsDeltaPion->Write(0, TObject::kWriteDelete);
5947
5948 if (hFractionKaonsDeltaPion)
5949 hFractionKaonsDeltaPion->Write(0, TObject::kWriteDelete);
5950
5951 if (hFractionPionsDeltaPion)
5952 hFractionPionsDeltaPion->Write(0, TObject::kWriteDelete);
5953
5954 if (hFractionProtonsDeltaPion)
5955 hFractionProtonsDeltaPion->Write(0, TObject::kWriteDelete);
5956
5957 if (hFractionMuonsDeltaPion)
5958 hFractionMuonsDeltaPion->Write(0, TObject::kWriteDelete);
5959
5960
5961 if (hFractionElectronsDeltaKaon)
5962 hFractionElectronsDeltaKaon->Write(0, TObject::kWriteDelete);
5963
5964 if (hFractionKaonsDeltaKaon)
5965 hFractionKaonsDeltaKaon->Write(0, TObject::kWriteDelete);
5966
5967 if (hFractionPionsDeltaKaon)
5968 hFractionPionsDeltaKaon->Write(0, TObject::kWriteDelete);
5969
5970 if (hFractionProtonsDeltaKaon)
5971 hFractionProtonsDeltaKaon->Write(0, TObject::kWriteDelete);
5972
5973 if (hFractionMuonsDeltaKaon)
5974 hFractionMuonsDeltaKaon->Write(0, TObject::kWriteDelete);
5975
5976
5977 if (hFractionElectronsDeltaProton)
5978 hFractionElectronsDeltaProton->Write(0, TObject::kWriteDelete);
5979
5980 if (hFractionKaonsDeltaProton)
5981 hFractionKaonsDeltaProton->Write(0, TObject::kWriteDelete);
5982
5983 if (hFractionPionsDeltaProton)
5984 hFractionPionsDeltaProton->Write(0, TObject::kWriteDelete);
5985
5986 if (hFractionProtonsDeltaProton)
5987 hFractionProtonsDeltaProton->Write(0, TObject::kWriteDelete);
5988
5989 if (hFractionMuonsDeltaProton)
5990 hFractionMuonsDeltaProton->Write(0, TObject::kWriteDelete);
5991
5992 if (hNumEvents)
5993 hNumEvents->Write();
5994
5995 if (cFractions)
5996 cFractions->Write();
5997 if (cFractionsPions)
5998 cFractionsPions->Write();
5999 if (cFractionsElectrons)
6000 cFractionsElectrons->Write();
6001 if (cFractionsKaons)
6002 cFractionsKaons->Write();
6003 if (cFractionsProtons)
6004 cFractionsProtons->Write();
6005 if (cFractionsMuons)
6006 cFractionsMuons->Write();
6007
6008
6009 if (hFractionElectronsMC)
6010 hFractionElectronsMC->Write(0, TObject::kWriteDelete);
6011
6012 if (hFractionKaonsMC)
6013 hFractionKaonsMC->Write(0, TObject::kWriteDelete);
6014
6015 if (hFractionPionsMC)
6016 hFractionPionsMC->Write(0, TObject::kWriteDelete);
6017
6018 if (hFractionMuonsMC)
6019 hFractionMuonsMC->Write(0, TObject::kWriteDelete);
6020
6021 if (hFractionProtonsMC)
6022 hFractionProtonsMC->Write(0, TObject::kWriteDelete);
6023
6024
6025 if (hFractionComparisonElectrons)
6026 hFractionComparisonElectrons->Write(0, TObject::kWriteDelete);
6027
6028 if (hFractionComparisonMuons)
6029 hFractionComparisonMuons->Write(0, TObject::kWriteDelete);
6030
6031 if (hFractionComparisonKaons)
6032 hFractionComparisonKaons->Write(0, TObject::kWriteDelete);
6033
6034 if (hFractionComparisonPions)
6035 hFractionComparisonPions->Write(0, TObject::kWriteDelete);
6036
6037 if (hFractionComparisonProtons)
6038 hFractionComparisonProtons->Write(0, TObject::kWriteDelete);
6039
6040 if (hFractionComparisonTotal)
6041 hFractionComparisonTotal->Write(0, TObject::kWriteDelete);
6042
6043 if (cFractionComparisons)
6044 cFractionComparisons->Write();
6045
6046
6047 if (hYieldComparisonElectrons)
6048 hYieldComparisonElectrons->Write(0, TObject::kWriteDelete);
6049
6050 if (hYieldComparisonMuons)
6051 hYieldComparisonMuons->Write(0, TObject::kWriteDelete);
6052
6053 if (hYieldComparisonKaons)
6054 hYieldComparisonKaons->Write(0, TObject::kWriteDelete);
6055
6056 if (hYieldComparisonPions)
6057 hYieldComparisonPions->Write(0, TObject::kWriteDelete);
6058
6059 if (hYieldComparisonProtons)
6060 hYieldComparisonProtons->Write(0, TObject::kWriteDelete);
6061
6062 if (cYieldComparisons)
6063 cYieldComparisons->Write();
6064
6065
6066 if (hYieldElectrons)
6067 hYieldElectrons->Write(0, TObject::kWriteDelete);
6068
6069 if (hYieldKaons)
6070 hYieldKaons->Write(0, TObject::kWriteDelete);
6071
6072 if (hYieldPions)
6073 hYieldPions->Write(0, TObject::kWriteDelete);
6074
6075 if (hYieldProtons)
6076 hYieldProtons->Write(0, TObject::kWriteDelete);
6077
6078 if (hYieldMuons)
6079 hYieldMuons->Write(0, TObject::kWriteDelete);
6080
6081
6082 if (hYieldElectronsDeltaElectron)
6083 hYieldElectronsDeltaElectron->Write(0, TObject::kWriteDelete);
6084
6085 if (hYieldKaonsDeltaElectron)
6086 hYieldKaonsDeltaElectron->Write(0, TObject::kWriteDelete);
6087
6088 if (hYieldPionsDeltaElectron)
6089 hYieldPionsDeltaElectron->Write(0, TObject::kWriteDelete);
6090
6091 if (hYieldProtonsDeltaElectron)
6092 hYieldProtonsDeltaElectron->Write(0, TObject::kWriteDelete);
6093
6094 if (hYieldMuonsDeltaElectron)
6095 hYieldMuonsDeltaElectron->Write(0, TObject::kWriteDelete);
6096
6097
6098 if (hYieldElectronsDeltaPion)
6099 hYieldElectronsDeltaPion->Write(0, TObject::kWriteDelete);
6100
6101 if (hYieldKaonsDeltaPion)
6102 hYieldKaonsDeltaPion->Write(0, TObject::kWriteDelete);
6103
6104 if (hYieldPionsDeltaPion)
6105 hYieldPionsDeltaPion->Write(0, TObject::kWriteDelete);
6106
6107 if (hYieldProtonsDeltaPion)
6108 hYieldProtonsDeltaPion->Write(0, TObject::kWriteDelete);
6109
6110 if (hYieldMuonsDeltaPion)
6111 hYieldMuonsDeltaPion->Write(0, TObject::kWriteDelete);
6112
6113
6114 if (hYieldElectronsDeltaKaon)
6115 hYieldElectronsDeltaKaon->Write(0, TObject::kWriteDelete);
6116
6117 if (hYieldKaonsDeltaKaon)
6118 hYieldKaonsDeltaKaon->Write(0, TObject::kWriteDelete);
6119
6120 if (hYieldPionsDeltaKaon)
6121 hYieldPionsDeltaKaon->Write(0, TObject::kWriteDelete);
6122
6123 if (hYieldProtonsDeltaKaon)
6124 hYieldProtonsDeltaKaon->Write(0, TObject::kWriteDelete);
6125
6126 if (hYieldMuonsDeltaKaon)
6127 hYieldMuonsDeltaKaon->Write(0, TObject::kWriteDelete);
6128
6129
6130 if (hYieldElectronsDeltaProton)
6131 hYieldElectronsDeltaProton->Write(0, TObject::kWriteDelete);
6132
6133 if (hYieldKaonsDeltaProton)
6134 hYieldKaonsDeltaProton->Write(0, TObject::kWriteDelete);
6135
6136 if (hYieldPionsDeltaProton)
6137 hYieldPionsDeltaProton->Write(0, TObject::kWriteDelete);
6138
6139 if (hYieldProtonsDeltaProton)
6140 hYieldProtonsDeltaProton->Write(0, TObject::kWriteDelete);
6141
6142 if (hYieldMuonsDeltaProton)
6143 hYieldMuonsDeltaProton->Write(0, TObject::kWriteDelete);
6144
6145
6146 if (hYieldElectronsMC)
6147 hYieldElectronsMC->Write(0, TObject::kWriteDelete);
6148
6149 if (hYieldKaonsMC)
6150 hYieldKaonsMC->Write(0, TObject::kWriteDelete);
6151
6152 if (hYieldPionsMC)
6153 hYieldPionsMC->Write(0, TObject::kWriteDelete);
6154
6155 if (hYieldMuonsMC)
6156 hYieldMuonsMC->Write(0, TObject::kWriteDelete);
6157
6158 if (hYieldProtonsMC)
6159 hYieldProtonsMC->Write(0, TObject::kWriteDelete);
6160
6161 if (hYieldSummedMC)
6162 hYieldSummedMC->Write(0, TObject::kWriteDelete);
6163
6164
6165 if (hRatioToPiElectrons)
6166 hRatioToPiElectrons->Write(0, TObject::kWriteDelete);
6167
6168 if (hRatioToPiMuons)
6169 hRatioToPiMuons->Write(0, TObject::kWriteDelete);
6170
6171 if (hRatioToPiKaons)
6172 hRatioToPiKaons->Write(0, TObject::kWriteDelete);
6173
6174 if (hRatioToPiProtons)
6175 hRatioToPiProtons->Write(0, TObject::kWriteDelete);
6176
6177 if (hRatioToPiElectronsMC)
6178 hRatioToPiElectronsMC->Write(0, TObject::kWriteDelete);
6179
6180 if (hRatioToPiMuonsMC)
6181 hRatioToPiMuonsMC->Write(0, TObject::kWriteDelete);
6182
6183 if (hRatioToPiKaonsMC)
6184 hRatioToPiKaonsMC->Write(0, TObject::kWriteDelete);
6185
6186 if (hRatioToPiProtonsMC)
6187 hRatioToPiProtonsMC->Write(0, TObject::kWriteDelete);
6188
6189
6190
6191 if (hReducedChiSquarePt)
6192 hReducedChiSquarePt->Write(0, TObject::kWriteDelete);
6193
6194 if (cYields)
6195 cYields->Write();
6196 if (cYieldsPions)
6197 cYieldsPions->Write();
6198 if (cYieldsElectrons)
6199 cYieldsElectrons->Write();
6200 if (cYieldsKaons)
6201 cYieldsKaons->Write();
6202 if (cYieldsProtons)
6203 cYieldsProtons->Write();
6204 if (cYieldsMuons)
6205 cYieldsMuons->Write();
6206
6207 for (Int_t i = 0; i < AliPID::kSPECIES; i++) {
6208 if (hMCgenYieldsPrimSpecies[i])
6209 hMCgenYieldsPrimSpecies[i]->Write();
6210 }
6211
6212 if (filePathNameResults)
6213 *filePathNameResults = saveFName;
6214
6215 if (TMath::Abs(mathFit->GetScaleFactorError() - 1.) > 1e-6) {
6216 // If the deltaPrime range is large enough, we artificially get a factor 4 in statistics by looking at the four
6217 // different deltaPrimeSpecies, which have (except for binning effects) the same information.
6218 // Therefore, to get the "real" statistical error, we need to multiply the obtained error by sqrt(4) = 2
6219 std::cout << "NOTE: Errors multiplied by " << mathFit->GetScaleFactorError()
6220 << " to take into account artificially higher statistics (by factor of 4) due to same information "
6221 << "for all deltaPrimeSpecies (except for binning effects), if deltaPrimeRange sufficiently large!" << std::endl
6222 << std::endl;
6223 }
6224
6225 if (fitMethod < 2) {
6226 std::cout << "WARNING: Errors might be wrong! Especially, for the to-pi ratios there are no correlations taken into account!"
6227 << std::endl;
6228 }
6229
6230 delete gFractionElectronsData;
6231 delete fElectronFraction;
6232
6233 delete mathFit;
6234
6235 delete cFractions;
6236 delete cFractionComparisons;
6237 delete cYieldComparisons;
6238 delete cFractionsPions;
6239 delete cFractionsElectrons;
6240 delete cFractionsKaons;
6241 delete cFractionsProtons;
6242 delete cFractionsMuons;
6243 delete cYields;
6244 delete cYieldsPions;
6245 delete cYieldsKaons;
6246 delete cYieldsMuons;
6247 delete cYieldsProtons;
6248 delete cYieldsElectrons;
6249
6250 saveF->Close();
6251
6252 return 0;
6253}