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