]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGJE/macros/PID/PID.C
Undoing some unwanted method renames
[u/mrichter/AliRoot.git] / PWGJE / macros / PID / PID.C
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
30 enum processMode { kPMpT = 0, kPMz = 1, kPMxi = 2 };
31 enum muonTreatment { kNoMuons = 0, kMuonFracEqualElFrac = 1, kMuonFracOverElFracTunedOnMCStandardTrackCuts = 2,
32                      kMuonFracOverElFracTunedOnMCHybridTrackCuts = 3, kMuonFracOverElFracTunedOnMCHybridTrackCutsJets = 4,
33                      kMuonFracOverElFracTunedOnMCStandardTrackCutsPPb = 5,
34                      kNumHandlings = 6 };
35
36 const TString modeShortName[3] = { "Pt", "Z", "Xi" };
37 const TString modeLatexName[3] = { "P_{T}", "z", "#xi" };
38
39 const TString muonFractionHandlingShortName[kNumHandlings] =
40   { "noMuons", "muonsEqualElectrons", "muonToElTunedOnMCStandardTrackCuts", "muonToElTunedOnMCHybridTrackCuts",
41     "muonToElTunedOnMCHybridTrackCutsJets", "muonToElTunedOnMCStandardTrackCutsPPB" };
42
43 const Double_t epsilon = 1e-10;
44 const TString identifiedLabels[2] = { "Most Probable PID", "MC" };
45 Int_t isMC = 0;
46
47 TString minimisationStrategy = "MIGRAD"; // "MINIMIZE"
48 Bool_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,
52 Int_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!)
58 const Bool_t muonContamination = kFALSE;//TODO CAREFUL: fitMethod == 1 takes into account the muon contamination in the error calculation!!!
59
60 const Bool_t normaliseResults = kTRUE; // Works only for fitMethod == 2
61
62 const Bool_t enableShift = kFALSE;
63 const Int_t dataAxis = kPidDeltaPrime;//kPidDelta; kPidDeltaPrime
64
65 const Int_t numSimultaneousFits = 4;
66
67 // Upper and lower axis bounds (y-axis) of (data - fit) / data QA histos
68 const Double_t fitQAaxisLowBound = -0.5;
69 const Double_t fitQAaxisUpBound = 0.5;
70
71 Bool_t useDeltaPrime = (dataAxis == kPidDeltaPrime);
72
73 // Will be set later
74 Double_t muonFractionThresholdForFitting = -1.;
75 Double_t muonFractionThresholdBinForFitting = -1;
76   
77 Double_t electronFractionThresholdForFitting = -1.;
78 Double_t electronFractionThresholdBinForFitting = -1;
79
80
81 TF1 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
84 TF1* fElectronFraction = 0x0;
85 const Double_t lowFittingBoundElectronFraction = 3.0; 
86
87 TGraphErrors* gFractionElectronsData = 0x0;
88 Double_t lastPtForCallOfGetElectronFraction = -1;
89
90
91 //____________________________________________________________________________________________________________________
92 Double_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 //____________________________________________________________________________________________________________________
145 Double_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 //____________________________________________________________________________________________________________________
174 Double_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 //____________________________________________________________________________________________________________________
205 Double_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 //____________________________________________________________________________________________________________________
225 void 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 //____________________________________________________________________________________________________________________
261 void 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 //____________________________________________________________________________________________________________________
272 void 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 //____________________________________________________________________________________________________________________
284 Int_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 //____________________________________________________________________________________________________________________
296 Double_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 //____________________________________________________________________________________________________________________
323 void 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 //____________________________________________________________________________________________________________________
339 void 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 //____________________________________________________________________________________________________________________
355 void 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 //____________________________________________________________________________________________________________________
378 inline 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 //____________________________________________________________________________________________________________________
391 Double_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 //____________________________________________________________________________________________________________________
441 void 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 //____________________________________________________________________________________________________________________
465 Double_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 //____________________________________________________________________________________________________________________
526 inline Double_t multiGaussFitDeltaPi(const Double_t *xx, const Double_t *par)
527 {
528   return multiGaussFitForSimultaneousFitting(xx, par, 0);
529 }
530
531 //____________________________________________________________________________________________________________________
532 inline Double_t multiGaussFitDeltaKa(const Double_t *xx, const Double_t *par)
533 {
534   return multiGaussFitForSimultaneousFitting(xx, par, 1);
535 }
536
537 //____________________________________________________________________________________________________________________
538 inline Double_t multiGaussFitDeltaPr(const Double_t *xx, const Double_t *par)
539 {
540   return multiGaussFitForSimultaneousFitting(xx, par, 2);
541 }
542
543 //____________________________________________________________________________________________________________________
544 inline Double_t multiGaussFitDeltaEl(const Double_t *xx, const Double_t *par)
545 {
546   return multiGaussFitForSimultaneousFitting(xx, par, 3);
547 }
548
549
550 //____________________________________________________________________________________________________________________
551 Double_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 //____________________________________________________________________________________________________________________
602 Double_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 //____________________________________________________________________________________________________________________
671 inline Double_t errorOfFitHistosDeltaPi(const Double_t *xx, const Double_t *par)
672 {
673   return errorOfFitHistosForSimultaneousFitting(xx, par, 0);
674 }
675
676
677 //____________________________________________________________________________________________________________________
678 inline Double_t errorOfFitHistosDeltaKa(const Double_t *xx, const Double_t *par)
679 {
680   return errorOfFitHistosForSimultaneousFitting(xx, par, 1);
681 }
682
683
684 //____________________________________________________________________________________________________________________
685 inline Double_t errorOfFitHistosDeltaPr(const Double_t *xx, const Double_t *par)
686 {
687   return errorOfFitHistosForSimultaneousFitting(xx, par, 2);
688 }
689
690
691 //____________________________________________________________________________________________________________________
692 inline Double_t errorOfFitHistosDeltaEl(const Double_t *xx, const Double_t *par)
693 {
694   return errorOfFitHistosForSimultaneousFitting(xx, par, 3);
695 }
696
697
698 //____________________________________________________________________________________________________________________
699 Double_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 //____________________________________________________________________________________________________________________
756 inline Double_t saveDivide(Double_t numerator, Double_t denominator) 
757 {
758   return ((denominator != 0) ? numerator/denominator : 0 );
759 }
760
761
762 //____________________________________________________________________________________________________________________
763 Double_t getErrorOfPionIntegral(TMatrixDSym covMat)
764 {
765   return TMath::Sqrt(covMat(0, 0) + covMat(12, 12) + 2 * covMat(0, 12));
766 }
767
768
769 //____________________________________________________________________________________________________________________
770 Double_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 //____________________________________________________________________________________________________________________
783 Double_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 //____________________________________________________________________________________________________________________
797 Double_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 //____________________________________________________________________________________________________________________
812 Double_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 //____________________________________________________________________________________________________________________
826 Double_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 //____________________________________________________________________________________________________________________
837 Double_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 //____________________________________________________________________________________________________________________
863 TCanvas* 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 //____________________________________________________________________________________________________________________
916 TCanvas* 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 //____________________________________________________________________________________________________________________
972 Int_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 //____________________________________________________________________________________________________________________
1052 Int_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 //____________________________________________________________________________________________________________________
1136 Int_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 //____________________________________________________________________________________________________________________
1213 Double_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 //____________________________________________________________________________________________________________________
1307 Int_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 }