]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGPP/TPC/AliTPCcalibResidualPID.cxx
- ATO-57, ATO-71 calibResidual: Added tree output to study local track density effect...
[u/mrichter/AliRoot.git] / PWGPP / TPC / AliTPCcalibResidualPID.cxx
CommitLineData
88b71b9f 1/**************************************************************************
2* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3* *
4* Author: Yvonne Pachmayer <pachmay@physi.uni-heidelberg.de> *
5* Contributors are mentioned in the code where appropriate. *
6* *
7* Permission to use, copy, modify and distribute this software and its *
8* documentation strictly for non-commercial purposes is hereby granted *
9* without fee, provided that the above copyright notice appears in all *
10* copies and that both the copyright notice and this permission notice *
11* appear in the supporting documentation. The authors make no claims *
12* about the suitability of this software for any purpose. It is *
13* provided "as is" without express or implied warranty. *
14**************************************************************************/
15//
16// The task:
17// stores TPC PID quantities in a THnSparse
18// output can then be used for e.g. dEdx calibration
19//
20// Author:
21// Yvonne Pachmayer <pachmay@physi.uni-heidelberg.de>
22//
23
24
25#include "AliTPCcalibResidualPID.h"
26#include "TChain.h"
27#include "AliAnalysisManager.h"
28#include "AliESDEvent.h"
29#include "AliAODEvent.h"
30#include "AliMCEvent.h"
31#include "AliMCParticle.h"
32//#include "AliStack.h"
33#include "AliPID.h"
34#include "AliTPCcalibResidualPID.h"
35#include "AliESDtrack.h"
36#include "AliESDtrackCuts.h"
f310f95e 37#include "AliPIDResponse.h"
38#include "AliInputEventHandler.h"
88b71b9f 39#include "AliESDInputHandler.h"
40#include "AliESDv0KineCuts.h"
41#include "AliESDv0.h"
42#include "AliCentrality.h"
43#include "THnSparse.h"
44#include "TH2D.h"
45#include "TCanvas.h"
46#include "TGraphErrors.h"
47#include "TMultiGraph.h"
48#include "TAxis.h"
49#include "TFile.h"
50#include "TSpline.h"
51#include "TStyle.h"
52#include "AliTPCdEdxInfo.h"
53#include "TString.h"
54#include "TFitResult.h"
55#include "TH1F.h"
56#include "TLegend.h"
57#include "TVirtualFitter.h"
f310f95e 58#include "TTree.h"
88b71b9f 59
60using namespace std;
61
62ClassImp(AliTPCcalibResidualPID)
63
64Double_t AliTPCcalibResidualPID::fgCutGeo = 1.;
65Double_t AliTPCcalibResidualPID::fgCutNcr = 0.85;
66Double_t AliTPCcalibResidualPID::fgCutNcl = 0.7;
67
68//________________________________________________________________________
69AliTPCcalibResidualPID::AliTPCcalibResidualPID()
f310f95e 70 : AliAnalysisTaskSE(), fESD(0), fMC(0), fOutputContainer(0), fESDtrackCuts(0), fESDtrackCutsV0(0), fPIDResponse(0),
71 fNumEtaCorrReqErrorsIssued(0),
72 fNumMultCorrReqErrorsIssued(0),
88b71b9f 73 fUseTPCCutMIGeo(kFALSE),
74 fUseMCinfo(kTRUE),
75 fIsPbpOrpPb(kFALSE),
76 fZvtxCutEvent(9999.0),
77 fV0KineCuts(0x0),
f310f95e 78 fCutOnProdRadiusForV0el(kTRUE),
88b71b9f 79 fNumTagsStored(0),
80 fV0tags(0x0),
81 fV0motherIndex(0x0),
82 fV0motherPDG(0x0),
83 fProduceAllPadTypes(0),
84 fProduceGlobal(0),
85 fProduceShortPads(0),
86 fProduceMediumPads(0),
87 fProduceLongPads(0),
88 fProduceOroc(0),
89 fHistPidQA(0),
90 fHistPidQAshort(0),
91 fHistPidQAmedium(0),
92 fHistPidQAlong(0),
93 fHistPidQAoroc(0),
94 fProduceTPCSignalSparse(0),
95 fCorrectdEdxEtaDependence(0),
96 fCorrectdEdxMultiplicityDependence(0),
97 fThnspTpc(0),
f310f95e 98 fWriteAdditionalOutput(kFALSE),
88b71b9f 99 fQAList(0x0),
100 fhInvMassGamma(0x0),
101 fhInvMassK0s(0x0),
102 fhInvMassLambda(0x0),
103 fhInvMassAntiLambda(0x0),
104 fhArmenterosAll(0x0),
105 fhArmenterosGamma(0x0),
106 fhArmenterosK0s(0x0),
107 fhArmenterosLambda(0x0),
108 fhArmenterosAntiLambda(0x0),
109 fHistSharedClusQAV0Pi(0x0),
110 fHistSharedClusQAV0Pr(0x0),
f310f95e 111 fHistSharedClusQAV0El(0x0),
112 fTreeV0El(0x0),
113 fTreeV0Pi(0x0),
114 fTreeV0Pr(0x0),
115 fTree_dEdx_tr(0.),
116 fTree_dEdx_nb(0.),
117 fTree_dEdx_vs(0.),
118 fTree_dEdxExpected_tr(0.),
119 fTree_p_TPC_tr(0.),
120 fTree_p_TPC_nb(0.),
121 fTree_p_TPC_vs(0.),
122 fTree_BtimesChargeOverPt_tr(0.),
123 fTree_BtimesChargeOverPt_nb(0.),
124 fTree_BtimesChargeOverPt_vs(0.),
125 fTree_tanTheta_tr(0.),
126 fTree_tanTheta_nb(0.),
127 fTree_tanTheta_vs(0.),
128 fTree_distance_nb(0.),
129 fTree_distance_vs(0.)
88b71b9f 130{
131 // default Constructor
132 /* fast compilation test
133 gSystem->Load("libANALYSIS");
134 gSystem->Load("libANALYSISalice");
135 .L /lustre/alice/akalweit/train/trunk/util/statsQA/AliTPCcalibResidualPID.cxx++
136 */
137
138}
139
140
141//________________________________________________________________________
142AliTPCcalibResidualPID::AliTPCcalibResidualPID(const char *name)
f310f95e 143 : AliAnalysisTaskSE(name), fESD(0), fMC(0), fOutputContainer(0), fESDtrackCuts(0), fESDtrackCutsV0(0), fPIDResponse(0),
144 fNumEtaCorrReqErrorsIssued(0),
145 fNumMultCorrReqErrorsIssued(0),
88b71b9f 146 fUseTPCCutMIGeo(kFALSE),
147 fUseMCinfo(kTRUE),
148 fIsPbpOrpPb(kFALSE),
149 fZvtxCutEvent(9999.0),
150 fV0KineCuts(0x0),
f310f95e 151 fCutOnProdRadiusForV0el(kTRUE),
88b71b9f 152 fNumTagsStored(0),
153 fV0tags(0x0),
154 fV0motherIndex(0x0),
155 fV0motherPDG(0x0),
156 fProduceAllPadTypes(0),
157 fProduceGlobal(0),
158 fProduceShortPads(0),
159 fProduceMediumPads(0),
160 fProduceLongPads(0),
161 fProduceOroc(0),
162 fHistPidQA(0),
163 fHistPidQAshort(0),
164 fHistPidQAmedium(0),
165 fHistPidQAlong(0),
166 fHistPidQAoroc(0),
167 fProduceTPCSignalSparse(0),
168 fCorrectdEdxEtaDependence(0),
169 fCorrectdEdxMultiplicityDependence(0),
170 fThnspTpc(0),
f310f95e 171 fWriteAdditionalOutput(kFALSE),
88b71b9f 172 fQAList(0x0),
173 fhInvMassGamma(0x0),
174 fhInvMassK0s(0x0),
175 fhInvMassLambda(0x0),
176 fhInvMassAntiLambda(0x0),
177 fhArmenterosAll(0x0),
178 fhArmenterosGamma(0x0),
179 fhArmenterosK0s(0x0),
180 fhArmenterosLambda(0x0),
181 fhArmenterosAntiLambda(0x0),
182 fHistSharedClusQAV0Pi(0x0),
183 fHistSharedClusQAV0Pr(0x0),
f310f95e 184 fHistSharedClusQAV0El(0x0),
185 fTreeV0El(0x0),
186 fTreeV0Pi(0x0),
187 fTreeV0Pr(0x0),
188 fTree_dEdx_tr(0.),
189 fTree_dEdx_nb(0.),
190 fTree_dEdx_vs(0.),
191 fTree_dEdxExpected_tr(0.),
192 fTree_p_TPC_tr(0.),
193 fTree_p_TPC_nb(0.),
194 fTree_p_TPC_vs(0.),
195 fTree_BtimesChargeOverPt_tr(0.),
196 fTree_BtimesChargeOverPt_nb(0.),
197 fTree_BtimesChargeOverPt_vs(0.),
198 fTree_tanTheta_tr(0.),
199 fTree_tanTheta_nb(0.),
200 fTree_tanTheta_vs(0.),
201 fTree_distance_nb(0.),
202 fTree_distance_vs(0.)
88b71b9f 203{
204
205 //fESDtrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(kTRUE);
206 //fESDtrackCutsV0 = AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(kFALSE);
207
208 // Constructor
209 DefineInput(0, TChain::Class());
210 DefineOutput(1, TObjArray::Class());
211 DefineOutput(2, TObjArray::Class());
f310f95e 212 DefineOutput(3, TTree::Class());
213 DefineOutput(4, TTree::Class());
214 DefineOutput(5, TTree::Class());
88b71b9f 215
216}
217
218
219//_________________________________________________
220AliTPCcalibResidualPID::~AliTPCcalibResidualPID()
221{
222 delete fOutputContainer;
223 fOutputContainer = 0;
224
225 delete fQAList;
226 fQAList = 0;
227
f310f95e 228 /*
229 delete fTreeV0El;
230 fTreeV0El = 0;
231
232 delete fTreeV0Pi;
233 fTreeV0Pi = 0;
234
235 delete fTreeV0Pr;
236 fTreeV0Pr = 0;
237 */
238
88b71b9f 239 delete fESDtrackCuts;
240 fESDtrackCuts = 0;
241
242 delete fESDtrackCutsV0;
243 fESDtrackCutsV0 = 0;
244
245 delete fV0KineCuts;
246 fV0KineCuts = 0;
247
248 delete fV0tags;
249 fV0tags = 0;
250 fNumTagsStored = 0;
251
252 delete fV0motherIndex;
253 fV0motherIndex = 0;
254
255 delete fV0motherPDG;
256 fV0motherPDG = 0;
257}
258
259
260//________________________________________________________________________
261void AliTPCcalibResidualPID::UserCreateOutputObjects()
262{
f310f95e 263 AliInputEventHandler* inputHandler = dynamic_cast<AliInputEventHandler*>(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
264 if (!inputHandler)
265 printf("Inputhandler not available \n");
266 else
267 fPIDResponse = inputHandler->GetPIDResponse();
268
269 // THnSparse binning
270 const Int_t kNdim = 9;
271 //v0id, dEdx, TPCsigele, TPCsigpion, TOFbit, eta, TPCclus, centr, p
272 Int_t bins[kNdim] = { 4, 250, 200, 200, 8, 20, 50, 20, 100};
273 Double_t xmin[kNdim] = { 0.5, 30, -10., -10., -1.5, -1., 60., 0., 0.1};
274 Double_t xmax[kNdim] = { 4.5, 500., 10., 10., 6.5, 1., 160., 100, 4};
275 fThnspTpc= new THnSparseF("tpcsignals", "TPC signal;v0id;tpc signal;tpcsigele;tpcsigpion;tofbit;eta;tpcclus;centr;p (GeV/c)", kNdim, bins, xmin, xmax);
276 BinLogAxis(fThnspTpc, 8);
88b71b9f 277
f310f95e 278 //
279 // 0.ptot, 1.tpcSig, 2.particle ID, 3. assumed particle, 4. nSigmaTPC (4x), 5. nSigmaTOF (4x), 6. centrality
280 // Concerning 2 (particle ID):
281 // - in case of MC: Contains MC ID. Bin 1-4 (<=> Slot 0-3): el, pi, ka, pr
282 // - in case of data: Contains V0 particles + bin with all others: Bin 1-4 (<=> Slot 0-3): All non-V0s, V0-el, V0-pi, V0-pr
283 //
284
285 Int_t binsHistQA[7] = {135, 1980, 4, 5, 40, 10, 40};
286 Double_t xminHistQA[7] = {0.1, 20, -0.5, -0.5, -10, -5, 0.};
287 Double_t xmaxHistQA[7] = {50., 2000, 3.5, 4.5, 10, 5, 20000};
288 fHistPidQA = new THnSparseF("fHistPidQA","PID QA",7,binsHistQA,xminHistQA,xmaxHistQA);
289 BinLogAxis(fHistPidQA, 0);
88b71b9f 290
f310f95e 291 //
292 fHistPidQAshort = new THnSparseF("fHistPidQAshort" ,"PID QA -- short pads",7,binsHistQA,xminHistQA,xmaxHistQA);
293 fHistPidQAmedium = new THnSparseF("fHistPidQAmedium","PID QA -- med pads",7,binsHistQA,xminHistQA,xmaxHistQA);
294 fHistPidQAlong = new THnSparseF("fHistPidQAlong" ,"PID QA -- long pads",7,binsHistQA,xminHistQA,xmaxHistQA);
295 fHistPidQAoroc = new THnSparseF("fHistPidQAoroc" ,"PID QA -- oroc",7,binsHistQA,xminHistQA,xmaxHistQA);
296 BinLogAxis(fHistPidQAshort, 0);
297 BinLogAxis(fHistPidQAmedium, 0);
298 BinLogAxis(fHistPidQAlong, 0);
299 BinLogAxis(fHistPidQAoroc, 0);
300 //
301 fOutputContainer = new TObjArray(2);
302 fOutputContainer->SetName(GetName());
303 fOutputContainer->SetOwner();
304
305 if(fProduceTPCSignalSparse)fOutputContainer->Add(fThnspTpc);
306 if(fProduceGlobal)fOutputContainer->Add(fHistPidQA);
307 if(fProduceAllPadTypes || fProduceShortPads)fOutputContainer->Add(fHistPidQAshort);
308 if(fProduceAllPadTypes || fProduceMediumPads)fOutputContainer->Add(fHistPidQAmedium);
309 if(fProduceAllPadTypes || fProduceLongPads)fOutputContainer->Add(fHistPidQAlong);
310 if(fProduceAllPadTypes || fProduceOroc)fOutputContainer->Add(fHistPidQAoroc);
311
312 // V0 Kine cuts
313 fV0KineCuts = new AliESDv0KineCuts;
314 fV0KineCuts->SetGammaCutChi2NDF(5.);
315
316 if (fCutOnProdRadiusForV0el) {
88b71b9f 317 // Only accept V0el with prod. radius within 45 cm -> PID will by systematically biased for larger values!
318 Float_t gammaProdVertexRadiusCuts[2] = { 3.0, 45. };
319 fV0KineCuts->SetGammaCutVertexR(&gammaProdVertexRadiusCuts[0]);
f310f95e 320 }
321
322
323 if (fWriteAdditionalOutput) {
88b71b9f 324 fQAList = new TObjArray(4);
325 fQAList->SetName(GetName());
326 fQAList->SetOwner();
327
328 fhInvMassGamma = new TH1F("fhInvMassGamma", "Invariant Mass of gammas; m_{ee} (GeV/#it{c}^{2}); Entries", 200, 0., 0.2);
329 fhInvMassK0s = new TH1F("fhInvMassK0s", "Invariant Mass of K0s; m_{#pi#pi} (GeV/#it{c}^{2}); Entries;", 200, 0.45, 0.55);
330 fhInvMassLambda = new TH1F("fhInvMassLambda", "Invariant Mass of lambdas; m_{p#pi^{-}} (GeV/#it{c}^{2}); Entries", 200, 1.05, 1.15);
331 fhInvMassAntiLambda = new TH1F("fhInvMassAntiLambda", "Invariant Mass of anti-lambdas; m_{#pi^{+}#bar{p}} (GeV/#it{c}^{2}); Entries",
f310f95e 332 200, 1.05, 1.15);
88b71b9f 333
334 fQAList->Add(fhInvMassGamma);
335 fQAList->Add(fhInvMassK0s);
336 fQAList->Add(fhInvMassLambda);
337 fQAList->Add(fhInvMassAntiLambda);
338
339
340 fhArmenterosAll = new TH2F("fhArmenterosAll",
f310f95e 341 "Armenteros plot all V0s;#alpha = (#it{p}^{+}_{L}-#it{p}^{-}_{L})/(#it{p}^{+}_{L}+#it{p}^{-}_{L});#it{q}_{T} (GeV/#it{c})",
342 200, -1., 1., 200, 0., 0.4);
88b71b9f 343 fhArmenterosGamma = new TH2F("fhArmenterosGamma",
f310f95e 344 "Armenteros plot Gamma;#alpha = (#it{p}^{+}_{L}-#it{p}^{-}_{L})/(#it{p}^{+}_{L}+#it{p}^{-}_{L});#it{q}_{T} (GeV/#it{c})",
345 200, -1., 1., 200, 0., 0.4);
88b71b9f 346 fhArmenterosK0s = new TH2F("fhArmenterosK0s",
f310f95e 347 "Armenteros plot K0s;#alpha = (#it{p}^{+}_{L}-#it{p}^{-}_{L})/(#it{p}^{+}_{L}+#it{p}^{-}_{L});#it{q}_{T} (GeV/#it{c})",
348 200, -1., 1., 200, 0., 0.4);
88b71b9f 349 fhArmenterosLambda = new TH2F("fhArmenterosLambda",
f310f95e 350 "Armenteros plot lambda;#alpha = (#it{p}^{+}_{L}-#it{p}^{-}_{L})/(#it{p}^{+}_{L}+#it{p}^{-}_{L});#it{q}_{T} (GeV/#it{c})",
351 200, -1., 1., 200, 0., 0.4);
88b71b9f 352 fhArmenterosAntiLambda = new TH2F("fhArmenterosAntiLambda",
353 "Armenteros plot anti-lambda;#alpha = (#it{p}^{+}_{L}-#it{p}^{-}_{L})/(#it{p}^{+}_{L}+#it{p}^{-}_{L});#it{q}_{T} (GeV/#it{c})",
354 200, -1., 1., 200, 0., 0.4);
355
356 fQAList->Add(fhArmenterosAll);
357 fQAList->Add(fhArmenterosGamma);
358 fQAList->Add(fhArmenterosK0s);
359 fQAList->Add(fhArmenterosLambda);
360 fQAList->Add(fhArmenterosAntiLambda);
361
362
363 const Int_t dimQASharedClusters = 4;
364 const TString axisTitles[dimQASharedClusters] = { "#it{p}_{TPC} (GeV/#it{c})", "#it{#Delta'}", "#it{N}_{shared cl}", "Pad row"};
365 Int_t binsHistQASharedClusters[dimQASharedClusters] = { 100, 100, 160, 160};
366 Double_t xminHistQASharedClusters[dimQASharedClusters] = { 0.3, 0.5, 0, -1};
367 Double_t xmaxHistQASharedClusters[dimQASharedClusters] = { 20, 1.5, 160, 159};
368
369 fHistSharedClusQAV0Pi = new THnSparseF("fHistSharedClusQAV0Pi" ,"PID QA shared clusters - V0 pi", dimQASharedClusters,
f310f95e 370 binsHistQASharedClusters, xminHistQASharedClusters, xmaxHistQASharedClusters);
88b71b9f 371 BinLogAxis(fHistSharedClusQAV0Pi, 0);
372 for (Int_t i = 0; i < dimQASharedClusters; i++)
373 fHistSharedClusQAV0Pi->GetAxis(i)->SetTitle(axisTitles[i].Data());
374 fQAList->Add(fHistSharedClusQAV0Pi);
375
376 fHistSharedClusQAV0Pr = new THnSparseF("fHistSharedClusQAV0Pr" ,"PID QA shared clusters - V0 pr", dimQASharedClusters,
f310f95e 377 binsHistQASharedClusters, xminHistQASharedClusters, xmaxHistQASharedClusters);
88b71b9f 378 BinLogAxis(fHistSharedClusQAV0Pr, 0);
379 for (Int_t i = 0; i < dimQASharedClusters; i++)
380 fHistSharedClusQAV0Pi->GetAxis(i)->SetTitle(axisTitles[i].Data());
381 fQAList->Add(fHistSharedClusQAV0Pr);
f310f95e 382
88b71b9f 383 fHistSharedClusQAV0El = new THnSparseF("fHistSharedClusQAV0El" ,"PID QA shared clusters - V0 el", dimQASharedClusters,
f310f95e 384 binsHistQASharedClusters, xminHistQASharedClusters, xmaxHistQASharedClusters);
88b71b9f 385 BinLogAxis(fHistSharedClusQAV0El, 0);
386 for (Int_t i = 0; i < dimQASharedClusters; i++)
387 fHistSharedClusQAV0Pi->GetAxis(i)->SetTitle(axisTitles[i].Data());
388 fQAList->Add(fHistSharedClusQAV0El);
f310f95e 389
390 OpenFile(3);
391 fTreeV0El = new TTree("treeV0El", "V0 el together with info from closest neighbour");
392 fTreeV0El->Branch("dEdx_tr", &fTree_dEdx_tr);
393 fTreeV0El->Branch("dEdx_nb", &fTree_dEdx_nb);
394 fTreeV0El->Branch("dEdx_vs", &fTree_dEdx_vs);
395 fTreeV0El->Branch("dEdxExpected_tr", &fTree_dEdxExpected_tr);
396 fTreeV0El->Branch("p_TPC_tr", &fTree_p_TPC_tr);
397 fTreeV0El->Branch("p_TPC_nb", &fTree_p_TPC_nb);
398 fTreeV0El->Branch("p_TPC_vs", &fTree_p_TPC_vs);
399 fTreeV0El->Branch("BtimesChargeOverPt_tr", &fTree_BtimesChargeOverPt_tr);
400 fTreeV0El->Branch("BtimesChargeOverPt_nb", &fTree_BtimesChargeOverPt_nb);
401 fTreeV0El->Branch("BtimesChargeOverPt_vs", &fTree_BtimesChargeOverPt_vs);
402 fTreeV0El->Branch("tanTheta_tr", &fTree_tanTheta_tr);
403 fTreeV0El->Branch("tanTheta_nb", &fTree_tanTheta_nb);
404 fTreeV0El->Branch("tanTheta_vs", &fTree_tanTheta_vs);
405 fTreeV0El->Branch("distance_nb", &fTree_distance_nb);
406 fTreeV0El->Branch("distance_vs", &fTree_distance_vs);
407
408 OpenFile(4);
409 fTreeV0Pi = new TTree("treeV0Pi", "V0 pi together with info from closest neighbour");
410 fTreeV0Pi->Branch("dEdx_tr", &fTree_dEdx_tr);
411 fTreeV0Pi->Branch("dEdx_nb", &fTree_dEdx_nb);
412 fTreeV0Pi->Branch("dEdx_vs", &fTree_dEdx_vs);
413 fTreeV0Pi->Branch("dEdxExpected_tr", &fTree_dEdxExpected_tr);
414 fTreeV0Pi->Branch("p_TPC_tr", &fTree_p_TPC_tr);
415 fTreeV0Pi->Branch("p_TPC_nb", &fTree_p_TPC_nb);
416 fTreeV0Pi->Branch("p_TPC_vs", &fTree_p_TPC_vs);
417 fTreeV0Pi->Branch("BtimesChargeOverPt_tr", &fTree_BtimesChargeOverPt_tr);
418 fTreeV0Pi->Branch("BtimesChargeOverPt_nb", &fTree_BtimesChargeOverPt_nb);
419 fTreeV0Pi->Branch("BtimesChargeOverPt_vs", &fTree_BtimesChargeOverPt_vs);
420 fTreeV0Pi->Branch("tanTheta_tr", &fTree_tanTheta_tr);
421 fTreeV0Pi->Branch("tanTheta_nb", &fTree_tanTheta_nb);
422 fTreeV0Pi->Branch("tanTheta_vs", &fTree_tanTheta_vs);
423 fTreeV0Pi->Branch("distance_nb", &fTree_distance_nb);
424 fTreeV0Pi->Branch("distance_vs", &fTree_distance_vs);
425
426 OpenFile(5);
427 fTreeV0Pr = new TTree("treeV0Pr", "V0 pr together with info from closest neighbour");
428 fTreeV0Pr->Branch("dEdx_tr", &fTree_dEdx_tr);
429 fTreeV0Pr->Branch("dEdx_nb", &fTree_dEdx_nb);
430 fTreeV0Pr->Branch("dEdx_vs", &fTree_dEdx_vs);
431 fTreeV0Pr->Branch("dEdxExpected_tr", &fTree_dEdxExpected_tr);
432 fTreeV0Pr->Branch("p_TPC_tr", &fTree_p_TPC_tr);
433 fTreeV0Pr->Branch("p_TPC_nb", &fTree_p_TPC_nb);
434 fTreeV0Pr->Branch("p_TPC_vs", &fTree_p_TPC_vs);
435 fTreeV0Pr->Branch("BtimesChargeOverPt_tr", &fTree_BtimesChargeOverPt_tr);
436 fTreeV0Pr->Branch("BtimesChargeOverPt_nb", &fTree_BtimesChargeOverPt_nb);
437 fTreeV0Pr->Branch("BtimesChargeOverPt_vs", &fTree_BtimesChargeOverPt_vs);
438 fTreeV0Pr->Branch("tanTheta_tr", &fTree_tanTheta_tr);
439 fTreeV0Pr->Branch("tanTheta_nb", &fTree_tanTheta_nb);
440 fTreeV0Pr->Branch("tanTheta_vs", &fTree_tanTheta_vs);
441 fTreeV0Pr->Branch("distance_nb", &fTree_distance_nb);
442 fTreeV0Pr->Branch("distance_vs", &fTree_distance_vs);
443 }
444
445 PostData(1,fOutputContainer);
446 if (fWriteAdditionalOutput) {
88b71b9f 447 PostData(2,fQAList);
f310f95e 448 PostData(3,fTreeV0El);
449 PostData(4,fTreeV0Pi);
450 PostData(5,fTreeV0Pr);
451 }
88b71b9f 452}
453
454
455//_____________________________________________________________________________
456void AliTPCcalibResidualPID::UserExec(Option_t *)
457{
458 //calls the Process function
459 AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
460
461 if (!esdH) {
462 printf("ERROR: Could not get ESDInputHandler \n");
463 }
464 else fESD = esdH->GetEvent();
465
466 // If MC, forward MCevent
467 fMC = dynamic_cast<AliMCEvent*>(MCEvent());
468 //
469 Process(fESD, fMC);
470 //
471 PostData(1,fOutputContainer);
f310f95e 472 if (fWriteAdditionalOutput) {
473 PostData(2,fQAList);
474 PostData(3,fTreeV0El);
475 PostData(4,fTreeV0Pi);
476 PostData(5,fTreeV0Pr);
477 }
88b71b9f 478}
479
480
481
482//________________________________________________________________________
483void AliTPCcalibResidualPID::Process(AliESDEvent *const esdEvent, AliMCEvent *const mcEvent)
484{
485
486 //called for each event
487 if (!esdEvent) {
488 Printf("ERROR: esdEvent not available");
489 return;
490 }
491
f310f95e 492 if (!fPIDResponse || !fV0KineCuts) {
493 Printf("ERROR: No PIDresponse and/or v0KineCuts!");
88b71b9f 494 return;
f310f95e 495 }
88b71b9f 496
497 Float_t centralityFper=99;
498
499 AliCentrality *esdCentrality = esdEvent->GetCentrality();
500 centralityFper = esdCentrality->GetCentralityPercentile("V0M");
501
502 if (!GetVertexIsOk(esdEvent))
503 return;
504
505 const AliESDVertex* fESDvertex = esdEvent->GetPrimaryVertexTracks();
506 if (!fESDvertex)
507 return;
508
509 Int_t ncontr = fESDvertex->GetNContributors();
510
511 if (ncontr <= 0)
512 return;
513
514 // Fill V0 arrays with V0s
515 FillV0PIDlist(esdEvent);
516
517 // Array with flags wheter QA for this V0 was already done or not
518 const Int_t numV0s = esdEvent->GetNumberOfV0s();
519 Bool_t v0QAadded[numV0s];
520 for (Int_t i = 0; i < numV0s; i++)
521 v0QAadded[i] = kFALSE;
522
523 Int_t nTotTracks = esdEvent->GetNumberOfTracks();
12f73ffa 524 const Int_t nTotESDTracks = esdEvent->GetNumberOfESDTracks();
525
f310f95e 526 const Double_t magField = esdEvent->GetMagneticField();
527
528 Bool_t etaCorrAvail = fPIDResponse->UseTPCEtaCorrection();
529 Bool_t multCorrAvail = fPIDResponse->UseTPCMultiplicityCorrection();
530
88b71b9f 531 for (Int_t iTracks = 0; iTracks < nTotTracks; iTracks++){//begin track loop
532 AliESDtrack *trackESD = esdEvent->GetTrack(iTracks);
533 if(!trackESD) {
534 Printf("ERROR: Could not receive track %d (esd loop)", iTracks);
535 continue;
536 }
537 if((TMath::Abs(trackESD->Eta())) > 0.9)
538 continue;
539
540 // Do not distinguish positively and negatively charged V0's
541 Char_t v0tagAllCharges = TMath::Abs(GetV0tag(iTracks));
542 if (v0tagAllCharges == -99) {
543 AliError(Form("Problem with V0 tag list (requested V0 track for track %d from %d (list status %d))!", iTracks, esdEvent->GetNumberOfTracks(),
544 fV0tags != 0x0));
545 continue;
546 }
547
548 Bool_t isV0el = v0tagAllCharges == 14;
549 Bool_t isV0pi = v0tagAllCharges == 15;
550 Bool_t isV0pr = v0tagAllCharges == 16;
551 Bool_t isV0 = isV0el || isV0pi || isV0pr;
552
553 if (mcEvent && fUseMCinfo) {
554 // For MC, do not look for V0s, i.e. demand the non-V0 track cuts
555 if (fESDtrackCuts && !fESDtrackCuts->AcceptTrack(trackESD)) continue;
556
557 if (fUseTPCCutMIGeo) {
558 // If cut on geometry is active, don't cut on number of clusters, since such a cut is already included.
559 if (!TPCCutMIGeo(trackESD, esdEvent))
560 continue;
561 }
562 else {
563 // If cut on geometry is not active, always cut on num clusters
564 if (trackESD->GetTPCsignalN() < 60)
565 continue;
566 }
567 }
568 else {
569 // For data, take V0 AND non-V0 with separate cuts
570 //if (!isV0 && fESDtrackCuts && !fESDtrackCuts->AcceptTrack(trackESD)) continue;
571 if (isV0) {
572 if (fESDtrackCutsV0 && !fESDtrackCutsV0->AcceptTrack(trackESD))
573 continue;
574 }
575 else {
576 if (fESDtrackCuts && !fESDtrackCuts->AcceptTrack(trackESD))
577 continue;
578 }
579
580 if (fUseTPCCutMIGeo) {
581 // If cut on geometry is active, don't cut on number of clusters, since such a cut is already included.
582 if (!isV0) {
583 if (!TPCCutMIGeo(trackESD, esdEvent))
584 continue;
585 }
586 else {
587 // One should not cut on geometry for V0's since they have different topology. (Loosely) cut on num of clusters instead.
588 if (trackESD->GetTPCsignalN() < 60)
589 continue;
590 }
591 }
592 else {
593 // If cut on geometry is not active, always cut on num clusters
594 if (trackESD->GetTPCsignalN() < 60)
595 continue;
596 }
597 }
598
599 const AliExternalTrackParam *paramIn = trackESD->GetInnerParam();
600 Float_t precin=-1;
601 if(paramIn) {
602 precin=paramIn->GetP();
603 } else {
f310f95e 604 printf("Inner param not found for track %d - skipping!\n", iTracks);
88b71b9f 605 continue;
606 }
607 Int_t precdefault=CompareFloat(precin,-1);
608 if(precdefault==1) continue; // momentum cut
609 //
610
611 AliMCParticle* mcTrack = 0x0;
612 Int_t particleID = -1;
613 Int_t v0id = 0;
614
615 if (mcEvent && fUseMCinfo) {
616 // MC - particle ID = MC ID
617 Int_t label = trackESD->GetLabel();
618
619 if (label < 0)
620 continue; // If MC is available, reject tracks with negative ESD label
621
622 mcTrack = dynamic_cast<AliMCParticle*>(mcEvent->GetTrack(TMath::Abs(label)));
623 if (!mcTrack) {
624 Printf("ERROR: Could not receive mcTrack with label %d for track %d", label, iTracks);
625 continue;
626 }
627
628 /*// Only accept MC primaries
629 if (!mcEvent->Stack()->IsPhysicalPrimary(TMath::Abs(label))) {
630 continue;
631 }*/
632
633 Int_t pdgAbs = TMath::Abs(mcTrack->PdgCode());
634
635 if (pdgAbs == 11) { // electron
636 particleID = 0;
637 }
638 else if (pdgAbs == 211) { // pion
639 particleID = 1;
640 }
641 else if (pdgAbs == 321) { // kaon
642 particleID = 2;
643 }
644 else if (pdgAbs == 2212) { // proton
645 particleID = 3;
646 }
647 else
648 continue; // Reject all other particles
649 }
650 else {
651 // Data - particle ID = V0 ID (if V0)
652 if (isV0pi) { // pion
653 particleID = 2;
654 v0id = 2;
655 }
656 else if (isV0el) { // electron
657 particleID = 1;
658 v0id = 1;
659 }
660 else if (isV0pr) { // proton
661 particleID = 3;
662 v0id = 3;
663 }
664 else { // No V0-ID available (species must be determined via TPC, TOF, ...)
665 particleID = 0;
666 }
667 }
668
669
670 Float_t tpcsignal=trackESD->GetTPCsignal();
671 Int_t tofbit=-1;
672 Int_t iTOFpid=0;
673 Int_t ikTIME=0;
674 Double_t tpcnsigmaele=-10;
675 Double_t tpcnsigmapion=-10;
676 //
677 if ((trackESD->GetStatus() & AliESDtrack::kTOFpid)) iTOFpid = 1;
678 if ((trackESD->GetStatus() & AliESDtrack::kTIME)) ikTIME = 1;
f310f95e 679 Float_t time0 = fPIDResponse->GetTOFResponse().GetTimeZero();
88b71b9f 680 //
681 if((iTOFpid==1) &&(ikTIME==1)){
f310f95e 682 Double_t tofnsigmaele= fPIDResponse->NumberOfSigmasTOF(trackESD,AliPID::kElectron, time0);
683 Double_t tofnsigmapion=fPIDResponse->NumberOfSigmasTOF(trackESD,AliPID::kPion, time0);
88b71b9f 684 if (TMath::Abs(tofnsigmapion)<3) tofbit = 1;
685 if (TMath::Abs(tofnsigmaele)<3) tofbit = 0;
f310f95e 686 tpcnsigmaele=fPIDResponse->NumberOfSigmasTPC(trackESD,AliPID::kElectron);
687 tpcnsigmapion=fPIDResponse->NumberOfSigmasTPC(trackESD,AliPID::kPion);
88b71b9f 688 }
689 //
690 Int_t tpcnclusN=trackESD->GetTPCsignalN();
691 Double_t eta=trackESD->Eta();
692
693 //
694 if(fProduceTPCSignalSparse){
695 Double_t contentSignal[9];
696 contentSignal[0]=v0id;
697 contentSignal[1]=tpcsignal;
698 contentSignal[2]=tpcnsigmaele;
699 contentSignal[3]=tpcnsigmapion;
700 contentSignal[4]=tofbit;
701 contentSignal[5]=eta;
702 contentSignal[6]=tpcnclusN;
703 contentSignal[7]=centralityFper;
704 contentSignal[8]=precin;
705 //
706 if (fThnspTpc->GetEntries() < 1e6) fThnspTpc->Fill(contentSignal);
707 }//should it be created or not
708
709
710
711 //
712 // 2nd THnSparse
713 //
f310f95e 714 Double_t tpcQA[5] = {fPIDResponse->NumberOfSigmasTPC(trackESD, AliPID::kElectron),
715 fPIDResponse->NumberOfSigmasTPC(trackESD, AliPID::kPion),
716 fPIDResponse->NumberOfSigmasTPC(trackESD, AliPID::kKaon),
717 fPIDResponse->NumberOfSigmasTPC(trackESD, AliPID::kProton),
88b71b9f 718 0};
f310f95e 719 Double_t tofQA[5] = {fPIDResponse->NumberOfSigmasTOF(trackESD, AliPID::kElectron, time0),
720 fPIDResponse->NumberOfSigmasTOF(trackESD, AliPID::kPion, time0),
721 fPIDResponse->NumberOfSigmasTOF(trackESD, AliPID::kKaon, time0),
722 fPIDResponse->NumberOfSigmasTOF(trackESD, AliPID::kProton, time0),
88b71b9f 723 0 };
724
725 // id 5 is just again Kaons in restricted eta range
726 tpcQA[4] = tpcQA[2];
727 tofQA[4] = tofQA[2];
728
729 //
730 // dE/dx in different pad regions
731 //
732 AliTPCdEdxInfo * infoTpcPid = trackESD->GetTPCdEdxInfo();
733 Double32_t signal[4]; Char_t ncl[3]; Char_t nrows[3];
734 if (infoTpcPid) {
735 infoTpcPid->GetTPCSignalRegionInfo(signal, ncl, nrows);
736 } else {
737 for(Int_t iarr = 0; iarr < 3; iarr++) {
738 signal[iarr] = 0;
739 ncl[iarr] = 0;
740 nrows[iarr] = 0;
741 }
742 signal[3] = 0;
743 }
744 //
745 UInt_t status = trackESD->GetStatus();
746 Bool_t hasTOFout = status&AliESDtrack::kTOFout;
747 Bool_t hasTOFtime = status&AliESDtrack::kTIME;
748 Bool_t hasTOF = kFALSE;
749 if (hasTOFout && hasTOFtime) hasTOF = kTRUE;
750 Float_t length = trackESD->GetIntegratedLength();
751 // Length check only for primaries!
752 if (length < 350 && !isV0) hasTOF = kFALSE;
753 //
754
755 if (!hasTOF) {
756 // Make sure that number of sigmas is large in this case, so that the track will be rejected if a TOF cut is applied
757 for (Int_t i = 0; i < 5; i++) {
758 tofQA[i] = 999;
759 }
760 }
761
762
763 Double_t processedTPCsignal[5] = { tpcsignal, tpcsignal, tpcsignal, tpcsignal, tpcsignal };
764
f310f95e 765 if (fCorrectdEdxEtaDependence && fNumEtaCorrReqErrorsIssued < 23 && !etaCorrAvail) {
766 AliError("TPC eta correction requested, but was not activated in PID response (most likely not available)!");
767 fNumEtaCorrReqErrorsIssued++;
768 if (fNumEtaCorrReqErrorsIssued == 23)
769 AliError("Ignoring this error from now on!");
770 }
88b71b9f 771
f310f95e 772 if (fCorrectdEdxMultiplicityDependence && fNumMultCorrReqErrorsIssued < 23 && !multCorrAvail) {
773 AliError("TPC multiplicity correction requested, but was not activated in PID response (most likely not available)!");
774 fNumMultCorrReqErrorsIssued++;
775 if (fNumMultCorrReqErrorsIssued == 23)
776 AliError("Ignoring this error from now on!");
88b71b9f 777 }
f310f95e 778
779 if (fCorrectdEdxEtaDependence && etaCorrAvail && fCorrectdEdxMultiplicityDependence && multCorrAvail) {
780 processedTPCsignal[0] = fPIDResponse->GetTPCResponse().GetEtaAndMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kElectron,
781 AliTPCPIDResponse::kdEdxDefault);
782 processedTPCsignal[1] = fPIDResponse->GetTPCResponse().GetEtaAndMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kPion,
783 AliTPCPIDResponse::kdEdxDefault);
784 processedTPCsignal[2] = fPIDResponse->GetTPCResponse().GetEtaAndMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kKaon,
785 AliTPCPIDResponse::kdEdxDefault);
786 processedTPCsignal[3] = fPIDResponse->GetTPCResponse().GetEtaAndMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kProton,
787 AliTPCPIDResponse::kdEdxDefault);
788 }
789 else if (fCorrectdEdxEtaDependence && etaCorrAvail) {
790 processedTPCsignal[0] = fPIDResponse->GetTPCResponse().GetEtaCorrectedTrackdEdx(trackESD, AliPID::kElectron,
791 AliTPCPIDResponse::kdEdxDefault);
792 processedTPCsignal[1] = fPIDResponse->GetTPCResponse().GetEtaCorrectedTrackdEdx(trackESD, AliPID::kPion,
793 AliTPCPIDResponse::kdEdxDefault);
794 processedTPCsignal[2] = fPIDResponse->GetTPCResponse().GetEtaCorrectedTrackdEdx(trackESD, AliPID::kKaon,
795 AliTPCPIDResponse::kdEdxDefault);
796 processedTPCsignal[3] = fPIDResponse->GetTPCResponse().GetEtaCorrectedTrackdEdx(trackESD, AliPID::kProton,
797 AliTPCPIDResponse::kdEdxDefault);
88b71b9f 798 }
f310f95e 799 else if (fCorrectdEdxMultiplicityDependence && multCorrAvail) {
800 processedTPCsignal[0] = fPIDResponse->GetTPCResponse().GetMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kElectron,
801 AliTPCPIDResponse::kdEdxDefault);
802 processedTPCsignal[1] = fPIDResponse->GetTPCResponse().GetMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kPion,
803 AliTPCPIDResponse::kdEdxDefault);
804 processedTPCsignal[2] = fPIDResponse->GetTPCResponse().GetMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kKaon,
805 AliTPCPIDResponse::kdEdxDefault);
806 processedTPCsignal[3] = fPIDResponse->GetTPCResponse().GetMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kProton,
807 AliTPCPIDResponse::kdEdxDefault);
88b71b9f 808 }
809
810 // id 5 is just again Kaons in restricted eta range
811 processedTPCsignal[4] = processedTPCsignal[2];
812
813 for(Int_t iPart = 0; iPart < 5; iPart++) {
814 // Only accept "Kaons" within |eta| < 0.2 for index 4 in case of data (no contamination in case of MC, so this index is not used)
815 if (iPart == 4 && ((mcEvent && fUseMCinfo) || abs(trackESD->Eta()) > 0.2))
816 continue;
817
0e60aeb1 818 Double_t vecHistQA[7] = {precin, processedTPCsignal[iPart], (Double_t)particleID, (Double_t)iPart, tpcQA[iPart], tofQA[iPart],
12f73ffa 819 (Double_t)nTotESDTracks};
88b71b9f 820 if (fProduceGlobal) fHistPidQA->Fill(vecHistQA);
821 vecHistQA[1] = signal[0]; vecHistQA[4] = ncl[0];
822 if ((fProduceAllPadTypes || fProduceShortPads)) fHistPidQAshort->Fill(vecHistQA);
823 //
824 vecHistQA[1] = signal[1]; vecHistQA[4] = ncl[1];
825 if ((fProduceAllPadTypes || fProduceMediumPads)) fHistPidQAmedium->Fill(vecHistQA);
826 //
827 vecHistQA[1] = signal[2]; vecHistQA[4] = ncl[2];
828 if ((fProduceAllPadTypes || fProduceLongPads)) fHistPidQAlong->Fill(vecHistQA);
829 //
830 vecHistQA[1] = signal[3]; vecHistQA[4] = nrows[1] + nrows[2];
831 if ((fProduceAllPadTypes || fProduceOroc)) fHistPidQAoroc->Fill(vecHistQA);
832 }
833
f310f95e 834 if (fWriteAdditionalOutput && isV0) {
835
836 // Find the closest neighbour and fill the information into the trees.
837 fTree_p_TPC_tr = precin;
838 fTree_dEdx_tr = tpcsignal;
839 fTree_BtimesChargeOverPt_tr = TMath::Abs(magField) * trackESD->GetSigned1Pt();
840 fTree_tanTheta_tr = trackESD->GetInnerParam()->GetTgl();
841
842 Int_t closestNeighbourIndex = -1;
843 const Double_t tpcInnerRadius = 85.;
844 const Int_t parIndexGlobalPhi = 8;
845 const Double_t z_tr = trackESD->GetInnerParam()->GetZ();
846 const Double_t phi_tr = trackESD->GetInnerParam()->GetParameterAtRadius(tpcInnerRadius, magField, parIndexGlobalPhi);
847
848 const Double_t distanceCut = 12.; // Cut on distance between track to closest neighbour
849
850 Double_t z_nb = 9999;
851 Double_t phi_nb = 9999;
852 Double_t delta_z = 9999;
853 Double_t delta_phi = 9999;
854
855 fTree_distance_nb = -9999;
856
857 for (Int_t jTracks = 0; jTracks < nTotTracks; jTracks++) {
858 if (iTracks == jTracks)
859 continue; // Exclude track we are looking at right now from neighbour list
860
861 AliESDtrack *track_nb= esdEvent->GetTrack(jTracks);
862 if(!track_nb)
863 continue;
864
865 const AliExternalTrackParam *paramIn_nb = track_nb->GetInnerParam();
866 if (!paramIn_nb)
867 continue;
868
869 z_nb = paramIn_nb->GetZ();
870 delta_z = TMath::Abs(z_nb - z_tr);
871
872 if (delta_z >= distanceCut)
873 continue;
874
875 phi_nb = paramIn_nb->GetParameterAtRadius(tpcInnerRadius, magField, parIndexGlobalPhi);
876 delta_phi = TMath::Abs(phi_nb - phi_tr);
877
878 const Double_t delta_r_phi = tpcInnerRadius * delta_phi;
879
880 if (delta_r_phi >= distanceCut)
881 continue;
882
883
884 const Double_t distance = TMath::Sqrt(delta_z * delta_z + delta_r_phi * delta_r_phi);
885
886 if (distance >= distanceCut)
887 continue;
888
889 if (closestNeighbourIndex < 0 || distance < fTree_distance_nb) {
890 fTree_distance_nb = distance;
891 closestNeighbourIndex = jTracks;
892 }
893 }
894
895 if (closestNeighbourIndex >= 0 && closestNeighbourIndex < nTotTracks) {
896 AliESDtrack *track_nb= esdEvent->GetTrack(closestNeighbourIndex);
897 fTree_dEdx_nb = track_nb->GetTPCsignal();
898 fTree_p_TPC_nb = track_nb->GetInnerParam()->GetP();
899 fTree_BtimesChargeOverPt_nb = TMath::Abs(magField) * track_nb->GetSigned1Pt();
900 fTree_tanTheta_nb = track_nb->GetInnerParam()->GetTgl();
901 }
902 else {
903 // No neighbour in this range -> nevertheless store the track, but set neighbour values to invalid
904 fTree_dEdx_nb = -999.;
905 fTree_p_TPC_nb = -999.;
906 fTree_BtimesChargeOverPt_nb = -999.;
907 fTree_tanTheta_nb = -999.;
908 fTree_distance_nb = -999.;
909 }
910
911
912 // Find the other V0 daughter and store its values
913 const Int_t motherIndex = GetV0motherIndex(iTracks);
914 AliESDv0* v0Mother = (AliESDv0*)esdEvent->GetV0(motherIndex);
915 if (!v0Mother) {
916 printf("Error: Track tagged as V0 daughter, but V0 mother not found!\n");
917 continue;
918 }
919
920 const Int_t iTrackP = v0Mother->GetPindex(); // positive track
921 const Int_t iTrackN = v0Mother->GetNindex(); // negative track_nb
922
923 Int_t iTrackV0sister = -1;
924 if (iTrackP == iTracks)
925 iTrackV0sister = iTrackN;
926 else if (iTrackN == iTracks)
927 iTrackV0sister = iTrackP;
928 else {
929 printf("Error: V0 sister relations are wrong!\n");
930 continue;
931 }
932
933 fTree_dEdx_vs = -999.;
934 fTree_p_TPC_vs = -999.;
935 fTree_BtimesChargeOverPt_vs = -999.;
936 fTree_tanTheta_vs = -999.;
937 fTree_distance_vs = -999.;
938
939 AliESDtrack *track_vs = esdEvent->GetTrack(iTrackV0sister);
940 if (track_vs) {
941 const AliExternalTrackParam *paramIn_vs = track_vs->GetInnerParam();
942 if (paramIn_vs) {
943 fTree_dEdx_vs = track_vs->GetTPCsignal();
944 fTree_p_TPC_vs = paramIn_vs->GetP();
945 fTree_BtimesChargeOverPt_vs = TMath::Abs(magField) * track_vs->GetSigned1Pt();
946 fTree_tanTheta_vs = paramIn_vs->GetTgl();
947
948 // Calculate distance
949 const Double_t z_vs = paramIn_vs->GetZ();
950 const Double_t delta_z_vs = TMath::Abs(z_vs - z_tr);
951
952 const Double_t phi_vs = paramIn_vs->GetParameterAtRadius(tpcInnerRadius, magField, parIndexGlobalPhi);
953 const Double_t delta_phi_vs = TMath::Abs(phi_vs - phi_tr);
954
955 const Double_t delta_r_phi_vs = tpcInnerRadius * delta_phi_vs;
956
957 fTree_distance_vs = TMath::Sqrt(delta_z_vs * delta_z_vs + delta_r_phi_vs * delta_r_phi_vs);
958 }
959 }
960
961 if (isV0el) {
962 fTree_dEdxExpected_tr = fPIDResponse->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault,
963 fPIDResponse->UseTPCEtaCorrection(),
964 fPIDResponse->UseTPCMultiplicityCorrection());
965 if (fTree_dEdxExpected_tr > 0)
966 fTreeV0El->Fill();
967 }
968 else if (isV0pi) {
969 fTree_dEdxExpected_tr = fPIDResponse->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault,
970 fPIDResponse->UseTPCEtaCorrection(),
971 fPIDResponse->UseTPCMultiplicityCorrection());
972 if (fTree_dEdxExpected_tr > 0)
973 fTreeV0Pi->Fill();
974 }
975 else if (isV0pr) {
976 fTree_dEdxExpected_tr = fPIDResponse->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault,
977 fPIDResponse->UseTPCEtaCorrection(),
978 fPIDResponse->UseTPCMultiplicityCorrection());
979 if (fTree_dEdxExpected_tr > 0)
980 fTreeV0Pr->Fill();
981 }
982
88b71b9f 983 // Fill QA hists for shared clusters dE/dx
0e60aeb1 984 Double_t vecHistQA[4] = { precin, -1., (Double_t)trackESD->GetTPCSharedMap().CountBits(), -1. };
88b71b9f 985 THnSparse* currHist = fHistSharedClusQAV0Pi;
986
987 if (isV0pi) {
f310f95e 988 Double_t expectedDeDx = fPIDResponse->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault,
989 fPIDResponse->UseTPCEtaCorrection(),
990 fPIDResponse->UseTPCMultiplicityCorrection());
88b71b9f 991 if (expectedDeDx > 0 ) {
992 vecHistQA[1] = tpcsignal / expectedDeDx;
993 currHist = fHistSharedClusQAV0Pi;
994 }
995 }
996 else if (isV0pr) {
f310f95e 997 Double_t expectedDeDx = fPIDResponse->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault,
998 fPIDResponse->UseTPCEtaCorrection(),
999 fPIDResponse->UseTPCMultiplicityCorrection());
88b71b9f 1000 if (expectedDeDx > 0 ) {
1001 vecHistQA[1] = tpcsignal / expectedDeDx;
1002 currHist = fHistSharedClusQAV0Pr;
1003 }
1004 }
1005 else if (isV0el) {
f310f95e 1006 Double_t expectedDeDx = fPIDResponse->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault,
1007 fPIDResponse->UseTPCEtaCorrection(),
1008 fPIDResponse->UseTPCMultiplicityCorrection());
88b71b9f 1009 if (expectedDeDx > 0 ) {
1010 vecHistQA[1] = tpcsignal / expectedDeDx;
1011 currHist = fHistSharedClusQAV0El;
1012 }
1013 }
1014
1015 Int_t iRowInd = -1;
1016 // iRowInd == -1 for "all rows w/o multiple counting"
1017 currHist->Fill(vecHistQA);
1018
1019 // Fill hist for every pad row with shared cluster
1020 for (iRowInd = 0; iRowInd < 159; iRowInd++) {
1021 if (trackESD->GetTPCSharedMap().TestBitNumber(iRowInd)) {
1022 vecHistQA[3] = iRowInd;
1023 currHist->Fill(vecHistQA);
1024 }
1025 }
1026
1027
1028
1029 // Check, whether the QA for this V0 mother was already filled into the histograms (is the case if the other daughter has already
1030 // been processed). If not, set flag to kTRUE and fill the QA.
1031 const Int_t iV0 = GetV0motherIndex(iTracks);
1032 if (!v0QAadded[iV0]) {
1033 v0QAadded[iV0] = kTRUE;
1034
1035 AliESDv0* esdV0 = (AliESDv0*)esdEvent->GetV0(iV0);
1036
1037 if (!esdV0) {
1038 printf("Error: V0 tagged, but does not exist!\n");
88b71b9f 1039 }
f310f95e 1040 else {
1041 Float_t armVar[2] = {0.0,0.0};
1042 fV0KineCuts->Armenteros(esdV0, armVar);
1043
1044 const Int_t motherPDG = GetV0motherPDG(iTracks);
1045
1046 // Mother and daughter match the requirements, otherwise it wouldn't be tagged as a V0. Now just fill the QA histos.
1047 fhArmenterosAll->Fill(armVar[0], armVar[1]);
1048 //if (esdV0->TestBit(BIT(14))) {
1049 if (TMath::Abs(motherPDG) == 22) {
1050 fhInvMassGamma->Fill(esdV0->GetEffMass(AliPID::kElectron, AliPID::kElectron));
1051 fhArmenterosGamma->Fill(armVar[0], armVar[1]);
1052 }
1053 else if (TMath::Abs(motherPDG) == 310) {
1054 //else if (esdV0->TestBit(BIT(15))) {
1055 fhInvMassK0s->Fill(esdV0->GetEffMass(AliPID::kPion, AliPID::kPion));
1056 fhArmenterosK0s->Fill(armVar[0], armVar[1]);
1057 }
1058 else if (motherPDG == 3122) {
1059 //else if (esdV0->TestBit(BIT(16))) {
1060 fhInvMassLambda->Fill(esdV0->GetEffMass(AliPID::kProton, AliPID::kPion));
1061 fhArmenterosLambda->Fill(armVar[0], armVar[1]);
1062 }
1063 else if (motherPDG == -3122) {
1064 //else if (esdV0->TestBit(BIT(17))) {
1065 fhInvMassAntiLambda->Fill(esdV0->GetEffMass(AliPID::kPion, AliPID::kProton));
1066 fhArmenterosAntiLambda->Fill(armVar[0], armVar[1]);
1067 }
88b71b9f 1068 }
1069 }
1070 }
1071 } //end track loop
1072
1073
1074 // Clear the V0 PID arrays
1075 ClearV0PIDlist();
1076}
1077
1078
1079//________________________________________________________________________
1080Int_t AliTPCcalibResidualPID::CompareFloat(Float_t f1, Float_t f2) const
1081{
1082 //compares if the Float_t f1 is equal with f2 and returns 1 if true and 0 if false
1083 Float_t precision = 0.00001;
1084 if (((f1 - precision) < f2) &&
1085 ((f1 + precision) > f2))
1086 {
1087 return 1;
1088 }
1089 else
1090 {
1091 return 0;
1092 }
1093}
1094
1095
1096//________________________________________________________________________
1097void AliTPCcalibResidualPID::Terminate(const Option_t *)
1098{
1099
1100
1101}
1102
1103
1104
1105//________________________________________________________________________
1106void AliTPCcalibResidualPID::BinLogAxis(const THnSparseF *h, Int_t axisNumber) {
1107 //
1108 // Method for the correct logarithmic binning of histograms
1109 //
1110 TAxis *axis = h->GetAxis(axisNumber);
1111 int bins = axis->GetNbins();
1112
1113 Double_t from = axis->GetXmin();
1114 Double_t to = axis->GetXmax();
1115 Double_t *newBins = new Double_t[bins + 1];
1116
1117 newBins[0] = from;
1118 Double_t factor = pow(to/from, 1./bins);
1119
1120 for (int i = 1; i <= bins; i++) {
1121 newBins[i] = factor * newBins[i-1];
1122 }
1123 axis->Set(bins, newBins);
1124 delete [] newBins;
1125
1126}
1127
1128
1129//________________________________________________________________________
1130Double_t* AliTPCcalibResidualPID::ExtractResidualPID(THnSparseF * histPidQA, const Bool_t useV0s, const Char_t * outFile,
1131 const Char_t * type, const Char_t * period, const Char_t * pass,
1132 const Char_t * system, const Double_t * initialParameters,
1133 const Char_t *dedxtype,
1134 AliTPCcalibResidualPID::FitType fitType) {
1135 //
1136 // (1.) obtain residual graphs
1137 //
1138 TObjArray * arr = 0x0;
1139
1140 Bool_t isMC = kFALSE;
1141 if (strcmp(type, "MC") == 0) {
1142 arr = GetResidualGraphsMC(histPidQA, system);
1143 isMC = kTRUE;
1144 }
1145 else if (strcmp(type, "DATA") == 0) {
1146 arr = GetResidualGraphs(histPidQA, system, useV0s);
1147 }
1148 else {
1149 Printf("ERROR - ExtractResidualPID: Unknown type \"%s\" - must be \"MC\" or \"DATA\"!", type);
1150
1151 return 0x0;
1152 }
1153
1154 Bool_t isPPb = kFALSE;
1155 if (strcmp(system, "PPB") == 0 || strcmp(system, "PBP") == 0) {
1156 Printf("p-Pb/Pb-p detected - Applying special handling!");
1157 isPPb = kTRUE;
1158 }
1159 //
1160 // (2.) get old-style Bethe-Bloch parameters
1161 //
1162 TF1* parametrisation = FitBB(arr, isMC, isPPb, useV0s, initialParameters, fitType);
1163 //
1164 // (3.) obtain response functions to OADB
1165 //
1166 TObjArray* arrResponse = GetResponseFunctions(parametrisation, arr, type, period, pass, system, dedxtype);
1167 //
1168 // (4.) write results to file and exit
1169 //
1170 if (arrResponse) {
1171 TFile outputFile(outFile,"RECREATE");
1172 arrResponse->Write();
1173 outputFile.Close();
1174 }
1175 //
1176
1177 return parametrisation->GetParameters();
1178}
1179
1180
1181//________________________________________________________________________
1182TObjArray * AliTPCcalibResidualPID::GetSeparation(THnSparseF * histPidQA, Int_t kParticle1, Int_t kParticle2) {
1183
1184 //get THnSparse
1185 THnSparse * hist = histPidQA;
1186
1187
1188 Float_t nSigmaPlus1 = 0, nSigmaMinus1 = 0; //sigma of first particle in the TPC
1189 Float_t nSigmaPlus2 = 0, nSigmaMinus2 = 0; //sigma of second particle in the TPC
1190
1191 if(kParticle1 == 0){ // electron
1192 nSigmaMinus1 = -1.999;
1193 nSigmaPlus1 = 2.999;
1194 } else if(kParticle1 == 1){ //pion
1195 nSigmaMinus1 = -1.999;
1196 nSigmaPlus1 = 2.999;
1197 } else if(kParticle1 == 2){ //kaons
1198 nSigmaMinus1 = -2.999;
1199 nSigmaPlus1 = 2.999;
1200 } else if(kParticle1 == 3){ //protons
1201 nSigmaMinus1 = -2.999;
1202 nSigmaPlus1 = 2.999;
1203 }
1204
1205 //
1206 // 1. select and fit first particle
1207 //
1208 hist->GetAxis(3)->SetRangeUser(kParticle1,kParticle1);
1209 hist->GetAxis(4)->SetRangeUser(nSigmaMinus1,nSigmaPlus1);
1210 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1211 TH2D * histPart1 = (TH2D*) hist->Projection(1,0)->Clone("histPart1");
1212 histPart1->SetTitle(";p /(GeV/c) ; TPCSignal /(a.u.)");
1213 histPart1->RebinX(4);
1214
1215 TObjArray arr;
1216 histPart1->FitSlicesY(0,0,-1,10,"QNR",&arr);
1217 TH1D * PartMean1 = (TH1D *) arr.At(1)->Clone("PartMean1");
1218 TH1D * PartSigma1 = (TH1D *) arr.At(2)->Clone("PartSigma1");
1219 PartMean1->SetTitle(";p /(GeV/c) ; Mean (Gauss)");
1220 PartSigma1->SetTitle(";p /(GeV/c) ; Sigma (Gauss)");
1221
1222 histPart1->SetMarkerStyle(22);
1223 PartMean1->SetMarkerStyle(21);
1224 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1225 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1226
1227 if(kParticle2==0){ // electron
1228 nSigmaMinus2 = -1.999;
1229 nSigmaPlus2 = 2.999;
1230 } else if(kParticle2 == 1){ //pion
1231 nSigmaMinus2 = -1.999;
1232 nSigmaPlus2 = 2.999;
1233 } else if(kParticle2 == 2){ //kaons
1234 nSigmaMinus2 = -2.999;
1235 nSigmaPlus2 = 2.999;
1236 } else if(kParticle2 == 3){ //protons
1237 nSigmaMinus2 = -2.999;
1238 nSigmaPlus2 = 2.999;
1239 }
1240
1241 //
1242 // 2. select and fit second particle
1243 //
1244 hist->GetAxis(3)->SetRangeUser(kParticle2,kParticle2);
1245 hist->GetAxis(4)->SetRangeUser(nSigmaMinus2,nSigmaPlus2);
1246 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1247 TH2D * histPart2 = (TH2D*)hist->Projection(1,0)->Clone("histPart2");
1248 histPart2->RebinX(4);
1249 histPart2->FitSlicesY(0,0,-1,10,"QNR",&arr);
1250 TH1D * PartMean2 = (TH1D *) arr.At(1)->Clone("PartMean2");
1251 TH1D * PartSigma2 = (TH1D *) arr.At(2)->Clone("PartSigma2");
1252 PartMean2->SetTitle(";p /(GeV/c) ; Mean (Gauss)");
1253 PartSigma2->SetTitle(";p /(GeV/c) ; Sigma (Gauss)");
1254 PartMean2->SetMarkerStyle(20);
1255 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1256 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1257
1258 //
1259 // 3. separation
1260 //
1261
1262 TH1F *fHistSeparation=(TH1F*)PartMean1->Clone("fHistSeparation"); //to get same binning
1263 fHistSeparation->SetMarkerStyle(22);
1264 const Int_t Nbins = PartMean1->GetNbinsX();
1265 fHistSeparation->SetTitle(";p /(GeV/c) ; Separation");
1266
1267 Float_t DeltaMean[Nbins] ;
1268 Float_t DeltaSigma[Nbins];
1269
1270 for(Int_t i=0 ; i<Nbins; i++){
1271
1272 DeltaMean[i] = TMath::Abs(PartMean1->GetBinContent(i) - PartMean2->GetBinContent(i));
1273 DeltaSigma[i] = TMath::Abs((PartSigma1->GetBinContent(i) + PartSigma2->GetBinContent(i)))/2.;
1274
1275 if(!(TMath::Abs(DeltaSigma[i])<0.000001))fHistSeparation->SetBinContent(i,DeltaMean[i]/DeltaSigma[i]);
1276 }//for(Int_t i=0 ; i<Nbins ; i++)
1277
1278 TObjArray *array = new TObjArray();
1279 array->Add(histPart1);
1280 array->Add(histPart2);
1281 array->Add(PartMean1);
1282 array->Add(PartSigma1);
1283 array->Add(PartMean2);
1284 array->Add(PartSigma2);
1285 array->Add(fHistSeparation);
1286 return array;
1287
1288}
1289
1290
1291//________________________________________________________________________
1292TObjArray * AliTPCcalibResidualPID::GetResidualGraphs(THnSparseF * histPidQA, const Char_t * system, Bool_t useV0s) {
1293 //
1294 // Extracts the residual graphs from THnSparse created from data (NOT MC!)
1295 //
1296
1297 const TString momTitle = "#it{p}_{TPC} (GeV/#it{c})";
1298 const TString dEdxTitle = "d#it{E}/d#it{x} (arb. unit)";
1299
1300 Bool_t isPPb = kFALSE;
1301 if (strcmp(system, "PPB") == 0 || strcmp(system, "PBP") == 0) {
1302 Printf("p-Pb/Pb-p detected - Applying special handling!");
1303 isPPb = kTRUE;
1304 }
1305
1306 // the following parameters have to be extracted from the data itself
1307 //
1308
1309 Float_t nSigmaPionMinus = -3.999;
1310 Float_t nSigmaPionPlus = 3.999;
1311 Float_t nSigmaKaonMinus = -4.199;
1312 Float_t nSigmaKaonPlus = 4.7999;
1313 Float_t nSigmaElectronMinus = -1.999;
1314 Float_t nSigmaElectronPlus = 4.999;
1315
1316 Int_t cutForFitting = 10;
1317 Double_t heightFractionForFittingRange = 0.1;
1318 //
1319 THnSparse * hist = histPidQA;
1320 //
1321 TCanvas * canvasQAtpc = new TCanvas("canvasQAtpcResGraph","Control canvas for residual graphs (TPC)",100,10,1380,800);
1322 canvasQAtpc->Divide(2,2);
1323
1324 TCanvas * canvasQAtof = new TCanvas("canvasQAtofResGraph","Control canvas for residual graphs (TOF)",100,10,1380,800);
1325 canvasQAtof->Divide(2,2);
1326
1327 TCanvas * canvasQAv0 = new TCanvas("canvasQAv0ResGraph","Control canvas for residual graphs (V0)",100,10,1380,800);
1328 canvasQAv0->Divide(2,2);
1329
1330 TCanvas * canvasQAv0plusTOF = new TCanvas("canvasQAv0plusTOFResGraph","Control canvas for residual graphs (V0+TOF)",100,10,1380,800);
1331 canvasQAv0plusTOF->Divide(2,2);
1332
1333
1334 TCanvas * canvasQAv0DeDxPurityEl = new TCanvas("canvasQAv0DeDxPurityEl","Control canvas for residual graphs (V0 el)",100,10,600,400);
1335 TCanvas * canvasQAv0DeDxPurityPi = new TCanvas("canvasQAv0DeDxPurityPi","Control canvas for residual graphs (V0 pi)",100,10,600,400);
1336 TCanvas * canvasQAv0DeDxPurityPr = new TCanvas("canvasQAv0DeDxPurityPr","Control canvas for residual graphs (V0 pr)",100,10,600,400);
1337
1338 canvasQAv0DeDxPurityEl->SetLogx();
1339 canvasQAv0DeDxPurityPi->SetLogx();
1340 canvasQAv0DeDxPurityPr->SetLogx();
1341
1342 canvasQAv0DeDxPurityEl->SetLogz();
1343 canvasQAv0DeDxPurityPi->SetLogz();
1344 canvasQAv0DeDxPurityPr->SetLogz();
1345
1346 canvasQAv0DeDxPurityEl->SetTopMargin(0.03);
1347 canvasQAv0DeDxPurityPi->SetTopMargin(0.03);
1348 canvasQAv0DeDxPurityPr->SetTopMargin(0.03);
1349
1350 for (Int_t i = 1; i <= 4; i++) {
1351 canvasQAtpc->GetPad(i)->SetGrid(1, 1);
1352 canvasQAtof->GetPad(i)->SetGrid(1, 1);
1353 canvasQAv0->GetPad(i)->SetGrid(1, 1);
1354 canvasQAv0plusTOF->GetPad(i)->SetGrid(1, 1);
1355
1356 canvasQAtpc->GetPad(i)->SetLogz();
1357 canvasQAtof->GetPad(i)->SetLogz();
1358 canvasQAv0->GetPad(i)->SetLogz();
1359 canvasQAv0plusTOF->GetPad(i)->SetLogz();
1360
1361 canvasQAtpc->GetPad(i)->SetLogx();
1362 canvasQAtof->GetPad(i)->SetLogx();
1363 canvasQAv0->GetPad(i)->SetLogx();
1364 canvasQAv0plusTOF->GetPad(i)->SetLogx();
1365 }
1366 //
1367 // 1. select and fit electrons
1368 //
1369 hist->GetAxis(2)->SetRangeUser(0,0); // Non-V0s
1370 hist->GetAxis(3)->SetRangeUser(0,0); // electrons
1371 hist->GetAxis(4)->SetRangeUser(nSigmaElectronMinus,nSigmaElectronPlus); // 3sigma in TPC
1372 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1373 TH2D * histElectron = hist->Projection(1,0);
1374 histElectron->SetName("histElectron");
1375 histElectron->RebinX(4);
1376 histElectron->GetXaxis()->SetRangeUser(0.2,3.0);
1377 TObjArray arr;
1378 FitSlicesY(histElectron, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1379 TH1D * electronPoints = (TH1D *) arr.At(1)->Clone();
1380 //
1381 TGraphErrors * electronGraph = new TGraphErrors(electronPoints);
1382 electronGraph->SetName("electronGraph");
1383 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
1384 Bool_t removePoint = electronGraph->GetY()[ip] < 10 ||
1385 electronGraph->GetEY()[ip]/electronGraph->GetY()[ip] > 0.05 ||
1386 electronGraph->GetX()[ip] > 2.0 ||
1387 electronGraph->GetX()[ip] < 0.5;
1388 if (removePoint) {
1389 electronGraph->RemovePoint(ip);
1390 ip--;
1391 continue;
1392 }
1393 }
1394 //
1395 canvasQAtof->cd(1);
1396 histElectron->SetTitle("electrons");
1397 histElectron->GetYaxis()->SetRangeUser(50, 120);
1398 histElectron->GetXaxis()->SetTitle(momTitle.Data());
1399 histElectron->GetYaxis()->SetTitle(dEdxTitle.Data());
1400 histElectron->GetXaxis()->SetMoreLogLabels(kTRUE);
1401 histElectron->GetXaxis()->SetNoExponent(kTRUE);
1402 histElectron->Draw("colz");
1403 electronPoints->SetMarkerStyle(24);
1404 electronPoints->Draw("same");
1405 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1406 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1407 //
1408 // 2. protons
1409 //
1410 hist->GetAxis(2)->SetRangeUser(0,0); // Non-V0s
1411 hist->GetAxis(3)->SetRangeUser(3,3); // protons
1412 //
1413 //hist->GetAxis(4)->SetRangeUser(nSigmaProtonMinus,nSigmaProtonPlus); // protons --> not reliable, use PATTERN RECOGNITION
1414 TH2D * histProtonTPC = hist->Projection(1,0);
1415 histProtonTPC->SetName("histProtonTPC");
1416 histProtonTPC->GetXaxis()->SetRangeUser(0.15,0.7);
1417 histProtonTPC->GetYaxis()->SetRangeUser(50, hist->GetAxis(1)->GetBinUpEdge(hist->GetAxis(1)->GetNbins()));
1418
1419 // PATTERN RECOGNITION
1420 //OLD TF1 betaSq("betaSq","50./TMath::Power(x,1.3)",0.1,10);
1421 // Add some additional Erf - cuts away kaons for pPb and PbPb and does not hurt in pp
1422 TF1 betaSq("betaSq","50./TMath::Power(x,1.3) + (1-TMath::Erf((x-0.2) / 0.075)) * 100",0.1,10);
1423 for(Int_t ix = 1; ix <= histProtonTPC->GetXaxis()->GetNbins(); ix++) {
1424 for(Int_t jy = 1; jy <= histProtonTPC->GetYaxis()->GetNbins(); jy++) {
1425 Float_t yPos = histProtonTPC->GetYaxis()->GetBinCenter(jy);
1426 Float_t xPos = histProtonTPC->GetXaxis()->GetBinCenter(ix);
1427 Int_t bin = histProtonTPC->GetBin(ix,jy);
1428 if (yPos < betaSq.Eval(xPos)) histProtonTPC->SetBinContent(bin,0);
1429 }
1430 }
1431 //
1432 //TODO Use likelihood option -> Inside fitting range ~no contamination, but little statistics at low momenta requires L
1433 FitSlicesY(histProtonTPC, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
1434 TH1D * protonPointsTPC = (TH1D *) arr.At(1)->Clone();
1435 //
1436 TGraphErrors * protonTpcGraph = new TGraphErrors(protonPointsTPC);
1437 protonTpcGraph->SetName("protonTpcGraph");
1438 for(Int_t ip = 0; ip < protonTpcGraph->GetN(); ip ++) {
1439 Bool_t removePoint = protonTpcGraph->GetY()[ip] < 10 || protonTpcGraph->GetEY()[ip]/protonTpcGraph->GetY()[ip] > 0.05 // TODO Larger tolerance, since this is only for the correction function, where 5% are still better than no data point
1440 || protonTpcGraph->GetX()[ip] > (useV0s ? (isPPb ? 0.499 : 0.349) : 0.649); // If V0s are to be used, don't use TPC only protons to too high momenta; for pPb low statistics for the moment, therefore, go a bit further with TPC protons
1441 //TODO NOW -> Changed range of TPC-signal -> Hopefully, sufficient statistics now for very low momenta!|| protonTpcGraph->GetX()[ip] < 0.19; // Added this cut because almost always bad statistics below 0.19
1442 if (removePoint) {
1443 protonTpcGraph->RemovePoint(ip);
1444 ip--;
1445 continue;
1446 }
1447 }
1448 //
1449 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1450 TH2D * histProtonTOF = hist->Projection(1,0);
1451 histProtonTOF->SetName("histProtonTOF");
1452 histProtonTOF->GetXaxis()->SetRangeUser(0.6,2.5);
1453
1454 // Same pattern recognition as before
1455 for(Int_t ix = 1; ix <= histProtonTOF->GetXaxis()->GetNbins(); ix++) {
1456 for(Int_t jy = 1; jy <= histProtonTOF->GetYaxis()->GetNbins(); jy++) {
1457 Float_t yPos = histProtonTOF->GetYaxis()->GetBinCenter(jy);
1458 Float_t xPos = histProtonTOF->GetXaxis()->GetBinCenter(ix);
1459 Int_t bin = histProtonTOF->GetBin(ix,jy);
1460 if (yPos < betaSq.Eval(xPos)) histProtonTOF->SetBinContent(bin,0);
1461 }
1462 }
1463
1464 FitSlicesY(histProtonTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1465
1466 TH1D * protonPointsTOF = (TH1D *)arr.At(1)->Clone();
1467 //
1468 TGraphErrors * protonTofGraph = new TGraphErrors(protonPointsTOF);
1469 protonTofGraph->SetName("protonTofGraph");
1470 for(Int_t ip = 0; ip < protonTofGraph->GetN(); ip ++) {
1471 // If V0s are to be used, TPC+TOF protons are only for reference and can be plotted to higher momenta
1472 Bool_t removePoint = protonTofGraph->GetY()[ip] < 10 || protonTofGraph->GetEY()[ip]/protonTofGraph->GetY()[ip] > 0.02 || protonTofGraph->GetX()[ip] > (useV0s ? 3 : 2) || protonTofGraph->GetX()[ip] < 0.65;
1473 if (removePoint) {
1474 protonTofGraph->RemovePoint(ip);
1475 ip--;
1476 continue;
1477 }
1478 }
1479 //
1480 canvasQAtpc->cd(2);
1481 histProtonTPC->SetTitle("protons");
1482 histProtonTPC->GetXaxis()->SetTitle(momTitle.Data());
1483 histProtonTPC->GetYaxis()->SetTitle(dEdxTitle.Data());
1484 histProtonTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
1485 histProtonTPC->GetXaxis()->SetNoExponent(kTRUE);
1486 histProtonTPC->Draw("colz");
1487 betaSq.DrawCopy("same");
1488 protonPointsTPC->SetMarkerStyle(20);
1489 protonPointsTOF->SetMarkerStyle(24);
1490 protonPointsTOF->Draw("same");
1491 protonPointsTPC->Draw("same");
1492 //
1493 protonTpcGraph->SetMarkerStyle(26);
1494 protonTpcGraph->SetMarkerColor(kMagenta);
1495 protonTpcGraph->DrawClone("p");
1496 protonTofGraph->SetMarkerStyle(25);
1497 protonTofGraph->SetMarkerColor(kMagenta);
1498 protonTofGraph->DrawClone("p");
1499
1500 canvasQAtof->cd(2);
1501 histProtonTOF->SetTitle("protons");
1502 histProtonTOF->GetYaxis()->SetRangeUser(30, 250);
1503 histProtonTOF->GetXaxis()->SetTitle(momTitle.Data());
1504 histProtonTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1505 histProtonTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1506 histProtonTOF->GetXaxis()->SetNoExponent(kTRUE);
1507 histProtonTOF->Draw("colz");
1508 betaSq.DrawCopy("same");
1509 protonPointsTOF->Draw("same");
1510 protonPointsTPC->Draw("same");
1511 //
1512 protonTpcGraph->DrawClone("p");
1513 protonTofGraph->DrawClone("p");
1514
1515 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1516 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1517 //
1518 // 3. pions
1519 //
1520 hist->GetAxis(2)->SetRangeUser(0,0); // Non-V0s
1521 hist->GetAxis(3)->SetRangeUser(1,1); // pions
1522 //
1523 Double_t lowerPionThreshold = 0.3;
1524
1525 hist->GetAxis(4)->SetRangeUser(nSigmaPionMinus,nSigmaPionPlus); // pions
1526 TH2D * histPionTPC = hist->Projection(1,0);
1527 histPionTPC->SetName("histPionTPC");
1528 histPionTPC->GetXaxis()->SetRangeUser(0.15,0.7);
1529 FitSlicesY(histPionTPC, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1530
1531 // In case of really bad splines comment last 5 lines and use the following 6 lines:
1532 //TH2D * histPionTPC = hist->Projection(1,0);
1533 //histPionTPC->SetName("histPionTPC");
1534 //histPionTPC->GetYaxis()->SetRangeUser(30,100);
1535 //histPionTPC->GetXaxis()->SetRangeUser(0.15,0.7);
1536 //FitSlicesY(histPionTPC, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1537 //lowerPionThreshold = 0.15;
1538
1539
1540 TH1D * pionPointsTPC = (TH1D *) arr.At(1)->Clone();
1541 //
1542 TGraphErrors * pionTpcGraph = new TGraphErrors(pionPointsTPC);
1543 pionTpcGraph->SetName("pionTpcGraph");
1544 for(Int_t ip = 0; ip < pionTpcGraph->GetN(); ip ++) {
1545 Bool_t removePoint = pionTpcGraph->GetY()[ip] < 10 || pionTpcGraph->GetEY()[ip]/pionTpcGraph->GetY()[ip] > 0.02 || pionTpcGraph->GetX()[ip] > 0.5
1546 || pionTpcGraph->GetX()[ip] < lowerPionThreshold; // Exclude contamination by electrons
1547 if (removePoint) {
1548 pionTpcGraph->RemovePoint(ip);
1549 ip--;
1550 continue;
1551 }
1552 }
1553 //
1554 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1555 TH2D * histPionTOF = hist->Projection(1,0);
1556 histPionTOF->SetName("histPionTOF");
1557 histPionTOF->GetXaxis()->SetRangeUser(0.5,1.1);
1558 FitSlicesY(histPionTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1559 TH1D * pionPointsTOF = (TH1D *) arr.At(1)->Clone();
1560 TGraphErrors * pionTofGraph = new TGraphErrors(pionPointsTOF);
1561 pionTofGraph->SetName("pionTofGraph");
1562 for(Int_t ip = 0; ip < pionTofGraph->GetN(); ip ++) {
1563 Bool_t removePoint = pionTofGraph->GetY()[ip] < 10 || pionTofGraph->GetEY()[ip]/pionTofGraph->GetY()[ip] > 0.02 || pionTofGraph->GetX()[ip] > 1.1 || pionTofGraph->GetX()[ip] < 0.5; // Changed by Ben (was 0.35) to avoid problems with TOF efficiency/systematics
1564 if (removePoint) {
1565 pionTofGraph->RemovePoint(ip);
1566 ip--;
1567 continue;
1568 }
1569 }
1570 canvasQAtpc->cd(3);
1571 histPionTPC->GetYaxis()->SetRangeUser(30, 90);
1572 histPionTPC->SetTitle("pions");
1573 histPionTPC->GetXaxis()->SetTitle(momTitle.Data());
1574 histPionTPC->GetYaxis()->SetTitle(dEdxTitle.Data());
1575 histPionTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
1576 histPionTPC->GetXaxis()->SetNoExponent(kTRUE);
1577 histPionTPC->Draw("colz");
1578 pionPointsTPC->SetMarkerStyle(20);
1579 pionPointsTOF->SetMarkerStyle(24);
1580 pionPointsTOF->Draw("same");
1581 pionPointsTPC->Draw("same");
1582 //
1583 pionTpcGraph->SetMarkerStyle(26);
1584 pionTpcGraph->SetMarkerColor(kMagenta);
1585 pionTpcGraph->DrawClone("p");
1586 pionTofGraph->SetMarkerStyle(25);
1587 pionTofGraph->SetMarkerColor(kMagenta);
1588 pionTofGraph->DrawClone("p");
1589
1590 canvasQAtof->cd(3);
1591 histPionTOF->GetYaxis()->SetRangeUser(30, 80);
1592 histPionTOF->GetXaxis()->SetTitle(momTitle.Data());
1593 histPionTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1594 histPionTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1595 histPionTOF->GetXaxis()->SetNoExponent(kTRUE);
1596 histPionTOF->Draw("colz");
1597 histPionTOF->SetTitle("pions");
1598 pionPointsTOF->Draw("same");
1599 pionPointsTPC->Draw("same");
1600 //
1601 pionTpcGraph->DrawClone("p");
1602 pionTofGraph->DrawClone("p");
1603
1604
1605 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1606 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1607 //
1608 // 4. kaons
1609 //
1610 hist->GetAxis(2)->SetRangeUser(0,0); // Non-V0s
1611 hist->GetAxis(3)->SetRangeUser(2,2); // kaons
1612 //
1613 hist->GetAxis(4)->SetRangeUser(nSigmaKaonMinus,nSigmaKaonPlus); // kaons
1614 TH2D * histKaonTPC = hist->Projection(1,0);
1615 histKaonTPC->SetName("histKaonTPC");
1616 histKaonTPC->GetXaxis()->SetRangeUser(0.12,0.6999);
1617 FitSlicesY(histKaonTPC, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1618 TH1D * kaonPointsTPC = (TH1D*) arr.At(1)->Clone();
1619 //
1620 TGraphErrors * kaonTpcGraph = new TGraphErrors(kaonPointsTPC);
1621 kaonTpcGraph->SetName("kaonTpcGraph");
1622 for(Int_t ip = 0; ip < kaonTpcGraph->GetN(); ip ++) {
1623 Bool_t removePoint = kaonTpcGraph->GetY()[ip] < 10 || kaonTpcGraph->GetEY()[ip]/kaonTpcGraph->GetY()[ip] > 0.02
1624 || kaonTpcGraph->GetX()[ip] < 0.12 || kaonTpcGraph->GetX()[ip] > 0.319; //TODO BEN was > 0.399
1625 if (removePoint) {
1626 kaonTpcGraph->RemovePoint(ip);
1627 ip--;
1628 continue;
1629 }
1630 }
1631 //
1632
1633 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // sigma in TOF
1634
1635 /*
1636 hist->GetAxis(5)->SetRangeUser(-1.999,1.999); // sigma in TOF
1637
1638 if (hist->GetAxis(3)->GetNbins() >= 5) {
1639 printf("Using restricted eta range for TPC+TOF Kaons!\n");
1640 hist->GetAxis(3)->SetRangeUser(4,4);
1641 }
1642 else {
1643 printf("WARNING: Data points for restricted eta range for TPC+TOF Kaons not available! Using full eta range (worse w.r.t. contamination)\n");
1644 }*/
1645
1646 TH2D * histKaonTOF = hist->Projection(1,0);
1647 histKaonTOF->SetName("histKaonTOF");
1648 histKaonTOF->GetXaxis()->SetRangeUser(0.3,1.5);
1649 FitSlicesY(histKaonTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1650 TH1D * kaonPointsTOF = (TH1D*) arr.At(1)->Clone();
1651 //
1652 TGraphErrors * kaonTofGraph = new TGraphErrors(kaonPointsTOF);
1653 kaonTofGraph->SetName("kaonTofGraph");
1654 //
1655 for(Int_t ip = 0; ip < kaonTofGraph->GetN(); ip ++) {
1656 Bool_t removePoint = kaonTofGraph->GetY()[ip] < 10 || kaonTofGraph->GetEY()[ip]/kaonTofGraph->GetY()[ip] > 0.02 || kaonTofGraph->GetX()[ip] > 1.0
1657 || kaonTofGraph->GetX()[ip] < 0.36; //TODO BEN NOW was 0.5
1658 if (removePoint) {
1659 kaonTofGraph->RemovePoint(ip);
1660 ip--;
1661 continue;
1662 }
1663 }
1664 //
1665 canvasQAtpc->cd(4);
1666 histKaonTPC->SetTitle("kaons");
1667 histKaonTPC->GetYaxis()->SetRangeUser(30, 500);
1668 histKaonTPC->GetXaxis()->SetTitle(momTitle.Data());
1669 histKaonTPC->GetYaxis()->SetTitle(dEdxTitle.Data());
1670 histKaonTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
1671 histKaonTPC->GetXaxis()->SetNoExponent(kTRUE);
1672 histKaonTPC->Draw("colz");
1673 kaonPointsTPC->SetMarkerStyle(20);
1674 kaonPointsTOF->SetMarkerStyle(24);
1675 kaonPointsTOF->Draw("same");
1676 kaonPointsTPC->Draw("same");
1677 //
1678 kaonTpcGraph->SetMarkerStyle(26);
1679 kaonTpcGraph->SetMarkerColor(kMagenta);
1680 kaonTpcGraph->DrawClone("p");
1681 kaonTofGraph->SetMarkerStyle(25);
1682 kaonTofGraph->SetMarkerColor(kMagenta);
1683 kaonTofGraph->DrawClone("p");
1684
1685
1686 canvasQAtof->cd(4);
1687 histKaonTOF->GetYaxis()->SetRangeUser(30, 250);
1688 histKaonTOF->SetTitle("kaons");
1689 histKaonTOF->GetXaxis()->SetTitle(momTitle.Data());
1690 histKaonTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1691 histKaonTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1692 histKaonTOF->GetXaxis()->SetNoExponent(kTRUE);
1693 histKaonTOF->Draw("colz");
1694 kaonPointsTOF->Draw("same");
1695 kaonPointsTPC->Draw("same");
1696 kaonTpcGraph->DrawClone("p");
1697 kaonTofGraph->DrawClone("p");
1698
1699 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1700 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1701
1702
1703 //
1704 // 5. V0 electrons
1705 //
1706 hist->GetAxis(2)->SetRangeUser(1,1); // V0 electrons
1707 hist->GetAxis(3)->SetRangeUser(0,0); // electrons
1708
1709 //
1710 TH2D * histElectronV0 = hist->Projection(1,0);
1711 histElectronV0->SetName("histElectronV0");
1712 //histElectronV0->RebinX(2);
1713 histElectronV0->GetXaxis()->SetRangeUser(0.15,5.0);
1714 FitSlicesY(histElectronV0, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1715 TH1D * electronPointsV0 = (TH1D*) arr.At(1)->Clone();
1716 //
1717 TGraphErrors * electronV0Graph = new TGraphErrors(electronPointsV0);
1718 electronV0Graph->SetName("electronV0Graph");
1719 for(Int_t ip = 0; ip < electronV0Graph->GetN(); ip ++) {
1720 Bool_t removePoint = electronV0Graph->GetY()[ip] < 10 || electronV0Graph->GetEY()[ip]/electronV0Graph->GetY()[ip] > 0.02;
1721
1722 if (removePoint) {
1723 electronV0Graph->RemovePoint(ip);
1724 ip--;
1725 continue;
1726 }
1727 }
1728 //
1729 canvasQAv0->cd(1);
1730 histElectronV0->SetTitle("V0 electrons");
1731 histElectronV0->GetYaxis()->SetRangeUser(50, 120);
1732 histElectronV0->GetXaxis()->SetTitle(momTitle.Data());
1733 histElectronV0->GetYaxis()->SetTitle(dEdxTitle.Data());
1734 histElectronV0->GetXaxis()->SetMoreLogLabels(kTRUE);
1735 histElectronV0->GetXaxis()->SetNoExponent(kTRUE);
1736 histElectronV0->SetStats(0);
1737 histElectronV0->Draw("colz");
1738 electronPointsV0->SetMarkerStyle(34);
1739 electronPointsV0->Draw("same");
1740 electronGraph->SetMarkerStyle(25);
1741 electronGraph->SetMarkerColor(kMagenta);
1742 electronGraph->DrawClone("p");
1743
1744 canvasQAv0DeDxPurityEl->cd();
1745 gStyle->SetOptTitle(0);
1746 TH1D* hElNew = (TH1D*)histElectronV0->DrawClone("colz");
1747 hElNew->GetXaxis()->SetTitleOffset(1.0);
1748 hElNew->SetTitle("");
1749 electronPointsV0->DrawClone("same");
1750 gStyle->SetOptTitle(1);
1751
1752
1753
1754 canvasQAtof->cd(1);
1755 electronV0Graph->SetMarkerStyle(24);
1756 electronV0Graph->SetMarkerColor(kMagenta);
1757 electronV0Graph->DrawClone("p");
1758
1759 //
1760 // 6. V0 pions
1761 //
1762 hist->GetAxis(2)->SetRangeUser(2,2); // V0 pions
1763 hist->GetAxis(3)->SetRangeUser(1,1); // pions
1764 //
1765 TH2D * histPionV0 = hist->Projection(1,0);
1766 histPionV0->SetName("histPionV0");
1767 histPionV0->GetXaxis()->SetRangeUser(0.15,10.);
1768 FitSlicesY(histPionV0, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1769 TH1D * pionPointsV0 = (TH1D*) arr.At(1)->Clone();
1770 //
1771 TGraphErrors * pionV0Graph = new TGraphErrors(pionPointsV0);
1772 pionV0Graph->SetName("pionV0Graph");
1773 for(Int_t ip = 0; ip < pionV0Graph->GetN(); ip ++) {
1774 Bool_t removePoint = pionV0Graph->GetY()[ip] < 10 || pionV0Graph->GetEY()[ip]/pionV0Graph->GetY()[ip] > 0.02;
1775
1776 if (removePoint) {
1777 pionV0Graph->RemovePoint(ip);
1778 ip--;
1779 continue;
1780 }
1781 }
1782 //
1783 canvasQAv0->cd(3);
1784 histPionV0->SetTitle("V0 pions");
1785 histPionV0->GetYaxis()->SetRangeUser(30, 100);
1786 histPionV0->GetXaxis()->SetTitle(momTitle.Data());
1787 histPionV0->GetYaxis()->SetTitle(dEdxTitle.Data());
1788 histPionV0->GetXaxis()->SetMoreLogLabels(kTRUE);
1789 histPionV0->GetXaxis()->SetNoExponent(kTRUE);
1790 histPionV0->Draw("colz");
1791 pionPointsV0->SetMarkerStyle(34);
1792 pionPointsV0->Draw("same");
1793 pionTofGraph->DrawClone("p");
1794 pionTpcGraph->DrawClone("p");
1795
1796 canvasQAv0DeDxPurityPi->cd();
1797 gStyle->SetOptTitle(0);
1798 TH1D* hPiNew = (TH1D*)histPionV0->DrawClone("colz");
1799 hPiNew->GetXaxis()->SetTitleOffset(1.0);
1800 hPiNew->SetTitle("");
1801 pionPointsV0->DrawClone("same");
1802 gStyle->SetOptTitle(1);
1803
1804 canvasQAtof->cd(3);
1805 pionV0Graph->SetMarkerStyle(24);
1806 pionV0Graph->SetMarkerColor(kMagenta);
1807 pionV0Graph->DrawClone("p");
1808
1809 canvasQAtpc->cd(3);
1810 pionV0Graph->DrawClone("p");
1811
1812 //
1813 // 6. V0 protons
1814 //
1815 hist->GetAxis(2)->SetRangeUser(3,3); // V0 protons
1816 hist->GetAxis(3)->SetRangeUser(3,3); // protons
1817 //
1818 TH2D * histProtonV0 = hist->Projection(1,0);
1819 histProtonV0->SetName("histProtonV0");
1820 histProtonV0->GetXaxis()->SetRangeUser(0.15,10.);
1821
1822 // Remove contamination due to el and pions and low momenta because there the statistics
1823 // for the V0 protons goes down and becomes comparable with the contamination
1824 // -> This spoils the fit, if the contamination is not removed
1825
1826 // PATTERN RECOGNITION
1827 Int_t correctionUpToBin = histProtonV0->GetXaxis()->FindBin(0.6);
1828
1829 for(Int_t ix = 1; ix <= correctionUpToBin; ix++) {
1830 for(Int_t jy = 1; jy <= histProtonV0->GetYaxis()->GetNbins(); jy++) {
1831 Float_t yPos = histProtonV0->GetYaxis()->GetBinCenter(jy);
1832 Float_t xPos = histProtonV0->GetXaxis()->GetBinCenter(ix);
1833 Int_t bin = histProtonV0->GetBin(ix,jy);
1834 if (yPos < betaSq.Eval(xPos)) histProtonV0->SetBinContent(bin,0);
1835 }
1836 }
1837
1838 /*
1839 Int_t correctionUpToBin = histProtonV0->GetXaxis()->FindBin(0.4);
1840 Double_t threshold = 120.;
1841
1842 for(Int_t ix = 1; ix <= correctionUpToBin; ix++) {
1843 for(Int_t jy = 1; jy <= histProtonV0->GetYaxis()->GetNbins(); jy++) {
1844 Float_t yPos = histProtonV0->GetYaxis()->GetBinCenter(jy);
1845 Int_t bin = histProtonV0->GetBin(ix,jy);
1846 if (yPos < threshold) histProtonV0->SetBinContent(bin,0);
1847 else break;
1848 }
1849 }
1850 */
1851
1852 FitSlicesY(histProtonV0, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1853 TH1D * protonPointsV0 = (TH1D*) arr.At(1)->Clone();
1854 //
1855 TGraphErrors * protonV0Graph = new TGraphErrors(protonPointsV0);
1856 protonV0Graph->SetName("protonV0Graph");
1857 for(Int_t ip = 0; ip < protonV0Graph->GetN(); ip ++) {
1858 Bool_t removePoint = protonV0Graph->GetY()[ip] < 10 || protonV0Graph->GetEY()[ip]/protonV0Graph->GetY()[ip] > 0.02;
1859
1860 if (removePoint) {
1861 protonV0Graph->RemovePoint(ip);
1862 ip--;
1863 continue;
1864 }
1865 }
1866 //
1867 canvasQAv0->cd(2);
1868 histProtonV0->SetTitle("V0 protons");
1869 histProtonV0->GetXaxis()->SetTitle(momTitle.Data());
1870 histProtonV0->GetYaxis()->SetTitle(dEdxTitle.Data());
1871 histProtonV0->GetXaxis()->SetMoreLogLabels(kTRUE);
1872 histProtonV0->GetXaxis()->SetNoExponent(kTRUE);
1873 histProtonV0->Draw("colz");
1874 protonPointsV0->SetMarkerStyle(34);
1875 protonPointsV0->Draw("same");
1876 protonTofGraph->DrawClone("p");
1877 protonTpcGraph->DrawClone("p");
1878
1879 canvasQAv0DeDxPurityPr->cd();
1880 gStyle->SetOptTitle(0);
1881 TH1D* hPrNew = (TH1D*)histProtonV0->DrawClone("colz");
1882 hPrNew->GetXaxis()->SetTitleOffset(1.0);
1883 hPrNew->SetTitle("");
1884 protonPointsV0->DrawClone("same");
1885 gStyle->SetOptTitle(1);
1886
1887 canvasQAtof->cd(2);
1888 protonV0Graph->SetMarkerStyle(24);
1889 protonV0Graph->SetMarkerColor(kMagenta);
1890 protonV0Graph->DrawClone("p");
1891
1892 canvasQAtpc->cd(2);
1893 protonV0Graph->DrawClone("p");
1894
1895
1896 hist->GetAxis(2)->SetRange(0,-1); // RESET RANGES
1897 hist->GetAxis(3)->SetRange(0,-1); // RESET RANGES
1898
1899
1900 //
1901 // 5. V0 electrons + TOF
1902 //
1903 hist->GetAxis(2)->SetRangeUser(1,1); // V0 electrons
1904 hist->GetAxis(3)->SetRangeUser(0,0); // electrons
1905 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1906 //
1907 TH2D * histElectronV0plusTOF = hist->Projection(1,0);
1908 histElectronV0plusTOF->SetName("histElectronV0plusTOF");
1909 histElectronV0plusTOF->RebinX(2);
1910 histElectronV0plusTOF->GetXaxis()->SetRangeUser(0.2,5.0);
1911 FitSlicesY(histElectronV0plusTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1912 TH1D * electronPointsV0plusTOF = (TH1D*) arr.At(1)->Clone();
1913 //
1914 TGraphErrors * electronV0plusTOFGraph = new TGraphErrors(electronPointsV0plusTOF);
1915 electronV0plusTOFGraph->SetName("electronV0plusTOFGraph");
1916 for(Int_t ip = 0; ip < electronV0plusTOFGraph->GetN(); ip ++) {
1917 Bool_t removePoint = electronV0plusTOFGraph->GetY()[ip] < 10 || electronV0plusTOFGraph->GetEY()[ip]/electronV0plusTOFGraph->GetY()[ip] > 0.02;
1918
1919 if (removePoint) {
1920 electronV0plusTOFGraph->RemovePoint(ip);
1921 ip--;
1922 continue;
1923 }
1924 }
1925 //
1926 canvasQAv0plusTOF->cd(1);
1927 histElectronV0plusTOF->SetTitle("V0+TOF electrons");
1928 histElectronV0plusTOF->GetYaxis()->SetRangeUser(50, 120);
1929 histElectronV0plusTOF->GetXaxis()->SetTitle(momTitle.Data());
1930 histElectronV0plusTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1931 histElectronV0plusTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1932 histElectronV0plusTOF->GetXaxis()->SetNoExponent(kTRUE);
1933 histElectronV0plusTOF->Draw("colz");
1934 electronPointsV0plusTOF->SetMarkerStyle(29);
1935 electronPointsV0plusTOF->Draw("same");
1936 electronGraph->DrawClone("p");
1937 electronV0Graph->DrawClone("p");
1938
1939 canvasQAv0->cd(1);
1940 electronV0plusTOFGraph->SetMarkerStyle(30);
1941 electronV0plusTOFGraph->SetMarkerColor(kMagenta);
1942 electronV0plusTOFGraph->DrawClone("p");
1943
1944 canvasQAtof->cd(1);
1945 electronV0plusTOFGraph->DrawClone("p");
1946
1947 //
1948 // 6. V0 pions + TOF
1949 //
1950 hist->GetAxis(2)->SetRangeUser(2,2); // V0 pions
1951 hist->GetAxis(3)->SetRangeUser(1,1); // pions
1952 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1953 //
1954 TH2D * histPionV0plusTOF = hist->Projection(1,0);
1955 histPionV0plusTOF->SetName("histPionV0plusTOF");
1956 histPionV0plusTOF->GetXaxis()->SetRangeUser(0.15,10.);
1957 FitSlicesY(histPionV0plusTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1958 TH1D * pionPointsV0plusTOF = (TH1D*) arr.At(1)->Clone();
1959 //
1960 TGraphErrors * pionV0plusTOFGraph = new TGraphErrors(pionPointsV0plusTOF);
1961 pionV0plusTOFGraph->SetName("pionV0plusTOFGraph");
1962 for(Int_t ip = 0; ip < pionV0plusTOFGraph->GetN(); ip ++) {
1963 Bool_t removePoint = pionV0plusTOFGraph->GetY()[ip] < 10 || pionV0plusTOFGraph->GetEY()[ip]/pionV0plusTOFGraph->GetY()[ip] > 0.02;
1964
1965 if (removePoint) {
1966 pionV0plusTOFGraph->RemovePoint(ip);
1967 ip--;
1968 continue;
1969 }
1970 }
1971 //
1972 canvasQAv0plusTOF->cd(3);
1973 histPionV0plusTOF->SetTitle("V0+TOF pions");
1974 histPionV0plusTOF->GetYaxis()->SetRangeUser(30, 100);
1975 histPionV0plusTOF->GetXaxis()->SetTitle(momTitle.Data());
1976 histPionV0plusTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1977 histPionV0plusTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1978 histPionV0plusTOF->GetXaxis()->SetNoExponent(kTRUE);
1979 histPionV0plusTOF->Draw("colz");
1980 pionPointsV0plusTOF->SetMarkerStyle(29);
1981 pionPointsV0plusTOF->Draw("same");
1982 pionV0Graph->DrawClone("p");
1983 pionTofGraph->DrawClone("p");
1984 pionTpcGraph->DrawClone("p");
1985
1986 canvasQAv0->cd(3);
1987 pionV0plusTOFGraph->SetMarkerStyle(30);
1988 pionV0plusTOFGraph->SetMarkerColor(kMagenta);
1989 pionV0plusTOFGraph->DrawClone("p");
1990
1991 canvasQAtof->cd(3);
1992 pionV0plusTOFGraph->DrawClone("p");
1993
1994 canvasQAtpc->cd(3);
1995 pionV0plusTOFGraph->DrawClone("p");
1996
1997 //
1998 // 6. V0 protons + TOF
1999 //
2000 hist->GetAxis(2)->SetRangeUser(3,3); // V0 protons
2001 hist->GetAxis(3)->SetRangeUser(3,3); // protons
2002 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
2003 //
2004 TH2D * histProtonV0plusTOF = hist->Projection(1,0);
2005 histProtonV0plusTOF->SetName("histProtonV0plusTOF");
2006 histProtonV0plusTOF->GetXaxis()->SetRangeUser(0.15,10.);
2007
2008 // Remove contamination due to el and pions and low momenta because there the statistics
2009 // for the V0 protons goes down and becomes comparable with the contamination
2010 // -> This spoils the fit, if the contamination is not removed
2011
2012 // PATTERN RECOGNITION
2013 correctionUpToBin = histProtonV0plusTOF->GetXaxis()->FindBin(0.6);
2014
2015 for(Int_t ix = 1; ix <= correctionUpToBin; ix++) {
2016 for(Int_t jy = 1; jy <= histProtonV0plusTOF->GetYaxis()->GetNbins(); jy++) {
2017 Float_t yPos = histProtonV0plusTOF->GetYaxis()->GetBinCenter(jy);
2018 Float_t xPos = histProtonV0plusTOF->GetXaxis()->GetBinCenter(ix);
2019 Int_t bin = histProtonV0plusTOF->GetBin(ix,jy);
2020 if (yPos < betaSq.Eval(xPos)) histProtonV0plusTOF->SetBinContent(bin,0);
2021 }
2022 }
2023
2024 FitSlicesY(histProtonV0plusTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
2025 TH1D * protonPointsV0plusTOF = (TH1D*) arr.At(1)->Clone();
2026 //
2027 TGraphErrors * protonV0plusTOFGraph = new TGraphErrors(protonPointsV0plusTOF);
2028 protonV0plusTOFGraph->SetName("protonV0plusTOFGraph");
2029 for(Int_t ip = 0; ip < protonV0plusTOFGraph->GetN(); ip ++) {
2030 Bool_t removePoint = protonV0plusTOFGraph->GetY()[ip] < 10 || protonV0plusTOFGraph->GetEY()[ip]/protonV0plusTOFGraph->GetY()[ip] > 0.02;
2031
2032 if (removePoint) {
2033 protonV0plusTOFGraph->RemovePoint(ip);
2034 ip--;
2035 continue;
2036 }
2037 }
2038 //
2039 canvasQAv0plusTOF->cd(2);
2040 histProtonV0plusTOF->SetTitle("V0+TOF protons");
2041 histProtonV0plusTOF->GetXaxis()->SetTitle(momTitle.Data());
2042 histProtonV0plusTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
2043 histProtonV0plusTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
2044 histProtonV0plusTOF->GetXaxis()->SetNoExponent(kTRUE);
2045 histProtonV0plusTOF->Draw("colz");
2046 protonPointsV0plusTOF->SetMarkerStyle(29);
2047 protonPointsV0plusTOF->Draw("same");
2048 protonV0Graph->DrawClone("p");
2049 protonTofGraph->DrawClone("p");
2050 protonTpcGraph->DrawClone("p");
2051
2052 canvasQAv0->cd(2);
2053 protonV0plusTOFGraph->SetMarkerStyle(30);
2054 protonV0plusTOFGraph->SetMarkerColor(kMagenta);
2055 protonV0plusTOFGraph->DrawClone("p");
2056
2057 canvasQAtof->cd(2);
2058 protonV0plusTOFGraph->DrawClone("p");
2059
2060 canvasQAtpc->cd(2);
2061 protonV0plusTOFGraph->DrawClone("p");
2062
2063 hist->GetAxis(2)->SetRange(0,-1); // RESET RANGES
2064 hist->GetAxis(3)->SetRange(0,-1); // RESET RANGES
2065 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
2066
2067
2068 // Clone (V0, V0+TOF) graphs: Remove some points, which are expected to deviate from the Bethe-Bloch curve, from the original graphs, so that
2069 // these graphs can be used for the BB fit. The original graph will keep all point in order to determine the correction and response
2070 // functions
2071 TGraphErrors * electronV0GraphForBBfit = new TGraphErrors(*electronV0Graph);
2072 electronV0GraphForBBfit->SetName("electronV0GraphForBBfit");
2073
2074 for(Int_t ip = 0; ip < electronV0GraphForBBfit->GetN(); ip ++) {
2075 Bool_t removePoint = electronV0GraphForBBfit->GetX()[ip] < (isPPb ? 1.2 : 0.4);// || electronV0GraphForBBfit->GetX()[ip] > 2.2;
2076
2077 if (removePoint) {
2078 electronV0GraphForBBfit->RemovePoint(ip);
2079 ip--;
2080 continue;
2081 }
2082 }
2083
2084 TGraphErrors * pionV0GraphForBBfit = new TGraphErrors(*pionV0Graph);
2085 pionV0GraphForBBfit->SetName("pionV0GraphForBBfit");
2086
2087 for(Int_t ip = 0; ip < pionV0GraphForBBfit->GetN(); ip ++) {
2088 Bool_t removePoint = pionV0GraphForBBfit->GetX()[ip] < (isPPb ? 1.0 : 0.76);// || pionV0GraphForBBfit->GetX()[ip] > 6.; //TODO NOW was < 0.4 before
2089 //Bool_t removePoint = pionV0GraphForBBfit->GetX()[ip] < 0.4 || pionV0GraphForBBfit->GetX()[ip] > 0.399;// In this case NOT used for BB fit
2090 if (removePoint) {
2091 pionV0GraphForBBfit->RemovePoint(ip);
2092 ip--;
2093 continue;
2094 }
2095 }
2096
2097 TGraphErrors * protonV0GraphForBBfit = new TGraphErrors(*protonV0Graph);
2098 protonV0GraphForBBfit->SetName("protonV0GraphForBBfit");
2099
2100 for(Int_t ip = 0; ip < protonV0GraphForBBfit->GetN(); ip ++) {
2101 Bool_t removePoint = protonV0GraphForBBfit->GetX()[ip] < 0.9 || protonV0GraphForBBfit->GetX()[ip] > 5.0; //TODO NOW was 2.5 before
2102 //Bool_t removePoint = protonV0GraphForBBfit->GetX()[ip] < 0.9 || protonV0GraphForBBfit->GetX()[ip] > 0.599;// In this case NOT used for BB fit
2103 if (removePoint) {
2104 protonV0GraphForBBfit->RemovePoint(ip);
2105 ip--;
2106 continue;
2107 }
2108 }
2109
2110
2111 // V0 plus TOF
2112 TGraphErrors * electronV0plusTOFGraphForBBfit = new TGraphErrors(*electronV0plusTOFGraph);
2113 electronV0plusTOFGraphForBBfit->SetName("electronV0plusTOFGraphForBBfit");
2114
2115 for(Int_t ip = 0; ip < electronV0plusTOFGraphForBBfit->GetN(); ip ++) {
2116 Bool_t removePoint = electronV0plusTOFGraphForBBfit->GetX()[ip] < (isPPb ? 1.2 : 0.6);//0.4 || electronV0plusTOFGraphForBBfit->GetX()[ip] > 1.3799;
2117 if (removePoint) {
2118 electronV0plusTOFGraphForBBfit->RemovePoint(ip);
2119 ip--;
2120 continue;
2121 }
2122 }
2123
2124 TGraphErrors * pionV0plusTOFGraphForBBfit = new TGraphErrors(*pionV0plusTOFGraph);
2125 pionV0plusTOFGraphForBBfit->SetName("pionV0plusTOFGraphForBBfit");
2126
2127 for(Int_t ip = 0; ip < pionV0plusTOFGraphForBBfit->GetN(); ip ++) {
2128 Bool_t removePoint = pionV0plusTOFGraphForBBfit->GetX()[ip] < 0.4;// || pionV0plusTOFGraphForBBfit->GetX()[ip] > 6.;
2129 if (removePoint) {
2130 pionV0plusTOFGraphForBBfit->RemovePoint(ip);
2131 ip--;
2132 continue;
2133 }
2134 }
2135
2136 TGraphErrors * protonV0plusTOFGraphForBBfit = new TGraphErrors(*protonV0plusTOFGraph);
2137 protonV0plusTOFGraphForBBfit->SetName("protonV0plusTOFGraphForBBfit");
2138
2139 for(Int_t ip = 0; ip < protonV0plusTOFGraphForBBfit->GetN(); ip ++) {
2140 Bool_t removePoint = protonV0plusTOFGraphForBBfit->GetX()[ip] < 0.9 || protonV0plusTOFGraphForBBfit->GetX()[ip] > 2.5;
2141 if (removePoint) {
2142 protonV0plusTOFGraphForBBfit->RemovePoint(ip);
2143 ip--;
2144 continue;
2145 }
2146 }
2147
2148
2149 //
2150 // rescale graphs to betaGamma
2151 //
2152 kaonTofGraph->SetMarkerStyle(21);
2153 kaonTpcGraph->SetMarkerStyle(22);
2154 for(Int_t ip = 0; ip < kaonTofGraph->GetN(); ip ++) {
2155 kaonTofGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2156 kaonTofGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2157 }
2158 for(Int_t ip = 0; ip < kaonTpcGraph->GetN(); ip ++) {
2159 kaonTpcGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2160 kaonTpcGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2161 }
2162 //
2163 electronGraph->SetMarkerStyle(22);
2164 electronV0Graph->SetMarkerStyle(34);
2165 electronV0GraphForBBfit->SetMarkerStyle(34);
2166 electronV0plusTOFGraph->SetMarkerStyle(30);
2167 electronV0plusTOFGraphForBBfit->SetMarkerStyle(30);
2168 electronGraph->SetMarkerColor(2);
2169 electronV0Graph->SetMarkerColor(2);
2170 electronV0GraphForBBfit->SetMarkerColor(2);
2171 electronV0plusTOFGraph->SetMarkerColor(2);
2172 electronV0plusTOFGraphForBBfit->SetMarkerColor(2);
2173 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
2174 electronGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2175 electronGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2176 }
2177 for(Int_t ip = 0; ip < electronV0Graph->GetN(); ip ++) {
2178 electronV0Graph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2179 electronV0Graph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2180 }
2181 for(Int_t ip = 0; ip < electronV0GraphForBBfit->GetN(); ip ++) {
2182 electronV0GraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2183 electronV0GraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2184 }
2185 for(Int_t ip = 0; ip < electronV0plusTOFGraph->GetN(); ip ++) {
2186 electronV0plusTOFGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2187 electronV0plusTOFGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2188 }
2189 for(Int_t ip = 0; ip < electronV0plusTOFGraphForBBfit->GetN(); ip ++) {
2190 electronV0plusTOFGraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2191 electronV0plusTOFGraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2192 }
2193 //
2194 pionTofGraph->SetMarkerStyle(21);
2195 pionTpcGraph->SetMarkerStyle(22);
2196 pionV0Graph->SetMarkerStyle(34);
2197 pionV0GraphForBBfit->SetMarkerStyle(34);
2198 pionV0plusTOFGraph->SetMarkerStyle(30);
2199 pionV0plusTOFGraphForBBfit->SetMarkerStyle(30);
2200 pionTofGraph->SetMarkerColor(3);
2201 pionTpcGraph->SetMarkerColor(3);
2202 pionV0Graph->SetMarkerColor(3);
2203 pionV0GraphForBBfit->SetMarkerColor(3);
2204 pionV0plusTOFGraph->SetMarkerColor(3);
2205 pionV0plusTOFGraphForBBfit->SetMarkerColor(3);
2206 for(Int_t ip = 0; ip < pionTofGraph->GetN(); ip ++) {
2207 pionTofGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2208 pionTofGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2209 }
2210 for(Int_t ip = 0; ip < pionTpcGraph->GetN(); ip ++) {
2211 pionTpcGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2212 pionTpcGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2213 }
2214 for(Int_t ip = 0; ip < pionV0Graph->GetN(); ip ++) {
2215 pionV0Graph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2216 pionV0Graph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2217 }
2218 for(Int_t ip = 0; ip < pionV0GraphForBBfit->GetN(); ip ++) {
2219 pionV0GraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2220 pionV0GraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2221 }
2222 for(Int_t ip = 0; ip < pionV0plusTOFGraph->GetN(); ip ++) {
2223 pionV0plusTOFGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2224 pionV0plusTOFGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2225 }
2226 for(Int_t ip = 0; ip < pionV0plusTOFGraphForBBfit->GetN(); ip ++) {
2227 pionV0plusTOFGraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2228 pionV0plusTOFGraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2229 }
2230 //
2231 protonTofGraph->SetMarkerStyle(21);
2232 protonTpcGraph->SetMarkerStyle(22);
2233 protonV0Graph->SetMarkerStyle(34);
2234 protonV0GraphForBBfit->SetMarkerStyle(34);
2235 protonV0plusTOFGraph->SetMarkerStyle(30);
2236 protonV0plusTOFGraphForBBfit->SetMarkerStyle(30);
2237 protonTofGraph->SetMarkerColor(4);
2238 protonTpcGraph->SetMarkerColor(4);
2239 protonV0Graph->SetMarkerColor(4);
2240 protonV0GraphForBBfit->SetMarkerColor(4);
2241 protonV0plusTOFGraph->SetMarkerColor(4);
2242 protonV0plusTOFGraphForBBfit->SetMarkerColor(4);
2243 for(Int_t ip = 0; ip < protonTofGraph->GetN(); ip ++) {
2244 protonTofGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2245 protonTofGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2246 }
2247 for(Int_t ip = 0; ip < protonTpcGraph->GetN(); ip ++) {
2248 protonTpcGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2249 protonTpcGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2250 }
2251 for(Int_t ip = 0; ip < protonV0Graph->GetN(); ip ++) {
2252 protonV0Graph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2253 protonV0Graph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2254 }
2255 for(Int_t ip = 0; ip < protonV0GraphForBBfit->GetN(); ip ++) {
2256 protonV0GraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2257 protonV0GraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2258 }
2259 for(Int_t ip = 0; ip < protonV0plusTOFGraph->GetN(); ip ++) {
2260 protonV0plusTOFGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2261 protonV0plusTOFGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2262 }
2263 for(Int_t ip = 0; ip < protonV0plusTOFGraphForBBfit->GetN(); ip ++) {
2264 protonV0plusTOFGraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2265 protonV0plusTOFGraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2266 }
2267 //
2268 //
2269 TGraphErrors * graphAll = new TGraphErrors();
2270 TList * listColl = new TList();
2271 if (!useV0s) {
2272 //listColl->Add(protonTpcGraph);
2273 //listColl->Add(kaonTpcGraph);
2274 listColl->Add(pionTpcGraph);
2275 listColl->Add(electronGraph);
2276 listColl->Add(protonTofGraph);
2277 listColl->Add(kaonTofGraph);
2278 listColl->Add(pionTofGraph);
2279 }
2280 else {
2281 listColl->Add(pionV0GraphForBBfit);
2282 //listColl->Add(electronV0GraphForBBfit);
2283 listColl->Add(protonV0GraphForBBfit);
2284
2285 //listColl->Add(pionV0plusTOFGraphForBBfit);
2286 listColl->Add(electronV0plusTOFGraphForBBfit);
2287 //listColl->Add(protonV0plusTOFGraphForBBfit);
2288 }
2289 MergeGraphErrors(graphAll, listColl);
2290 graphAll->SetNameTitle("beamDataPoints","beamDataPoints");
2291
2292 // Create graph out of TPC only, V0, V0+TOF and TPC+TOF to determine correction functions
2293 TList * listCollPr = new TList();
2294 if (useV0s) {
2295 listCollPr->Add(protonTpcGraph);
2296 //listCollPr->Add(protonTofGraph);
2297
2298 TGraphErrors * protonV0GraphCut = new TGraphErrors(*protonV0Graph);
2299 protonV0GraphCut->SetName("protonV0GraphCut");
2300 for(Int_t ip = 0; ip < protonV0GraphCut->GetN(); ip ++) {
2301 Double_t mom = protonV0GraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kProton);
2302 //Bool_t removePoint = mom >= 0.6 || mom < 0.35; // Will take TPC protons instead (statistics) for very low momenta
2303 Bool_t removePoint = mom < (isPPb ? 0.6 : 0.35); // Will take TPC protons instead (statistics) for very low momenta;
2304 // for pPb low statistics for the moment, therefore, go a bit further with TPC protons
2305
2306
2307 if (removePoint) {
2308 protonV0GraphCut->RemovePoint(ip);
2309 ip--;
2310 continue;
2311 }
2312 }
2313 /*
2314 TGraphErrors * protonV0plusTOFGraphCut = new TGraphErrors(*protonV0plusTOFGraph);
2315 protonV0plusTOFGraphCut->SetName("protonV0plusTOFGraphCut");
2316 for(Int_t ip = 0; ip < protonV0plusTOFGraphCut->GetN(); ip ++) {
2317 Double_t mom = protonV0plusTOFGraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kProton);
2318 Bool_t removePoint = mom < 0.6;
2319
2320 if (removePoint) {
2321 protonV0plusTOFGraphCut->RemovePoint(ip);
2322 ip--;
2323 continue;
2324 }
2325 }*/
2326
2327 listCollPr->Add(protonV0GraphCut);
2328 //listCollPr->Add(protonV0plusTOFGraphCut);
2329 }
2330 else {
2331 listCollPr->Add(protonTpcGraph);
2332 listCollPr->Add(protonTofGraph);
2333 }
2334 TGraphErrors * graphPrCombined = new TGraphErrors();
2335 MergeGraphErrors(graphPrCombined, listCollPr);
2336 graphPrCombined->SetMarkerStyle(22);
2337 graphPrCombined->SetMarkerColor(4);
2338 graphPrCombined->SetNameTitle("Graph_Protons_Combined", "Graph_Protons_Combined");
2339
2340 TList * listCollPi = new TList();
2341 if (useV0s) {
2342 //listCollPi->Add(pionTpcGraph);
2343 //listCollPi->Add(pionTofGraph);
2344
2345 TGraphErrors * pionV0GraphCut = new TGraphErrors(*pionV0Graph);
2346 pionV0GraphCut->SetName("pionV0GraphCut");
2347 for(Int_t ip = 0; ip < pionV0GraphCut->GetN(); ip ++) {
2348 //Double_t mom = pionV0GraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kPion);
2349 Bool_t removePoint = kFALSE;//mom >= 0.4;
2350 //|| mom < 0.2;//TODO NOW NEEDED?
2351 if (removePoint) {
2352 pionV0GraphCut->RemovePoint(ip);
2353 ip--;
2354 continue;
2355 }
2356 }
2357 /*
2358 TGraphErrors * pionV0plusTOFGraphCut = new TGraphErrors(*pionV0plusTOFGraph);
2359 pionV0plusTOFGraphCut->SetName("pionV0plusTOFGraphCut");
2360 for(Int_t ip = 0; ip < pionV0plusTOFGraphCut->GetN(); ip ++) {
2361 Double_t mom = pionV0plusTOFGraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kPion);
2362 Bool_t removePoint = mom < 0.4;
2363
2364 if (removePoint) {
2365 pionV0plusTOFGraphCut->RemovePoint(ip);
2366 ip--;
2367 continue;
2368 }
2369 }*/
2370
2371 listCollPi->Add(pionV0GraphCut);
2372 //listCollPi->Add(pionV0plusTOFGraphCut);
2373 }
2374 else {
2375 listCollPi->Add(pionTpcGraph);
2376 listCollPi->Add(pionTofGraph);
2377 }
2378 TGraphErrors * graphPiCombined = new TGraphErrors();
2379 MergeGraphErrors(graphPiCombined, listCollPi);
2380 graphPiCombined->SetMarkerStyle(22);
2381 graphPiCombined->SetMarkerColor(3);
2382 graphPiCombined->SetNameTitle("Graph_Pions_Combined", "Graph_Pions_Combined");
2383
2384 TList * listCollKa = new TList();
2385 listCollKa->Add(kaonTpcGraph);
2386 listCollKa->Add(kaonTofGraph);
2387 TGraphErrors * graphKaCombined = new TGraphErrors();
2388 MergeGraphErrors(graphKaCombined, listCollKa);
2389 graphKaCombined->SetMarkerStyle(22);
2390 graphKaCombined->SetMarkerColor(5);
2391 graphKaCombined->SetNameTitle("Graph_Kaons_Combined", "Graph_Kaons_Combined");
2392
2393 TList * listCollEl = new TList();
2394 if (useV0s) {
2395 //listCollEl->Add(electronGraph);
2396
2397 TGraphErrors * electronV0GraphCut = new TGraphErrors(*electronV0Graph);
2398 electronV0GraphCut->SetName("electronV0GraphCut");
2399 /*
2400 for(Int_t ip = 0; ip < electronV0GraphCut->GetN(); ip ++) {
2401 Double_t mom = electronV0GraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kElectron);
2402 Bool_t removePoint = mom > 0.3;
2403 if (removePoint) {
2404 electronV0GraphCut->RemovePoint(ip);
2405 ip--;
2406 continue;
2407 }
2408 }
2409
2410 TGraphErrors * electronV0plusTOFGraphCut = new TGraphErrors(*electronV0plusTOFGraph);
2411 electronV0plusTOFGraphCut->SetName("electronV0plusTOFGraphCut");
2412 for(Int_t ip = 0; ip < electronV0plusTOFGraphCut->GetN(); ip ++) {
2413 Double_t mom = electronV0plusTOFGraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kElectron);
2414 Bool_t removePoint = mom <= 0.4;
2415
2416 if (removePoint) {
2417 electronV0plusTOFGraphCut->RemovePoint(ip);
2418 ip--;
2419 continue;
2420 }
2421 }
2422 */
2423 listCollEl->Add(electronV0GraphCut);
2424 //listCollEl->Add(electronV0plusTOFGraphCut);
2425 }
2426 else {
2427 listCollEl->Add(electronGraph);
2428 }
2429 TGraphErrors * graphElCombined = new TGraphErrors();
2430 MergeGraphErrors(graphElCombined, listCollEl);
2431 graphElCombined->SetMarkerStyle(22);
2432 graphElCombined->SetMarkerColor(2);
2433 graphElCombined->SetNameTitle("Graph_Electrons_Combined", "Graph_Electrons_Combined");
2434
2435
2436
2437 //
2438 // return array with all graphs
2439 //
2440 TObjArray * arrGraphs = new TObjArray();
2441 arrGraphs->Add(graphAll);
2442 //
2443 arrGraphs->Add(electronGraph);
2444 arrGraphs->Add(electronV0Graph);
2445 arrGraphs->Add(electronV0plusTOFGraph);
2446 arrGraphs->Add(electronV0GraphForBBfit);
2447 arrGraphs->Add(pionTpcGraph);
2448 arrGraphs->Add(pionTofGraph);
2449 arrGraphs->Add(pionV0Graph);
2450 arrGraphs->Add(pionV0plusTOFGraph);
2451 arrGraphs->Add(pionV0GraphForBBfit);
2452 arrGraphs->Add(kaonTpcGraph);
2453 arrGraphs->Add(kaonTofGraph);
2454 arrGraphs->Add(protonTpcGraph);
2455 arrGraphs->Add(protonTofGraph);
2456 arrGraphs->Add(protonV0Graph);
2457 arrGraphs->Add(protonV0plusTOFGraph);
2458 arrGraphs->Add(protonV0GraphForBBfit);
2459 //
2460 arrGraphs->Add(graphElCombined);
2461 arrGraphs->Add(graphPiCombined);
2462 arrGraphs->Add(graphKaCombined);
2463 arrGraphs->Add(graphPrCombined);
2464 //
2465 //
2466
2467 canvasQAtpc->SaveAs("splines_QA_ResidualGraphsTPC.root");
2468 canvasQAtof->SaveAs("splines_QA_ResidualGraphsTOF.root");
2469 canvasQAv0->SaveAs("splines_QA_ResidualGraphsV0.root");
2470 canvasQAv0plusTOF->SaveAs("splines_QA_ResidualGraphsV0plusTOF.root");
2471
2472
2473 canvasQAv0DeDxPurityEl->SaveAs("V0_dEdx_purity_el.root");
2474 canvasQAv0DeDxPurityPi->SaveAs("V0_dEdx_purity_Pi.root");
2475 canvasQAv0DeDxPurityPr->SaveAs("V0_dEdx_purity_Pr.root");
2476
2477 return arrGraphs;
2478
2479}
2480
2481
2482//________________________________________________________________________
2483TObjArray * AliTPCcalibResidualPID::GetResidualGraphsMC(THnSparseF * histPidQA, const Char_t * /*system*/) {
2484 //
2485 // Extracts the residual graphs from THnSparse created from MC (NOT DATA!)
2486 //
2487
2488 const TString momTitle = "#it{p}_{TPC} (GeV/#it{c})";
2489 const TString dEdxTitle = "d#it{E}/d#it{x} (arb. unit)";
2490
2491 Int_t cutForFitting = 10;
2492 Double_t heightFractionForFittingRange = 0.1;
2493
2494 //
2495 THnSparse * hist = histPidQA;
2496 //
2497 TCanvas * canvasQAmc = new TCanvas("canvasQAmcResGraph","Control canvas for residual graphs (MC)",100,10,1380,800);
2498 canvasQAmc->Divide(2,2);
2499
2500 for (Int_t i = 1; i <= 4; i++) {
2501 canvasQAmc->GetPad(i)->SetGrid(1, 1);
2502 canvasQAmc->GetPad(i)->SetLogz();
2503 canvasQAmc->GetPad(i)->SetLogx();
2504 }
2505 //
2506 // 1. select and fit electrons
2507 //
2508 // In the following, axis 3 will also be limited in range, although nsigma itself is not used. This is to avoid multiple counting of entries
2509 hist->GetAxis(2)->SetRangeUser(0,0); // electrons
2510 hist->GetAxis(3)->SetRangeUser(0,0); // electrons (used for nsigma and for the eta correction of the signal)
2511 TH2D * histElectron = hist->Projection(1,0);
2512 histElectron->SetName("histElectron");
2513 histElectron->RebinX(2);
2514 histElectron->GetXaxis()->SetRangeUser(0.15,8.0);
2515 TObjArray arr;
2516 FitSlicesY(histElectron, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
2517 TH1D * electronPoints = (TH1D *) arr.At(1)->Clone();
2518 //
2519 TGraphErrors * electronGraph = new TGraphErrors(electronPoints);
2520 electronGraph->SetName("electronGraphMC");
2521 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
2522 Bool_t removePoint = electronGraph->GetY()[ip] < 10 || electronGraph->GetEY()[ip]/electronGraph->GetY()[ip] > 0.03
2523 || electronGraph->GetX()[ip] < 0.15;// || electronGraph->GetX()[ip] > 3.1;
2524 if (removePoint) {
2525 electronGraph->RemovePoint(ip);
2526 ip--;
2527 continue;
2528 }
2529 }
2530 //
2531 canvasQAmc->cd(1);
2532 histElectron->SetTitle("electrons");
2533 histElectron->GetYaxis()->SetRangeUser(50, 120);
2534 histElectron->GetXaxis()->SetTitle(momTitle.Data());
2535 histElectron->GetYaxis()->SetTitle(dEdxTitle.Data());
2536 histElectron->GetXaxis()->SetMoreLogLabels(kTRUE);
2537 histElectron->GetXaxis()->SetNoExponent(kTRUE);
2538 histElectron->Draw("colz");
2539 electronPoints->SetMarkerStyle(24);
2540 electronPoints->Draw("same");
2541 //
2542 // 2. protons
2543 //
2544 hist->GetAxis(2)->SetRangeUser(3,3); // protons
2545 hist->GetAxis(3)->SetRangeUser(3,3); // protons (used for nsigma and for the eta correction of the signal)
2546 //
2547 TH2D * histProton = hist->Projection(1,0);
2548 histProton->SetName("histProton");
2549 histProton->GetXaxis()->SetRangeUser(0.15,8);
2550 histProton->GetYaxis()->SetRangeUser(10, hist->GetAxis(1)->GetBinUpEdge(hist->GetAxis(1)->GetNbins()));
2551 FitSlicesY(histProton, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
2552 TH1D * protonPoints = (TH1D *) arr.At(1)->Clone();
2553 //
2554 TGraphErrors * protonGraph = new TGraphErrors(protonPoints);
2555 protonGraph->SetName("protonGraphMC");
2556 for(Int_t ip = 0; ip < protonGraph->GetN(); ip ++) {
2557 Bool_t removePoint = protonGraph->GetY()[ip] < 10 || protonGraph->GetEY()[ip]/protonGraph->GetY()[ip] > 0.02 ||
2558 protonGraph->GetX()[ip] < 0.15 || protonGraph->GetX()[ip] > 6;
2559 if (removePoint) {
2560 protonGraph->RemovePoint(ip);
2561 ip--;
2562 continue;
2563 }
2564 }
2565 //
2566 canvasQAmc->cd(2);
2567 histProton->SetTitle("protons");
2568 histProton->GetXaxis()->SetTitle(momTitle.Data());
2569 histProton->GetYaxis()->SetTitle(dEdxTitle.Data());
2570 histProton->GetXaxis()->SetMoreLogLabels(kTRUE);
2571 histProton->GetXaxis()->SetNoExponent(kTRUE);
2572 histProton->Draw("colz");
2573 protonPoints->SetMarkerStyle(20);
2574 protonPoints->Draw("same");
2575
2576 //
2577 // 3. pions
2578 //
2579 hist->GetAxis(2)->SetRangeUser(1,1); // pions
2580 hist->GetAxis(3)->SetRangeUser(1,1); // pions (used for nsigma and for the eta correction of the signal)
2581 //
2582 TH2D * histPion = hist->Projection(1,0);
2583 histPion->SetName("histPion");
2584 histPion->GetXaxis()->SetRangeUser(0.15,50);
2585 FitSlicesY(histPion, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
2586 TH1D * pionPoints = (TH1D *) arr.At(1)->Clone();
2587 //
2588 TGraphErrors * pionGraph = new TGraphErrors(pionPoints);
2589 pionGraph->SetName("pionGraphMC");
2590 for(Int_t ip = 0; ip < pionGraph->GetN(); ip ++) {
2591 Bool_t removePoint = pionGraph->GetY()[ip] < 10 || pionGraph->GetEY()[ip]/pionGraph->GetY()[ip] > 0.005
2592 || pionGraph->GetX()[ip] < 0.15 || pionGraph->GetX()[ip] > 30;
2593 if (removePoint) {
2594 pionGraph->RemovePoint(ip);
2595 ip--;
2596 continue;
2597 }
2598 }
2599 //
2600 canvasQAmc->cd(3);
2601 histPion->GetYaxis()->SetRangeUser(30, 90);
2602 histPion->GetXaxis()->SetTitle(momTitle.Data());
2603 histPion->GetYaxis()->SetTitle(dEdxTitle.Data());
2604 histPion->GetXaxis()->SetMoreLogLabels(kTRUE);
2605 histPion->GetXaxis()->SetNoExponent(kTRUE);
2606 histPion->Draw("colz");
2607 histPion->SetTitle("pions");
2608 pionPoints->SetMarkerStyle(20);
2609 pionPoints->Draw("same");
2610
2611 //
2612 // 4. kaons
2613 //
2614 hist->GetAxis(2)->SetRangeUser(2,2); // kaons
2615 hist->GetAxis(3)->SetRangeUser(2,2); // kaons (used for nsigma and for the eta correction of the signal)
2616 //
2617 TH2D * histKaon = hist->Projection(1,0);
2618 histKaon->SetName("histKaon");
2619 histKaon->GetXaxis()->SetRangeUser(0.15,8);
2620 FitSlicesY(histKaon, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
2621 TH1D * kaonPoints = (TH1D*) arr.At(1)->Clone();
2622 //
2623 TGraphErrors * kaonGraph = new TGraphErrors(kaonPoints);
2624 kaonGraph->SetName("kaonGraphMC");
2625 for(Int_t ip = 0; ip < kaonGraph->GetN(); ip ++) {
2626 Bool_t removePoint = kaonGraph->GetY()[ip] < 10 || kaonGraph->GetEY()[ip]/kaonGraph->GetY()[ip] > 0.02
2627 || kaonGraph->GetX()[ip] < 0.15;
2628 if (removePoint) {
2629 kaonGraph->RemovePoint(ip);
2630 ip--;
2631 continue;
2632 }
2633 }
2634 //
2635 canvasQAmc->cd(4);
2636 histKaon->SetTitle("kaons");
2637 histKaon->GetYaxis()->SetRangeUser(30, 500);
2638 histKaon->GetXaxis()->SetTitle(momTitle.Data());
2639 histKaon->GetYaxis()->SetTitle(dEdxTitle.Data());
2640 histKaon->GetXaxis()->SetMoreLogLabels(kTRUE);
2641 histKaon->GetXaxis()->SetNoExponent(kTRUE);
2642 histKaon->Draw("colz");
2643 kaonPoints->SetMarkerStyle(20);
2644 kaonPoints->Draw("same");
2645
2646
2647
2648 hist->GetAxis(2)->SetRange(0,-1); // RESET RANGES
2649 hist->GetAxis(3)->SetRange(0,-1); // RESET RANGES
2650
2651
2652 // Clone graphs to have graphs with the same names as for the data case -> same subsequent functions can be used to determine
2653 // the correction functions and, finally, the response functions.
2654 // In addition: Remove some points, which are expected to deviate from the Bethe-Bloch curve, from the original graphs, so that
2655 // these graphs can be used for the BB fit
2656 TGraphErrors * graphPrCombined = new TGraphErrors(*protonGraph);
2657 graphPrCombined->SetMarkerStyle(22);
2658 graphPrCombined->SetMarkerColor(4);
2659 graphPrCombined->SetNameTitle("Graph_Protons_Combined", "Graph_Protons_Combined");
2660
2661 TGraphErrors * graphPiCombined = new TGraphErrors(*pionGraph);
2662 graphPiCombined->SetMarkerStyle(22);
2663 graphPiCombined->SetMarkerColor(3);
2664 graphPiCombined->SetNameTitle("Graph_Pions_Combined", "Graph_Pions_Combined");
2665
2666 TGraphErrors * graphKaCombined = new TGraphErrors(*kaonGraph);
2667 graphKaCombined->SetMarkerStyle(22);
2668 graphKaCombined->SetMarkerColor(5);
2669 graphKaCombined->SetNameTitle("Graph_Kaons_Combined", "Graph_Kaons_Combined");
2670
2671 TGraphErrors * graphElCombined = new TGraphErrors(*electronGraph);
2672 graphElCombined->SetMarkerStyle(22);
2673 graphElCombined->SetMarkerColor(2);
2674 graphElCombined->SetNameTitle("Graph_Electrons_Combined", "Graph_Electrons_Combined");
2675
2676 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
2677 Bool_t removePoint = electronGraph->GetX()[ip] < 2.5;// || electronGraph->GetX()[ip] > 5.0;
2678 //Bool_t removePoint = electronGraph->GetX()[ip] < 1.2 || electronGraph->GetX()[ip] > 5.0;
2679 if (removePoint) {
2680 electronGraph->RemovePoint(ip);
2681 ip--;
2682 continue;
2683 }
2684 }
2685
2686 for(Int_t ip = 0; ip < protonGraph->GetN(); ip ++) {
2687 Bool_t removePoint = protonGraph->GetX()[ip] < 0.9
2688 || protonGraph->GetX()[ip] > 2.5;//3.5; //TODO NEW in order not to get into conflict with pions/kaons
2689 if (removePoint) {
2690 protonGraph->RemovePoint(ip);
2691 ip--;
2692 continue;
2693 }
2694 }
2695
2696 for(Int_t ip = 0; ip < pionGraph->GetN(); ip ++) {
2697 Bool_t removePoint = pionGraph->GetX()[ip] < 2.1;//TODO APR18 0.8;
2698 if (removePoint) {
2699 pionGraph->RemovePoint(ip);
2700 ip--;
2701 continue;
2702 }
2703 }
2704
2705 for(Int_t ip = 0; ip < kaonGraph->GetN(); ip ++) {
2706 Bool_t removePoint = kaonGraph->GetX()[ip] < 1.25 || kaonGraph->GetX()[ip] > 4.0;// < 0.7;// || kaonGraph->GetX()[ip] > 4;
2707 if (removePoint) {
2708 kaonGraph->RemovePoint(ip);
2709 ip--;
2710 continue;
2711 }
2712 }
2713 //
2714 // rescale graphs to betaGamma
2715 //
2716 kaonGraph->SetMarkerStyle(22);
2717 for(Int_t ip = 0; ip < kaonGraph->GetN(); ip ++) {
2718 kaonGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2719 kaonGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2720 }
2721 for(Int_t ip = 0; ip < graphKaCombined->GetN(); ip ++) {
2722 graphKaCombined->GetX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2723 graphKaCombined->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2724 }
2725 //
2726 electronGraph->SetMarkerStyle(22);
2727 electronGraph->SetMarkerColor(2);
2728 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
2729 electronGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2730 electronGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2731 }
2732 for(Int_t ip = 0; ip < graphElCombined->GetN(); ip ++) {
2733 graphElCombined->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2734 graphElCombined->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2735 }
2736 //
2737 pionGraph->SetMarkerStyle(22);
2738 pionGraph->SetMarkerColor(3);
2739 for(Int_t ip = 0; ip < pionGraph->GetN(); ip ++) {
2740 pionGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2741 pionGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2742 }
2743 for(Int_t ip = 0; ip < graphPiCombined->GetN(); ip ++) {
2744 graphPiCombined->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2745 graphPiCombined->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2746 }
2747 //
2748 protonGraph->SetMarkerStyle(22);
2749 protonGraph->SetMarkerColor(4);
2750 for(Int_t ip = 0; ip < protonGraph->GetN(); ip ++) {
2751 protonGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2752 protonGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2753 }
2754 for(Int_t ip = 0; ip < graphPrCombined->GetN(); ip ++) {
2755 graphPrCombined->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2756 graphPrCombined->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2757 }
2758 //
2759 //
2760
2761 // Store graphs without further restriction
2762 TGraphErrors * graphPrAll = new TGraphErrors(*graphPrCombined);
2763 graphPrAll->SetNameTitle("Protons_MC_all", "Protons_MC_all");
2764
2765 TGraphErrors * graphPiAll = new TGraphErrors(*graphPiCombined);
2766 graphPiAll->SetNameTitle("Pions_MC_all", "Pions_MC_all");
2767
2768 TGraphErrors * graphKaAll = new TGraphErrors(*graphKaCombined);
2769 graphKaAll->SetNameTitle("Kaons_MC_all", "Kaons_MC_all");
2770
2771 TGraphErrors * graphElAll = new TGraphErrors(*graphElCombined);
2772 graphElAll->SetNameTitle("Electrons_MC_all", "Electrons_MC_all");
2773
2774 //
2775 //
2776 TGraphErrors * graphAll = new TGraphErrors();
2777 TList * listColl = new TList();
2778 listColl->Add(electronGraph);
2779 listColl->Add(protonGraph);
2780 listColl->Add(kaonGraph);
2781 listColl->Add(pionGraph);
2782 MergeGraphErrors(graphAll, listColl);
2783 graphAll->SetNameTitle("beamDataPoints","beamDataPoints");
2784
2785 //
2786 // return array with all graphs
2787 //
2788 TObjArray * arrGraphs = new TObjArray();
2789 arrGraphs->Add(graphAll);
2790 //
2791 arrGraphs->Add(electronGraph);
2792 arrGraphs->Add(pionGraph);
2793 arrGraphs->Add(kaonGraph);
2794 arrGraphs->Add(protonGraph);
2795 //
2796 arrGraphs->Add(graphElAll);
2797 arrGraphs->Add(graphPiAll);
2798 arrGraphs->Add(graphKaAll);
2799 arrGraphs->Add(graphPrAll);
2800 //
2801 arrGraphs->Add(graphElCombined);
2802 arrGraphs->Add(graphPiCombined);
2803 arrGraphs->Add(graphKaCombined);
2804 arrGraphs->Add(graphPrCombined);
2805 //
2806 //
2807
2808 canvasQAmc->SaveAs("splines_QA_ResidualGraphsTPC.root");
2809
2810 return arrGraphs;
2811
2812}
2813
2814
2815//________________________________________________________________________
2816TObjArray * AliTPCcalibResidualPID::GetResponseFunctions(TF1* parametrisation, TObjArray* inputGraphs, const Char_t * type, const Char_t * period, const Char_t * pass, const Char_t * system, const Char_t* dedxtype) {
2817 //
2818 //
2819
2820 Bool_t isMC = kFALSE;
2821 if (strcmp(type, "MC") == 0) {
2822 isMC = kTRUE;
2823 }
2824 else if (strcmp(type, "DATA") == 0) {
2825 isMC = kFALSE;
2826 }
2827 else {
2828 Printf("ERROR - GetResponseFunctions: Unknown type \"%s\" - must be \"MC\" or \"DATA\"!", type);
2829
2830 return 0x0;
2831 }
2832
2833 Bool_t isPbPb = kFALSE;
2834 Bool_t isPPb = kFALSE;
2835 if (strcmp(system, "PBPB") == 0) {
2836 Printf("PbPb detected - Applying special handling!");
2837 isPbPb = kTRUE;
2838 }
2839 else if (strcmp(system, "PPB") == 0 || strcmp(system, "PBP") == 0) {
2840 Printf("p-Pb/Pb-p detected - Applying special handling!");
2841 isPPb = kTRUE;
2842 }
2843
2844 TCanvas* canvasQA[4] = { 0x0, };
2845 for (Int_t i = 0; i < 4; i++) {
2846 canvasQA[i] = new TCanvas(Form("canvasQAres_%d", i), "Control canvas for residual polynomial",100,10,1380,800);
2847 canvasQA[i]->SetGrid(1, 1);
2848 canvasQA[i]->SetLogx();
2849 }
2850 /*
2851 TCanvas * canvasQA = new TCanvas("canvasQAres","Control canvas for residual polynomial",100,10,1380,800);
2852 canvasQA->Divide(2,2);
2853
2854 for (Int_t i = 1; i <= 4; i++) {
2855 canvasQA->GetPad(i)->SetGrid(1, 1);
2856 }
2857 */
2858 //
2859 // smallest needed (100MeV proton) bg = 0.1/0.938(=AliPID::ParticleMass(AliPID::kProton)) = 0.1,
2860 // largest needed 100 GeV electron, bg = 100/0.000511(=AliPID::ParticleMass(AliPID::kElectron)) = 200 000
2861 //
2862 Double_t from = 0.1;
2863 Double_t to = 200000;
2864
2865 TF1* funcBB = new TF1(*parametrisation);
2866 funcBB->SetLineColor(2);
2867 funcBB->SetLineWidth(1);
2868
2869 TString fitFuncString = "[0] + [1] / x + [2] / (x**2) + [3] / (x**3) + [4] / (x**4) + [5] / (x**5) + [6] * x";
2870 TString fitFuncString2 = "pol6";
2871 //
2872 // 1. extract proton corrections
2873 //
2874 TGraphErrors * graphProtonTPC = (TGraphErrors *) inputGraphs->FindObject("Graph_Protons_Combined");
2875 TGraphErrors * graphProtonTPCfinal = new TGraphErrors(*graphProtonTPC);
2876 graphProtonTPCfinal->SetName("graphProtonTPCfinal");
2877 for(Int_t ip = 0; ip < graphProtonTPC->GetN(); ip ++) {
2878 graphProtonTPC->GetY()[ip] -= funcBB->Eval(graphProtonTPC->GetX()[ip]);
2879 graphProtonTPC->GetY()[ip] /= funcBB->Eval(graphProtonTPC->GetX()[ip]);
2880 graphProtonTPC->GetEY()[ip] /= funcBB->Eval(graphProtonTPC->GetX()[ip]);;
2881 }
2882 canvasQA[0]->cd();
2883 //canvasQA->cd(1);
2884 //gPad->SetLogx();
2885 graphProtonTPC->GetXaxis()->SetTitle("#beta#gamma");
2886 graphProtonTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
2887 graphProtonTPC->GetXaxis()->SetNoExponent(kTRUE);
2888 graphProtonTPC->GetYaxis()->SetLabelSize(0.04);
2889 graphProtonTPC->GetYaxis()->SetTitleOffset(0.85);
2890 graphProtonTPC->GetXaxis()->SetTitleOffset(1.0);
2891 graphProtonTPC->GetYaxis()->SetTitle("(data - fit) / fit");
2892 graphProtonTPC->Draw("ap");
2893
2894 if (graphProtonTPC->GetN() <= 0) {
2895 Printf("ERROR - GetResponseFunctions: Proton graph has no data points!");
2896
2897 return 0x0;
2898 }
2899 graphProtonTPC->Sort(); // Sort points along x. Next, the very first point will be used to determine the starting point of the correction function
2900 TF1 * funcCorrProton = new TF1("funcCorrProton", fitFuncString2.Data(), TMath::Max(graphProtonTPC->GetX()[0], 0.15),1.0); // TODO BEN was 0.18 - 0.85
2901 graphProtonTPC->Fit(funcCorrProton, "QREX0M");
2902 //
2903 // 2. extract kaon corrections
2904 //
2905 TGraphErrors * graphKaonTPC = (TGraphErrors *) inputGraphs->FindObject("Graph_Kaons_Combined");
2906 TGraphErrors * graphKaonTPCfinal = new TGraphErrors(*graphKaonTPC);
2907 graphKaonTPCfinal->SetName("graphKaonTPCfinal");
2908 for(Int_t ip = 0; ip < graphKaonTPC->GetN(); ip ++) {
2909 graphKaonTPC->GetY()[ip] -= funcBB->Eval(graphKaonTPC->GetX()[ip]);
2910 graphKaonTPC->GetY()[ip] /= funcBB->Eval(graphKaonTPC->GetX()[ip]);
2911 graphKaonTPC->GetEY()[ip] /= funcBB->Eval(graphKaonTPC->GetX()[ip]);;
2912 }
2913 canvasQA[1]->cd();
2914 //canvasQA->cd(2);
2915 //gPad->SetLogx();
2916 graphKaonTPC->GetXaxis()->SetTitle("#beta#gamma");
2917 graphKaonTPC->GetYaxis()->SetTitle("(data - fit) / fit");
2918 graphKaonTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
2919 graphKaonTPC->GetXaxis()->SetNoExponent(kTRUE);
2920 graphKaonTPC->GetYaxis()->SetLabelSize(0.04);
2921 graphKaonTPC->GetYaxis()->SetTitleOffset(0.85);
2922 graphKaonTPC->GetXaxis()->SetTitleOffset(1.0);
2923 graphKaonTPC->Draw("ap");
2924
2925 if (graphKaonTPC->GetN() <= 0) {
2926 Printf("ERROR - GetResponseFunctions: Kaon graph has no data points!");
2927
2928 return 0x0;
2929 }
2930 graphKaonTPC->Sort(); // Sort points along x. Next, the very first point will be used to determine the starting point of the correction function
2931
2932 TF1 * funcCorrKaon = 0x0;
2933
2934 if (isMC) {
2935 funcCorrKaon = new TF1("funcCorrKaon", fitFuncString.Data(), TMath::Max(graphKaonTPC->GetX()[0], 0.25), isPPb ? 3.44 : 1.981);
2936 graphKaonTPC->Fit(funcCorrKaon, "QREX0M");
2937 }
2938 else {
2939 // In case of data there are sometimes problems to fit the shape with one function (could describe the overall deviation,
2940 // but will not cover all the details).
2941 // Nevertheless, this shape (including most of the "details") can be fitted with the following approach with two functions
2942 TF1 * funcCorrKaon1 = new TF1("funcCorrKaon1", fitFuncString.Data(),
2943 TMath::Max(graphKaonTPC->GetX()[0], 0.25), 1.981);
2944 graphKaonTPC->Fit(funcCorrKaon1, "QREX0M", "same", TMath::Max(graphKaonTPC->GetX()[0], 0.25), 1.0);
2945
2946 TF1 * funcCorrKaon2 = new TF1("funcCorrKaon2", fitFuncString2.Data(), TMath::Max(graphKaonTPC->GetX()[0], 0.25), 1.981);
2947 graphKaonTPC->Fit(funcCorrKaon2, "QREX0M", "same", (isMC ? 1.981 : 1.0), 1.981);
2948
2949 funcCorrKaon = new TF1("funcCorrKaon",
2950 "funcCorrKaon1 * 0.5*(1.+TMath::Erf((1 - x) / 0.1)) + ([0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x+[5]*x*x*x*x*x+[6]*x*x*x*x*x*x) * 0.5*(1.+TMath::Erf((x - 1) / 0.1))",
2951 TMath::Max(graphKaonTPC->GetX()[0], 0.25), 1.981);
2952
2953 for (Int_t i = funcCorrKaon1->GetNpar(), j = 0; i < funcCorrKaon1->GetNpar() + funcCorrKaon2->GetNpar(); i++, j++) {
2954 funcCorrKaon->SetParameter(j, funcCorrKaon2->GetParameter(j));
2955 }
2956 funcCorrKaon->SetLineColor(kRed);
2957 funcCorrKaon->GetHistogram()->DrawClone("csame");
2958 //funcCorrKaon->Draw("same");
2959 }
2960 /*TODO
2961 TF1 * funcCorrKaon = new TF1("funcCorrKaon", fitFuncString.Data(),//TODO BEN was fitFuncString2
2962 TMath::Max(graphKaonTPC->GetX()[0], 0.25), (isMC ? 1.981 : 1.0)); //TODO BEN was 0.79 for data and 1.45 for MC
2963 graphKaonTPC->Fit(funcCorrKaon, "QREX0M");
2964 */
2965 //
2966 // 3. extract pion corrections
2967 //
2968 TGraphErrors * graphPionTPC = (TGraphErrors *) inputGraphs->FindObject("Graph_Pions_Combined");
2969 TGraphErrors * graphPionTPCfinal = new TGraphErrors(*graphPionTPC);
2970 graphPionTPCfinal->SetName("graphPionTPCfinal");
2971 for(Int_t ip = 0; ip < graphPionTPC->GetN(); ip ++) {
2972 graphPionTPC->GetY()[ip] -= funcBB->Eval(graphPionTPC->GetX()[ip]);
2973 graphPionTPC->GetY()[ip] /= funcBB->Eval(graphPionTPC->GetX()[ip]);
2974 graphPionTPC->GetEY()[ip] /= funcBB->Eval(graphPionTPC->GetX()[ip]);
2975 }
2976 canvasQA[2]->cd();
2977 //canvasQA->cd(3);
2978 //gPad->SetLogx();
2979 graphPionTPC->GetXaxis()->SetTitle("#beta#gamma");
2980 graphPionTPC->GetYaxis()->SetTitle("(data - fit) / fit");
2981 graphPionTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
2982 graphPionTPC->GetXaxis()->SetNoExponent(kTRUE);
2983 graphPionTPC->GetYaxis()->SetLabelSize(0.04);
2984 graphPionTPC->GetYaxis()->SetTitleOffset(0.85);
2985 graphPionTPC->GetXaxis()->SetTitleOffset(1.0);
2986 graphPionTPC->Draw("ap");
2987
2988 if (graphPionTPC->GetN() <= 0) {
2989 Printf("ERROR - GetResponseFunctions: Pion graph has no data points!");
2990
2991 return 0x0;
2992 }
2993 graphPionTPC->Sort(); // Sort points along x. Next, the very first point will be used to determine the starting point of the correction function
2994 // In case of PbPb (data, not MC) only correct down to 0.2 GeV/c; otherwise: contamination due to electrons
2995 TF1 * funcCorrPion = new TF1("funcCorrPion", fitFuncString.Data(), ((isPbPb && !isMC) ? (0.2 / AliPID::ParticleMass(AliPID::kPion)) : graphPionTPC->GetX()[0]), isMC ? (isPPb ? 12.8 : (isPbPb ? 12.8 : 7.1)) : (isPPb ? 7.68 : 7.1));
2996 graphPionTPC->Fit(funcCorrPion, "QREX0M");
2997 //
2998 // 4. extract electron corrections
2999 //
3000 TGraphErrors * graphElectronTPC = (TGraphErrors *) inputGraphs->FindObject("Graph_Electrons_Combined");
3001 TGraphErrors * graphElectronTPCfinal = new TGraphErrors(*graphElectronTPC);
3002 graphElectronTPCfinal->SetName("graphElectronTPCfinal");
3003 for(Int_t ip = 0; ip < graphElectronTPC->GetN(); ip ++) {
3004 graphElectronTPC->GetY()[ip] -= funcBB->Eval(graphElectronTPC->GetX()[ip]);
3005 graphElectronTPC->GetY()[ip] /= funcBB->Eval(graphElectronTPC->GetX()[ip]);
3006 graphElectronTPC->GetEY()[ip] /= funcBB->Eval(graphElectronTPC->GetX()[ip]);;
3007 }
3008 canvasQA[3]->cd();
3009 //canvasQA->cd(4);
3010 //gPad->SetLogx();
3011 graphElectronTPC->GetXaxis()->SetTitle("#beta#gamma");
3012 graphElectronTPC->GetYaxis()->SetTitle("(data - fit) / fit");
3013 graphElectronTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
3014 graphElectronTPC->GetXaxis()->SetNoExponent(kTRUE);
3015 graphElectronTPC->GetYaxis()->SetLabelSize(0.04);
3016 graphElectronTPC->GetYaxis()->SetTitleOffset(0.85);
3017 graphElectronTPC->GetXaxis()->SetTitleOffset(1.0);
3018 graphElectronTPC->Draw("ap");
3019
3020 if (graphElectronTPC->GetN() <= 0) {
3021 Printf("ERROR - GetResponseFunctions: Electron graph has no data points!");
3022
3023 return 0x0;
3024 }
3025 graphElectronTPC->Sort(); // Sort points along x. Next, the very first point will be used to determine the starting point of the correction function
3026 // In case of PbPb (data, not MC) only correct down to 0.2 GeV/c; otherwise: contamination due to pions
3027 TF1 * funcCorrElectron = new TF1("funcCorrElectron", fitFuncString.Data(), (!isMC && isPbPb ? (0.2 / AliPID::ParticleMass(AliPID::kElectron)) :graphElectronTPC->GetX()[0]), (isMC ? 3565 : (isPPb ? 2900 : 1920/*970*/)));// TODO was 1800 for pp data
3028 // NOTE: For data, the results are almost the same for fitFuncString and fitFuncString2. Maybe, fitFuncString2 is slightly better.
3029 graphElectronTPC->Fit(funcCorrElectron, "QREX0M");
3030 //
3031 // EXTRACT GRAPHS AND PUT THEM TO THE TOBJARRAY
3032 //
3033 const Int_t nBins = 500;
3034 Double_t xBetaGamma[nBins];
3035 Double_t yProton[nBins];
3036 Double_t yKaon[nBins];
3037 Double_t yPion[nBins];
3038 Double_t yElectron[nBins];
3039 Double_t yDefault[nBins];
3040 //
3041 //
3042 //
3043 xBetaGamma[0] = from;
3044 Double_t factor = pow(to/from, 1./nBins);
3045
3046 //
3047 for(Int_t kk = 0; kk < nBins; kk++) {
3048 if (kk > 0) xBetaGamma[kk] = factor * xBetaGamma[kk-1];
3049 yProton[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
3050 yPion[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
3051 yKaon[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
3052 yElectron[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
3053 yDefault[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
3054
3055 // Added by Ben
3056 Double_t widthFactor = 0.020;
3057 Double_t smoothProton = 0.5*(TMath::Erf((funcCorrProton->GetXmax()-xBetaGamma[kk])*AliPID::ParticleMass(AliPID::kProton)/widthFactor) + 1);
3058 Double_t smoothKaon = 0.5*(TMath::Erf((funcCorrKaon->GetXmax()-xBetaGamma[kk])*AliPID::ParticleMass(AliPID::kKaon)/widthFactor) + 1);
3059 Double_t smoothPion = 0.5*(TMath::Erf((funcCorrPion->GetXmax()-xBetaGamma[kk])*AliPID::ParticleMass(AliPID::kPion)/widthFactor) + 1);
3060 Double_t smoothElectron = 0.5*(TMath::Erf((funcCorrElectron->GetXmax()-xBetaGamma[kk])*AliPID::ParticleMass(AliPID::kElectron)/widthFactor) + 1);
3061
3062 if (xBetaGamma[kk] > funcCorrProton->GetXmax())
3063 yProton[kk] *= (1 + smoothProton*funcCorrProton->Eval(funcCorrProton->GetXmax()));
3064 // Correction is so large that one runs into trouble at low bg for Protons.
3065 // The deviation is smaller if one takes the lower bound of the correction function
3066 else if (xBetaGamma[kk] < funcCorrProton->GetXmin())
3067 yProton[kk] *= (1 + smoothProton*funcCorrProton->Eval(funcCorrProton->GetXmin()));
3068 else
3069 yProton[kk] *= (1 + smoothProton*funcCorrProton->Eval(xBetaGamma[kk]));
3070
3071 if (xBetaGamma[kk] > funcCorrKaon->GetXmax())
3072 yKaon[kk] *= (1 + smoothKaon*funcCorrKaon->Eval(funcCorrKaon->GetXmax()));
3073 // Correction is so large that one runs into trouble at low bg for Kaons.
3074 // The deviation is smaller if one takes the lower bound of the correction function
3075 else if (xBetaGamma[kk] < funcCorrKaon->GetXmin())
3076 yKaon[kk] *= (1 + smoothKaon*funcCorrKaon->Eval(funcCorrKaon->GetXmin()));
3077 else
3078 yKaon[kk] *= (1 + smoothKaon*funcCorrKaon->Eval(xBetaGamma[kk]));
3079
3080 if (xBetaGamma[kk] > funcCorrElectron->GetXmax())
3081 yElectron[kk] *= (1 + smoothElectron*funcCorrElectron->Eval(funcCorrElectron->GetXmax()));
3082 else if (xBetaGamma[kk] < funcCorrElectron->GetXmin())
3083 yElectron[kk] *= (1 + smoothElectron*funcCorrElectron->Eval(funcCorrElectron->GetXmin()));
3084 else
3085 yElectron[kk] *= (1 + smoothElectron*funcCorrElectron->Eval(xBetaGamma[kk]));
3086
3087 // Only true for LHC10d.pass?: Seems not to be needed because any (very small) deviations are most likely due to electron contamination(BEN)
3088 if (xBetaGamma[kk] > funcCorrPion->GetXmax())
3089 yPion[kk] *= (1 + smoothPion*funcCorrPion->Eval(funcCorrPion->GetXmax()));
3090 else if (xBetaGamma[kk] < funcCorrPion->GetXmin())
3091 yPion[kk] *= (1 + smoothPion*funcCorrPion->Eval(funcCorrPion->GetXmin()));
3092 else
3093 yPion[kk] *= (1 + smoothPion*funcCorrPion->Eval(xBetaGamma[kk]));
3094
3095
3096 /* Removed by Ben
3097 Double_t smoothProton = 0.5*(TMath::Erf((funcCorrProton->GetXmax()-xBetaGamma[kk])/0.002) + 1);
3098 Double_t smoothKaon = 0.5*(TMath::Erf((funcCorrKaon->GetXmax()-xBetaGamma[kk])/0.002) + 1);
3099 Double_t smoothPion = 0.5*(TMath::Erf((funcCorrPion->GetXmax()-xBetaGamma[kk])/0.002) + 1);
3100
3101 if (xBetaGamma[kk] < funcCorrProton->GetXmax() && xBetaGamma[kk] > funcCorrProton->GetXmin()) yProton[kk] *= (1 + smoothProton*funcCorrProton->Eval(xBetaGamma[kk]));
3102 if (xBetaGamma[kk] < funcCorrKaon->GetXmax() && xBetaGamma[kk] > funcCorrKaon->GetXmin()) yKaon[kk] *= (1 + smoothKaon*funcCorrKaon->Eval(xBetaGamma[kk]));
3103 if (xBetaGamma[kk] < funcCorrPion->GetXmax() && xBetaGamma[kk] > funcCorrPion->GetXmin()) yPion[kk] *= (1 + smoothPion*funcCorrPion->Eval(xBetaGamma[kk]));
3104 //if (xBetaGamma[kk] < funcCorrElectron->GetXmax()) yElectron[kk] *= (1 + funcCorrElectron->Eval(xBetaGamma[kk]));
3105 //
3106 if (xBetaGamma[kk] < funcCorrProton->GetXmin()) yProton[kk] *= (1 + funcCorrProton->Eval(funcCorrProton->GetXmin()));
3107 if (xBetaGamma[kk] < funcCorrKaon->GetXmin()) yKaon[kk] *= (1 + funcCorrKaon->Eval(funcCorrKaon->GetXmin()));
3108 if (xBetaGamma[kk] < funcCorrPion->GetXmin()) yPion[kk] *= (1 + funcCorrPion->Eval(funcCorrPion->GetXmin()));
3109 */
3110 }
3111 //
3112 TGraph * graphProton = new TGraph(nBins, xBetaGamma, yProton);
3113 TGraph * graphElectron = new TGraph(nBins, xBetaGamma, yElectron);
3114 TGraph * graphKaon = new TGraph(nBins, xBetaGamma, yKaon);
3115 TGraph * graphPion = new TGraph(nBins, xBetaGamma, yPion);
3116 TGraph * graphDefault = new TGraph(nBins, xBetaGamma, yDefault);
3117 //
3118 //
3119 TSpline3 * splineProton = new TSpline3("splineProton", graphProton);
3120 TSpline3 * splineElectron = new TSpline3("splineElectron", graphElectron);
3121 TSpline3 * splineKaon = new TSpline3("splineKaon", graphKaon);
3122 TSpline3 * splinePion = new TSpline3("splinePion", graphPion);
3123 TSpline3 * splineDefault = new TSpline3("splineDefault", graphDefault);
3124 //
3125 //
3126 splineProton->SetNameTitle(Form("TSPLINE3_%s_PROTON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
3127 Form("TSPLINE3_%s_PROTON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
3128 splineElectron->SetNameTitle(Form("TSPLINE3_%s_ELECTRON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
3129 Form("TSPLINE3_%s_ELECTRON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
3130 splineKaon->SetNameTitle(Form("TSPLINE3_%s_KAON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
3131 Form("TSPLINE3_%s_KAON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
3132 splinePion->SetNameTitle(Form("TSPLINE3_%s_PION_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
3133 Form("TSPLINE3_%s_PION_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
3134 splineDefault->SetNameTitle(Form("TSPLINE3_%s_ALL_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
3135 Form("TSPLINE3_%s_ALL_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
3136 //
3137 TObjArray * arrResponse = new TObjArray();
3138 arrResponse->SetName("TPCpidResponseFunctions");
3139 arrResponse->AddLast(splineProton);
3140 arrResponse->AddLast(splineElectron);
3141 arrResponse->AddLast(splineKaon);
3142 arrResponse->AddLast(splinePion);
3143 arrResponse->AddLast(splineDefault);
3144 //
3145
3146 // Draw deviation from final results
3147 for(Int_t ip = 0; ip < graphProtonTPCfinal->GetN(); ip ++) {
3148 graphProtonTPCfinal->GetY()[ip] -= 50. * splineProton->Eval(graphProtonTPCfinal->GetX()[ip]);
3149 graphProtonTPCfinal->GetY()[ip] /= 50. * splineProton->Eval(graphProtonTPCfinal->GetX()[ip]);
3150 graphProtonTPCfinal->GetEY()[ip] /= 50. * splineProton->Eval(graphProtonTPCfinal->GetX()[ip]);;
3151 }
3152 canvasQA[0]->cd();
3153 //canvasQA->cd(1);
3154 graphProtonTPCfinal->SetMarkerStyle(26);
3155 graphProtonTPCfinal->Draw("psame");
3156
3157 for(Int_t ip = 0; ip < graphKaonTPCfinal->GetN(); ip ++) {
3158 graphKaonTPCfinal->GetY()[ip] -= 50. * splineKaon->Eval(graphKaonTPCfinal->GetX()[ip]);
3159 graphKaonTPCfinal->GetY()[ip] /= 50. * splineKaon->Eval(graphKaonTPCfinal->GetX()[ip]);
3160 graphKaonTPCfinal->GetEY()[ip] /= 50. * splineKaon->Eval(graphKaonTPCfinal->GetX()[ip]);;
3161 }
3162 canvasQA[1]->cd();
3163 //canvasQA->cd(2);
3164 graphKaonTPCfinal->SetMarkerStyle(26);
3165 graphKaonTPCfinal->Draw("psame");
3166
3167 for(Int_t ip = 0; ip < graphPionTPCfinal->GetN(); ip ++) {
3168 graphPionTPCfinal->GetY()[ip] -= 50. * splinePion->Eval(graphPionTPCfinal->GetX()[ip]);
3169 graphPionTPCfinal->GetY()[ip] /= 50. * splinePion->Eval(graphPionTPCfinal->GetX()[ip]);
3170 graphPionTPCfinal->GetEY()[ip] /= 50. * splinePion->Eval(graphPionTPCfinal->GetX()[ip]);;
3171 }
3172 canvasQA[2]->cd();
3173 //canvasQA->cd(3);
3174 graphPionTPCfinal->SetMarkerStyle(26);
3175 graphPionTPCfinal->Draw("psame");
3176
3177 for(Int_t ip = 0; ip < graphElectronTPCfinal->GetN(); ip ++) {
3178 graphElectronTPCfinal->GetY()[ip] -= 50. * splineElectron->Eval(graphElectronTPCfinal->GetX()[ip]);
3179 graphElectronTPCfinal->GetY()[ip] /= 50. * splineElectron->Eval(graphElectronTPCfinal->GetX()[ip]);
3180 graphElectronTPCfinal->GetEY()[ip] /= 50. * splineElectron->Eval(graphElectronTPCfinal->GetX()[ip]);;
3181 }
3182 canvasQA[3]->cd();
3183 //canvasQA->cd(4);
3184 graphElectronTPCfinal->SetMarkerStyle(26);
3185 graphElectronTPCfinal->Draw("psame");
3186
3187 TFile* fSave = TFile::Open("splines_QA_ResidualPolynomials.root", "RECREATE");
3188 fSave->cd();
3189 for (Int_t i = 0; i < 4; i++)
3190 canvasQA[i]->Write();
3191
3192 fSave->Close();
3193 //canvasQA->SaveAs("splines_QA_ResidualPolynomials.root");
3194
3195
3196 delete funcBB;
3197
3198 return arrResponse;
3199}
3200
3201
3202//________________________________________________________________________
3203TF1* AliTPCcalibResidualPID::FitBB(TObjArray* inputGraphs, Bool_t isMC, Bool_t isPPb, const Bool_t useV0s,
3204 const Double_t * initialParameters, AliTPCcalibResidualPID::FitType fitType) {
3205 //
3206 // Fit Bethe-Bloch parametrisation to data points (inputGraphs)
3207 //
3208 const Int_t nPar = 6;
3209 TGraphErrors * graphAll = (TGraphErrors *) inputGraphs->FindObject("beamDataPoints");
3210 //
3211 Float_t from = 0.9; //TODO ADJUST -> Very important
3212 Float_t to = graphAll->GetXaxis()->GetXmax() * 2;
3213
3214
3215
3216 TF1* funcBB = 0x0;
3217
3218 Double_t parametersBBForward[nPar] = { 0, };
3219
3220 TVirtualFitter::SetMaxIterations(5e6);
3221
3222 if (fitType == AliTPCcalibResidualPID::kSaturatedLund) {
3223 printf("Fit function: Saturated Lund\n");
3224
3225 funcBB = new TF1("SaturatedLund", SaturatedLund, from, to, nPar);
3226 //Double_t parametersBB[nPar] = {34.0446, 8.42221, 4.16724, 1.29473, 80.6663, 0}; //Xianguos values
3227 //Double_t parametersBB[nPar] = {35.5, 8.7, 2.0, 1.09, 75.6, 0}; // No saturation
3228 Double_t parametersBB[nPar] = {61.0, 8.7, 1.86, 0.85, 113.4, -38}; // Yields reasonable results for data and MC ~ all periods
3229
3230 if (isPPb && !isMC) {
3231 parametersBB[0] = 51.6;
3232 parametersBB[1] = 9.7;
3233 parametersBB[2] = 1.62;
3234 parametersBB[3] = 0.99;
3235 parametersBB[4] = 104.4;
3236 parametersBB[5] = -27.0;
3237 }
3238 if (isMC) {
3239 parametersBB[0] = 41.4;
3240 parametersBB[1] = 8.6;
3241 parametersBB[2] = 2.2;
3242 parametersBB[3] = 0.92;
3243 parametersBB[4] = 90.4;
3244 parametersBB[5] = -20.0;
3245 }
3246 funcBB->SetParameters(parametersBB);
3247
3248 Double_t parameterErrorsBB[nPar] = {5., 0.5, 0.2, 0.05, 10, 10};
3249 funcBB->SetParErrors(parameterErrorsBB);
3250
3251 for (Int_t i = 0; i < nPar; i++)
3252 parametersBBForward[i] = parametersBB[i];
3253 }
3254 else if (fitType == AliTPCcalibResidualPID::kLund) {
3255 printf("Fit function: Lund\n");
3256 printf("****WARNING: Fit settings not tuned for this fit function, only for saturated Lund!\n");
3257
3258 funcBB = new TF1("SaturatedLund", SaturatedLund, from, to, nPar);
3259 //Double_t parametersBB[nPar] = {34.0446, 8.42221, 4.16724, 1.29473, 80.6663, 0}; //Xianguos values
3260 //Double_t parametersBB[nPar] = {35.5, 8.7, 2.0, 1.09, 75.6, 0}; // No saturation
3261 Double_t parametersBB[nPar] = {35.0, 7., 1.86, 1., 75., 0}; // Yields reasonable results for data and MC ~ all periods
3262
3263 funcBB->SetParameters(parametersBB);
3264
3265 Double_t parameterErrorsBB[nPar] = {5., 0.5, 0.2, 0.05, 10, 10};
3266 funcBB->SetParErrors(parameterErrorsBB);
3267
3268 funcBB->FixParameter(5, 0.0); // No saturation
3269
3270 for (Int_t i = 0; i < nPar; i++)
3271 parametersBBForward[i] = parametersBB[i];
3272 }
3273 else if (fitType == kAlephWithAdditionalParam) {
3274 printf("Fit function: Aleph with additional parameter\n");
3275 printf("****WARNING: Fit settings not tuned for this fit function, only for saturated Lund!\n");
3276
3277 // NOTE: This form is equivalent to the original form, but with parameter [2] redefined for better numerical stability.
3278 // The additional parameter [5] has been introduced later and is unity originally. It seems not to be needed and is, thus,
3279 // fixed to unity
3280 funcBB = new TF1("funcAleph",
3281 "[0]/TMath::Power(TMath::Sqrt(1. + x*x)/x , [3])*([1]-[2]-[5]*TMath::Power(TMath::Sqrt(1. + x*x)/x , [3])-TMath::Log(1. + TMath::Power(x, -[4])*TMath::Exp(-[2])))", from, to);
3282 //OLD"[0]*([1]*TMath::Power(TMath::Sqrt(1 + x*x)/x , [3]) - [5] - TMath::Power(TMath::Sqrt(1 + x*x)/x , [3])*TMath::Log(TMath::Exp([2]) + 1/TMath::Power(x, [4])))", from, to);
3283
3284 Double_t parametersBB[nPar] = {2.6,14.3,-15,2.2,2.7, 0.06};
3285 //OLD with different sign for [3]: Double_t parametersBB[nPar] = {0.0762*50.3,10.632,TMath::Log(1.34e-05),1.863,1.948, 1};
3286 funcBB->SetParameters(parametersBB);
3287
3288 for (Int_t i = 0; i < nPar; i++)
3289 parametersBBForward[i] = parametersBB[i];
3290 }
3291 else if (fitType == AliTPCcalibResidualPID::kAleph) {
3292 printf("Fit function: Aleph\n");
3293 printf("****WARNING: Fit settings not tuned for this fit function, only for saturated Lund!\n");
3294
3295 // NOTE: This form is equivalent to the original form, but with parameter [2] redefined for better numerical stability.
3296 // The additional parameter [5] has been introduced later and is unity originally. It seems not to be needed and is, thus,
3297 // fixed to unity
3298 funcBB = new TF1("funcAleph",
3299 "[0]/TMath::Power(x/TMath::Sqrt(1. + x*x) , [3])*([1]-[2]-[5]*TMath::Power(x/TMath::Sqrt(1. + x*x) , [3])-TMath::Log(1. + TMath::Power(x, -[4])*TMath::Exp(-[2])))", from, to);
3300 //OLD"[0]*([1]*TMath::Power(TMath::Sqrt(1 + x*x)/x , [3]) - [5] - TMath::Power(TMath::Sqrt(1 + x*x)/x , [3])*TMath::Log(TMath::Exp([2]) + 1/TMath::Power(x, [4])))", from, to);
3301 //TEST Double_t parametersBB[nPar] = {1.2, 26.0, -30.0, -2.15, 5.6, 1};
3302 Double_t parametersBB[nPar] = {1.25, 27.5, -29.0, 2.2, 5.2, 1};
3303
3304 // For [5] floating: Double_t parametersBB[nPar] = {2.42,15.2,-16,-2.24,2.8, 0.057};
3305 //OLD with different sign for [3] and [5] not fix: Double_t parametersBB[nPar] = {2.6,14.3,-15,2.2,2.7, 0.06};
3306 //OLD with different sign for [3]: Double_t parametersBB[nPar] = {0.0762*50.3,10.632,TMath::Log(1.34e-05),1.863,1.948, 1};
3307 funcBB->SetParameters(parametersBB);
3308
3309 // Fix parameter 5 to original value of unity
3310 funcBB->FixParameter(5, 1);
3311
3312 for (Int_t i = 0; i < nPar; i++)
3313 parametersBBForward[i] = parametersBB[i];
3314 }
3315 else {
3316 printf("Error: fitType not supported!\n");
3317 return 0x0;
3318 }
3319
3320 funcBB->SetLineColor(2);
3321 funcBB->SetLineWidth(1);
3322
3323 // Override initial parameters, if user provides some
3324 if (initialParameters) {
3325 printf("Setting user initial parameters!\n");
3326 funcBB->SetParameters(initialParameters);
3327 }
3328
3329 //
3330 //
3331 //
3332 TGraphErrors * graphDelta = new TGraphErrors(*graphAll);
3333 graphDelta->SetName("graphDelta");
3334
3335 // In MC case: Remove errors from fit -> Some data points with extremely small errors otherwise completely dominate the fit,
3336 // but these points could still be wrong due to systematics (low p effects, e.g.)
3337 if (isMC) {
3338 for(Int_t ip = 0; ip < graphAll->GetN(); ip++) {
3339 graphAll->SetPointError(ip, 0, 0);
3340 }
3341 }
3342 else if (useV0s) {
3343 // Increase weight in plateau by reducing errors. Neccessary because errors are large there compared to other data points
3344 for(Int_t ip = 0; ip < graphAll->GetN(); ip++) {
3345 if (graphAll->GetX()[ip] >= 2500) {
3346 graphAll->SetPointError(ip, 0, graphAll->GetEY()[ip] / 6.0);
3347 }
3348 // Same for pions in the very rel. rise
3349 if (graphAll->GetX()[ip] >= 25 && graphAll->GetX()[ip] < 1000) {
3350 graphAll->SetPointError(ip, 0, graphAll->GetEY()[ip] / 6.0);
3351 }
3352 // Same for protons in the MIP region
3353 if (graphAll->GetX()[ip] >= 2 && graphAll->GetX()[ip] < 4) {
3354 graphAll->SetPointError(ip, 0, graphAll->GetEY()[ip] / 6.0);
3355 }
3356 }
3357 }
3358 graphAll->Fit(funcBB, "REX0M");
3359 funcBB->SetRange(from, to);
3360 funcBB->GetParameters(parametersBBForward);
3361 //
3362 //
3363 //
3364 for(Int_t ip = 0; ip < graphDelta->GetN(); ip++) {
3365 graphDelta->GetY()[ip] -= funcBB->Eval(graphDelta->GetX()[ip]);
3366 graphDelta->GetY()[ip] /= funcBB->Eval(graphDelta->GetX()[ip]);
3367 graphDelta->GetEY()[ip] /= funcBB->Eval(graphDelta->GetX()[ip]);
3368 }
3369 TCanvas * canvDelta_1 = new TCanvas("canvDelta_1","control histogram for Bethe-Bloch fit 1",100,10,1380,800);
3370 TCanvas * canvDelta_2 = new TCanvas("canvDelta_2","control histogram for Bethe-Bloch fit 2",100,10,1380,800);
3371 canvDelta_1->SetGrid(1, 1);
3372 canvDelta_1->SetLogx();
3373 canvDelta_2->SetGrid(1, 1);
3374 canvDelta_2->SetLogx();
3375 /*
3376 canvDelta->Divide(2, 1);
3377 canvDelta->GetPad(1)->SetGrid(1, 1);
3378 canvDelta->GetPad(1)->SetLogx();
3379 canvDelta->GetPad(2)->SetGrid(1, 1);
3380 canvDelta->GetPad(2)->SetLogx();
3381 */
3382
3383 canvDelta_1->cd();
3384 //canvDelta->cd(1);
3385 TH1F *hBBdummy=new TH1F("hBBdummy","BB fit;#beta#gamma;#LTdE/dx#GT (arb. unit)",100,.8,1e4);
3386 hBBdummy->SetMinimum(45);
3387 hBBdummy->SetMaximum(120);
3388 hBBdummy->GetXaxis()->SetTitleOffset(1.1);
3389 hBBdummy->SetStats(kFALSE);
3390 hBBdummy->Draw();
3391
3392 graphAll->SetTitle("BB multi-graph fit");
3393 graphAll->SetMarkerStyle(22);
3394 graphAll->SetMarkerColor(kMagenta);
3395 graphAll->Draw("p");
3396
3397 TLegend *leg=new TLegend(.7,.12,.89,isMC?.4:.6);
3398 leg->SetFillColor(10);
3399 leg->SetBorderSize(1);
3400
3401 //overlay individual graphs
3402 TGraph *gr=0x0;
3403 if (isMC) {
3404 gr=(TGraph*)inputGraphs->FindObject("Protons_MC_all");
3405 gr->SetMarkerColor(kRed);
3406 gr->SetMarkerStyle(24);
3407 gr->Draw("p");
3408 leg->AddEntry(gr,"p (MC)","p");
3409 gr=(TGraph*)inputGraphs->FindObject("Pions_MC_all");
3410 gr->SetMarkerColor(kBlue);
3411 gr->SetMarkerStyle(24);
3412 gr->Draw("p");
3413 leg->AddEntry(gr,"#pi (MC)","p");
3414 gr=(TGraph*)inputGraphs->FindObject("Kaons_MC_all");
3415 gr->SetMarkerColor(kGreen);
3416 gr->SetMarkerStyle(24);
3417 gr->Draw("p");
3418 leg->AddEntry(gr,"K (MC)","p");
3419 gr=(TGraph*)inputGraphs->FindObject("Electrons_MC_all");
3420 gr->SetMarkerColor(kBlack);
3421 gr->SetMarkerStyle(24);
3422 gr->Draw("p");
3423 leg->AddEntry(gr,"e (MC)","p");
3424 }
3425 else {
3426 gr=(TGraph*)inputGraphs->FindObject("protonTpcGraph");
3427 gr->SetMarkerColor(kRed);
3428 gr->SetMarkerStyle(26);
3429 gr->Draw("p");
3430 leg->AddEntry(gr,"p (TPC)","p");
3431 gr=(TGraph*)inputGraphs->FindObject("protonTofGraph");
3432 gr->SetMarkerColor(kRed);
3433 gr->SetMarkerStyle(25);
3434 gr->Draw("p");
3435 leg->AddEntry(gr,"p (TOF)","p");
3436 gr=(TGraph*)inputGraphs->FindObject("protonV0Graph");//ForBBfit");
3437 gr->SetMarkerColor(kRed);
3438 gr->SetMarkerStyle(24);
3439 gr->Draw("p");
3440 leg->AddEntry(gr,"p (V0)","p");
3441 gr=(TGraph*)inputGraphs->FindObject("protonV0plusTOFGraph");//ForBBfit");
3442 gr->SetMarkerColor(kRed);
3443 gr->SetMarkerStyle(30);
3444 gr->Draw("p");
3445 leg->AddEntry(gr,"p (V0+TOF)","p");
3446 gr=(TGraph*)inputGraphs->FindObject("pionTpcGraph");
3447 gr->SetMarkerColor(kBlue);
3448 gr->SetMarkerStyle(26);
3449 gr->Draw("p");
3450 leg->AddEntry(gr,"#pi (TPC)","p");
3451 gr=(TGraph*)inputGraphs->FindObject("pionTofGraph");
3452 gr->SetMarkerColor(kBlue);
3453 gr->SetMarkerStyle(25);
3454 gr->Draw("p");
3455 leg->AddEntry(gr,"#pi (TOF)","p");
3456 gr=(TGraph*)inputGraphs->FindObject("pionV0Graph");//ForBBfit");
3457 gr->SetMarkerColor(kBlue);
3458 gr->SetMarkerStyle(24);
3459 gr->Draw("p");
3460 leg->AddEntry(gr,"#pi (V0)","p");
3461 gr=(TGraph*)inputGraphs->FindObject("pionV0plusTOFGraph");//ForBBfit");
3462 gr->SetMarkerColor(kBlue);
3463 gr->SetMarkerStyle(30);
3464 gr->Draw("p");
3465 leg->AddEntry(gr,"#pi (V0+TOF)","p");
3466 gr=(TGraph*)inputGraphs->FindObject("kaonTpcGraph");
3467 gr->SetMarkerColor(kGreen);
3468 gr->SetMarkerStyle(26);
3469 gr->Draw("p");
3470 leg->AddEntry(gr,"K (TPC)","p");
3471 gr=(TGraph*)inputGraphs->FindObject("kaonTofGraph");
3472 gr->SetMarkerColor(kGreen);
3473 gr->SetMarkerStyle(25);
3474 gr->Draw("p");
3475 leg->AddEntry(gr,"K (TOF)","p");
3476 gr=(TGraph*)inputGraphs->FindObject("electronGraph");
3477 gr->SetMarkerColor(kBlack);
3478 gr->SetMarkerStyle(25);
3479 gr->Draw("p");
3480 leg->AddEntry(gr,"e","p");
3481 gr=(TGraph*)inputGraphs->FindObject("electronV0Graph");//ForBBfit");
3482 gr->SetMarkerColor(kBlack);
3483 gr->SetMarkerStyle(24);
3484 gr->Draw("p");
3485 leg->AddEntry(gr,"e (V0)","p");
3486 gr=(TGraph*)inputGraphs->FindObject("electronV0plusTOFGraph");//ForBBfit");
3487 gr->SetMarkerColor(kBlack);
3488 gr->SetMarkerStyle(30);
3489 gr->Draw("p");
3490 leg->AddEntry(gr,"e (V0+TOF)","p");
3491 }
3492
3493 graphAll->GetXaxis()->SetTitle("#beta#gamma");
3494 graphAll->GetYaxis()->SetTitle("<dE/dx> (arb. unit)");
3495 graphAll->Draw("p");
3496 funcBB->GetHistogram()->DrawClone("csame");
3497
3498 leg->AddEntry(graphAll,"used","p");
3499 leg->AddEntry(funcBB,"fit","l");
3500 leg->Draw("same");
3501
3502 canvDelta_2->cd();
3503 //canvDelta->cd(2);
3504 TH1F *hBBresdummy=new TH1F("hBBresdummy","residuals of BB fit;#beta#gamma;(data-fit)/fit",100,.8,1e4);
3505 hBBresdummy->SetMinimum(-0.04);
3506 hBBresdummy->SetMaximum(0.04);
3507 hBBresdummy->GetXaxis()->SetTitleOffset(1.1);
3508 hBBresdummy->GetYaxis()->SetTitleOffset(0.8);
3509 hBBresdummy->SetStats(kFALSE);
3510 hBBresdummy->Draw();
3511
3512 graphDelta->SetTitle("residuals of BB fit to multi-graph");
3513 graphDelta->GetXaxis()->SetTitle("#beta#gamma");
3514 graphDelta->GetYaxis()->SetTitle("(data - fit) / fit");
3515 graphDelta->SetMarkerStyle(22);
3516 graphDelta->SetMarkerColor(4);
3517 graphDelta->Draw("p");
3518
3519 TFile* fSave = TFile::Open("splines_QA_BetheBlochFit.root", "RECREATE");
3520 fSave->cd();
3521 canvDelta_1->Write();
3522 canvDelta_2->Write();
3523
3524 TString fitResults = "Fit results:\n";
3525 for (Int_t i = 0; i < nPar; i++) {
3526 fitResults.Append(Form("par%d:\t%f +- %f\n", i, funcBB->GetParameters()[i], funcBB->GetParErrors()[i]));
3527 }
3528
3529 TNamed* settings = new TNamed(fitResults.Data(), fitResults.Data());
3530 settings->Write();
3531 fSave->Close();
3532
3533
3534 printf("\n\n%s", fitResults.Data());
3535
3536 return funcBB;
3537}
3538
3539
3540//________________________________________________________________________
3541Double_t AliTPCcalibResidualPID::Lund(Double_t* xx, Double_t* par)
3542{
3543 // bg is beta*gamma
3544 const Double_t bg = xx[0];
3545
3546 const Double_t beta2 = bg*bg / (1.0 + bg*bg);
3547
3548 const Double_t a = par[0];
3549 const Double_t b = par[1];
3550 const Double_t c = par[2];
3551 const Double_t e = par[3];
3552 const Double_t f = par[4];
3553
3554 const Double_t d = TMath::Exp(c*(a - f) / b);
3555
3556 const Double_t powbg = TMath::Power(1.0 + bg, c);
3557
3558 const Double_t value = a / TMath::Power(beta2,e) +
3559 b/c * TMath::Log(powbg / (1.0 + d*powbg));
3560
3561 return value;
3562}
3563
3564
3565//________________________________________________________________________
3566Double_t AliTPCcalibResidualPID::SaturatedLund(Double_t* xx, Double_t* par)
3567{
3568 const Double_t qq = Lund(xx, par);
3569 return qq * TMath::Exp(par[5] / qq);
3570}
3571
3572
3573//________________________________________________________________________
3574void AliTPCcalibResidualPID::FitSlicesY(TH2 *hist, Double_t heightFractionForRange, Int_t cutThreshold, TString fitOption, TObjArray *arr)
3575{
3576 //heightPercentageForRange
3577 // custom slices fit
3578 //
3579
3580 if (!hist) return;
3581 if (!arr) return;
3582
3583 // If old style is to be used
3584 /*
3585 hist->FitSlicesY(0, 0, -1, cutThreshold, fitOption.Data(), &arr);
3586 return;
3587 */
3588
3589
3590 arr->Clear();
3591 arr->SetOwner();
3592 arr->Expand(4);
3593
3594 TAxis *axis=hist->GetXaxis();
3595 const TArrayD *bins = axis->GetXbins();
3596 TH1D** hList = new TH1D*[4];
3597
3598 for (Int_t i = 0; i < 4; i++) {
3599 delete gDirectory->FindObject(Form("%s_%d", hist->GetName(), i));
3600
3601 if (bins->fN == 0) {
3602 hList[i] = new TH1D(Form("%s_%d", hist->GetName(), i), i < 3 ? Form("Fitted value of par[%d]", i) : "Chi2/NDF",
3603 hist->GetNbinsX(), axis->GetXmin(), axis->GetXmax());
3604 } else {
3605 hList[i] = new TH1D(Form("%s_%d", hist->GetName(), i), i < 3 ? Form("Fitted value of par[%d]", i) : "Chi2/NDF", hist->GetNbinsX(), bins->fArray);
3606 }
3607
3608 (*arr)[i] = hList[i];
3609 }
3610
3611 for (Int_t ibin=axis->GetFirst(); ibin<=axis->GetLast(); ++ibin){
3612 TH1 *h=hist->ProjectionY("_temp",ibin,ibin);
3613 if (!h)
3614 continue;
3615
3616 if (h->GetEntries() < cutThreshold) {
3617 delete h;
3618 continue;
3619 }
3620
3621 // Average around maximum bin -> Might catch some outliers
3622 Int_t maxBin = h->GetMaximumBin();
3623 Double_t maxVal = h->GetBinContent(maxBin);
3624
3625 if (maxVal < 2) { // It could happen that all entries are in overflow/underflow; don't fit in this case
3626 delete h;
3627 continue;
3628 }
3629
3630 UChar_t usedBins = 1;
3631 if (maxBin > 1) {
3632 maxVal += h->GetBinContent(maxBin - 1);
3633 usedBins++;
3634 }
3635 if (maxBin < h->GetNbinsX()) {
3636 maxVal += h->GetBinContent(maxBin + 1);
3637 usedBins++;
3638 }
3639 maxVal /= usedBins;
3640
3641 Double_t thresholdFraction = heightFractionForRange * maxVal;
3642 Int_t lowThrBin = TMath::Max(1, h->FindFirstBinAbove(thresholdFraction));
3643 Int_t highThrBin = TMath::Min(h->GetNbinsX(), h->FindLastBinAbove(thresholdFraction));
3644
3645 Double_t lowThreshold = h->GetBinCenter(lowThrBin);
3646 Double_t highThreshold = h->GetBinCenter(highThrBin);
3647
3648 TFitResultPtr res = h->Fit("gaus", Form("%sS", fitOption.Data()), "", lowThreshold, highThreshold);
3649
3650 if ((Int_t)res == 0) {
3651 Int_t resBin = ibin;
3652 hList[0]->SetBinContent(resBin,res->GetParams()[0]);
3653 hList[0]->SetBinError(resBin,res->GetErrors()[0]);
3654 hList[1]->SetBinContent(resBin,res->GetParams()[1]);
3655 hList[1]->SetBinError(resBin,res->GetErrors()[1]);
3656 hList[2]->SetBinContent(resBin,res->GetParams()[2]);
3657 hList[2]->SetBinError(resBin,res->GetErrors()[2]);
3658 hList[3]->SetBinContent(resBin,res->Ndf()>0?res->Chi2()/res->Ndf():0);
3659 }
3660
3661 delete h;
3662 }
3663}
3664
3665
3666//______________________________________________________________________________
3667Bool_t AliTPCcalibResidualPID::GetVertexIsOk(AliVEvent* event) const
3668{
3669 AliAODEvent* aod = 0x0;
3670 AliESDEvent* esd = 0x0;
3671
3672 aod = dynamic_cast<AliAODEvent*>(event);
3673 if (!aod) {
3674 esd = dynamic_cast<AliESDEvent*>(event);
3675
3676 if (!esd) {
3677 AliError("Event seems to be neither AOD nor ESD!");
3678 return kFALSE;
3679 }
3680 }
3681
3682 if (fIsPbpOrpPb) {
3683 const AliVVertex* trkVtx = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertex()) :
3684 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertex()));
3685
3686 if (!trkVtx || trkVtx->GetNContributors() <= 0)
3687 return kFALSE;
3688
3689 TString vtxTtl = trkVtx->GetTitle();
3690 if (!vtxTtl.Contains("VertexerTracks"))
3691 return kFALSE;
3692
3693 Float_t zvtx = trkVtx->GetZ();
3694 const AliVVertex* spdVtx = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertexSPD()) :
3695 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertexSPD()));
3696 if (spdVtx->GetNContributors() <= 0)
3697 return kFALSE;
3698
3699 TString vtxTyp = spdVtx->GetTitle();
3700 Double_t cov[6] = {0};
3701 spdVtx->GetCovarianceMatrix(cov);
3702 Double_t zRes = TMath::Sqrt(cov[5]);
3703 if (vtxTyp.Contains("vertexer:Z") && (zRes > 0.25))
3704 return kFALSE;
3705
3706 if (TMath::Abs(spdVtx->GetZ() - trkVtx->GetZ()) > 0.5)
3707 return kFALSE;
3708
3709 if (TMath::Abs(zvtx) > fZvtxCutEvent) //Default: 10 cm
3710 return kFALSE;
3711
3712 return kTRUE;
3713 }
3714
3715
3716 // pp and PbPb
3717 const AliVVertex* primaryVertex = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertex()) :
3718 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertexTracks()));
3719
3720 if (!primaryVertex || primaryVertex->GetNContributors() <= 0)
3721 return kFALSE;
3722
3723 if (TMath::Abs(primaryVertex->GetZ()) >= fZvtxCutEvent) //Default: 10 cm
3724 return kFALSE;
3725
3726 return kTRUE;
3727}
3728
3729
3730//______________________________________________________________________________
3731void AliTPCcalibResidualPID::FillV0PIDlist(AliESDEvent* event)
3732{
3733 //
3734 // Fill the PID tag list
3735 //
3736
3737 // If no event forwarded as parameter (default), cast current input event.
3738 // Dynamic cast to ESD events (DO NOTHING for AOD events)
3739 if (!event)
3740 event = dynamic_cast<AliESDEvent *>(InputEvent());
3741
3742 // If this fails, do nothing
3743 if (!event)
3744 return;
3745
3746 if (!fV0KineCuts) {
3747 AliError("V0KineCuts not available!");
3748 return;
3749 }
3750
3751 TString beamType(event->GetBeamType());
3752
3753 if (beamType.CompareTo("Pb-Pb") == 0 || beamType.CompareTo("A-A") == 0) {
3754 fV0KineCuts->SetMode(AliESDv0KineCuts::kPurity, AliESDv0KineCuts::kPbPb);
3755 }
3756 else {
3757 fV0KineCuts->SetMode(AliESDv0KineCuts::kPurity, AliESDv0KineCuts::kPP);
3758 }
3759
3760 // V0 selection
3761 // set event
3762 fV0KineCuts->SetEvent(event);
3763
3764 const Int_t numTracks = event->GetNumberOfTracks();
3765 fV0tags = new Char_t[numTracks];
3766 for (Int_t i = 0; i < numTracks; i++)
3767 fV0tags[i] = 0;
3768
3769 fV0motherIndex = new Int_t[numTracks];
3770 for (Int_t i = 0; i < numTracks; i++)
3771 fV0motherIndex[i] = -1;
3772
3773 fV0motherPDG = new Int_t[numTracks];
3774 for (Int_t i = 0; i < numTracks; i++)
3775 fV0motherPDG[i] = 0;
3776
3777 fNumTagsStored = numTracks;
3778
3779
3780
3781
3782
3783 // loop over V0 particles
3784 for (Int_t iv0 = 0; iv0 < event->GetNumberOfV0s(); iv0++) {
3785 AliESDv0* v0 = (AliESDv0*)event->GetV0(iv0);
3786
3787 if (!v0)
3788 continue;
3789
3790 // Reject onFly V0's <-> Only take V0's from offline V0 finder
3791 if (v0->GetOnFlyStatus())
3792 continue;
3793
3794 // Get the particle selection
3795 Bool_t foundV0 = kFALSE;
3796 Int_t pdgV0 = 0, pdgP = 0, pdgN = 0;
3797
3798 foundV0 = fV0KineCuts->ProcessV0(v0, pdgV0, pdgP, pdgN);
3799 if (!foundV0)
3800 continue;
3801
3802 Int_t iTrackP = v0->GetPindex(); // positive track
3803 Int_t iTrackN = v0->GetNindex(); // negative track
3804
3805 /*
3806 AliESDtrack* trackP = event->GetTrack(iTrackP);
3807 AliESDtrack* trackN = event->GetTrack(iTrackN);
3808
3809 if (!trackP || !trackN)
3810 continue;
3811
3812
3813
3814 Float_t xy = 999, z = 999;
3815 trackP->GetImpactParameters(xy, z);
3816
3817 Bool_t reject = kFALSE;
3818 if (TMath::Abs(z) > 1)
3819 continue;
3820
3821 trackN->GetImpactParameters(xy, z);
3822 if (TMath::Abs(z) > 1)
3823 continue;
3824 */
3825
3826
3827 // Fill the Object arrays
3828 // positive particles
3829 if (pdgP == -11) {
3830 fV0tags[iTrackP] = 14;
3831 }
3832 else if (pdgP == 211) {
3833 fV0tags[iTrackP] = 15;
3834 }
3835 else if(pdgP == 2212) {
3836 fV0tags[iTrackP] = 16;
3837 }
3838
3839 fV0motherIndex[iTrackP] = iv0;
3840 fV0motherPDG[iTrackP] = pdgV0;
3841
3842 // negative particles
3843 if( pdgN == 11){
3844 fV0tags[iTrackN] = -14;
3845 }
3846 else if( pdgN == -211){
3847 fV0tags[iTrackN] = -15;
3848 }
3849 else if( pdgN == -2212){
3850 fV0tags[iTrackN] = -16;
3851 }
3852
3853 fV0motherIndex[iTrackN] = iv0;
3854 fV0motherPDG[iTrackN] = pdgV0;
3855
3856 }
3857}
3858
3859
3860//______________________________________________________________________________
3861void AliTPCcalibResidualPID::ClearV0PIDlist()
3862{
3863 //
3864 // Clear the PID tag list
3865 //
3866
3867 delete fV0tags;
3868 fV0tags = 0;
3869
3870 delete fV0motherIndex;
3871 fV0motherIndex = 0;
3872
3873 delete fV0motherPDG;
3874 fV0motherPDG = 0;
3875
3876 fNumTagsStored = 0;
3877}
3878
3879
3880//______________________________________________________________________________
3881Char_t AliTPCcalibResidualPID::GetV0tag(Int_t trackIndex) const
3882{
3883 //
3884 // Get the tag for the corresponding trackIndex. Returns -99 in case of invalid index/tag list.
3885 //
3886
3887 if (trackIndex < 0 || trackIndex >= fNumTagsStored || !fV0tags)
3888 return -99;
3889
3890 return fV0tags[trackIndex];
3891}
3892
3893
3894//______________________________________________________________________________
3895Int_t AliTPCcalibResidualPID::GetV0motherIndex(Int_t trackIndex) const
3896{
3897 //
3898 // Get the index of the V0 mother for the corresponding trackIndex. Returns -99 in case of invalid index/mother index list.
3899 //
3900
3901 if (trackIndex < 0 || trackIndex >= fNumTagsStored || !fV0motherIndex)
3902 return -99;
3903
3904 return fV0motherIndex[trackIndex];
3905}
3906
3907
3908//______________________________________________________________________________
3909Int_t AliTPCcalibResidualPID::GetV0motherPDG(Int_t trackIndex) const
3910{
3911 //
3912 // Get the PDG code of the V0 mother for the corresponding trackIndex. Returns 0 in case of invalid index/mother index list.
3913 //
3914
3915 if (trackIndex < 0 || trackIndex >= fNumTagsStored || !fV0motherPDG)
3916 return 0;
3917
3918 return fV0motherPDG[trackIndex];
3919}
3920
3921
3922//______________________________________________________________________________
3923Int_t AliTPCcalibResidualPID::MergeGraphErrors(TGraphErrors* mergedGraph, TCollection* li)
3924{
3925 // Adds all graphs with errors from the collection to this graph.
3926 // Returns the total number of poins in the result or -1 in case of an error.
3927
3928 // TODO "Normal" merge of latest root trunk will also take into account the error bars,
3929 // so this function can be replaced by the normal root function with the latest root version.
3930
3931 TIter next(li);
3932 while (TObject* o = next()) {
3933 TGraph *g = dynamic_cast<TGraph*>(o);
3934 if (!g) {
3935 Printf("ERROR: Cannot merge an object which doesn't inherit from TGraph found in the list");
3936 return -1;
3937 }
3938 int n0 = mergedGraph->GetN();
3939 int n1 = n0+g->GetN();
3940 mergedGraph->Set(n1);
3941 Double_t * x = g->GetX();
3942 Double_t * y = g->GetY();
3943 Double_t * ex = g->GetEX();
3944 Double_t * ey = g->GetEY();
3945 for (Int_t i = 0 ; i < g->GetN(); i++) {
3946 mergedGraph->SetPoint(n0+i, x[i], y[i]);
3947 Double_t exPoint = ex ? ex[i] : 0;
3948 Double_t eyPoint = ey ? ey[i] : 0;
3949 mergedGraph->SetPointError(n0+i, exPoint, eyPoint);
3950 }
3951 }
3952 return mergedGraph->GetN();
3953}
3954
3955//________________________________________________________________________
3956Bool_t AliTPCcalibResidualPID::TPCCutMIGeo(const AliVTrack* track, const AliVEvent* evt, TTreeStream* streamer)
3957{
3958 //
3959 // TPC Cut MIGeo
3960 //
3961
3962 if (!track || !evt)
3963 return kFALSE;
3964
3965 const Short_t sign = track->Charge();
3966 Double_t xyz[50];
3967 Double_t pxpypz[50];
3968 Double_t cv[100];
3969
3970 track->GetXYZ(xyz);
3971 track->GetPxPyPz(pxpypz);
3972
3973 AliExternalTrackParam* par = new AliExternalTrackParam(xyz, pxpypz, cv, sign);
3974 const AliESDtrack dummy;
3975
3976 const Double_t magField = evt->GetMagneticField();
3977 Double_t varGeom = dummy.GetLengthInActiveZone(par, 3, 236, magField, 0, 0);
3978 Double_t varNcr = track->GetTPCClusterInfo(3, 1);
3979 Double_t varNcls = track->GetTPCsignalN();
3980
3981 const Double_t varEval = 130. - 5. * TMath::Abs(1. / track->Pt());
3982 Bool_t cutGeom = varGeom > fgCutGeo * varEval;
3983 Bool_t cutNcr = varNcr > fgCutNcr * varEval;
3984 Bool_t cutNcls = varNcls > fgCutNcl * varEval;
3985
3986 Bool_t kout = cutGeom && cutNcr && cutNcls;
3987
3988 if (streamer) {
3989 Double_t dedx = track->GetTPCsignal();
3990
3991 (*streamer)<<"tree"<<
3992 "param.="<< par<<
3993 "varGeom="<<varGeom<<
3994 "varNcr="<<varNcr<<
3995 "varNcls="<<varNcls<<
3996
3997 "cutGeom="<<cutGeom<<
3998 "cutNcr="<<cutNcr<<
3999 "cutNcls="<<cutNcls<<
4000
4001 "kout="<<kout<<
4002 "dedx="<<dedx<<
4003
4004 "\n";
4005 }
4006
4007 delete par;
4008
4009 return kout;
4010}