1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: Yvonne Pachmayer <pachmay@physi.uni-heidelberg.de> *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 // stores TPC PID quantities in a THnSparse
18 // output can then be used for e.g. dEdx calibration
21 // Yvonne Pachmayer <pachmay@physi.uni-heidelberg.de>
25 #include "AliTPCcalibResidualPID.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"
34 #include "AliTPCcalibResidualPID.h"
35 #include "AliESDtrack.h"
36 #include "AliESDtrackCuts.h"
37 #include "AliESDpid.h"
38 #include "AliESDInputHandler.h"
39 #include "AliESDv0KineCuts.h"
41 #include "AliCentrality.h"
42 #include "THnSparse.h"
45 #include "TGraphErrors.h"
46 #include "TMultiGraph.h"
51 #include "AliTPCdEdxInfo.h"
53 #include "TFitResult.h"
56 #include "TVirtualFitter.h"
60 ClassImp(AliTPCcalibResidualPID)
62 Double_t AliTPCcalibResidualPID::fgCutGeo = 1.;
63 Double_t AliTPCcalibResidualPID::fgCutNcr = 0.85;
64 Double_t AliTPCcalibResidualPID::fgCutNcl = 0.7;
66 //________________________________________________________________________
67 AliTPCcalibResidualPID::AliTPCcalibResidualPID()
68 : AliAnalysisTaskSE(), fESD(0), fMC(0), fOutputContainer(0), fESDtrackCuts(0), fESDtrackCutsV0(0), fESDpid(0),
69 fUseTPCCutMIGeo(kFALSE),
72 fZvtxCutEvent(9999.0),
78 fProduceAllPadTypes(0),
81 fProduceMediumPads(0),
89 fProduceTPCSignalSparse(0),
90 fCorrectdEdxEtaDependence(0),
91 fCorrectdEdxMultiplicityDependence(0),
97 fhInvMassAntiLambda(0x0),
99 fhArmenterosGamma(0x0),
100 fhArmenterosK0s(0x0),
101 fhArmenterosLambda(0x0),
102 fhArmenterosAntiLambda(0x0),
103 fHistSharedClusQAV0Pi(0x0),
104 fHistSharedClusQAV0Pr(0x0),
105 fHistSharedClusQAV0El(0x0)
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++
117 //________________________________________________________________________
118 AliTPCcalibResidualPID::AliTPCcalibResidualPID(const char *name)
119 : AliAnalysisTaskSE(name), fESD(0), fMC(0), fOutputContainer(0), fESDtrackCuts(0), fESDtrackCutsV0(0), fESDpid(0),
120 fUseTPCCutMIGeo(kFALSE),
123 fZvtxCutEvent(9999.0),
129 fProduceAllPadTypes(0),
131 fProduceShortPads(0),
132 fProduceMediumPads(0),
140 fProduceTPCSignalSparse(0),
141 fCorrectdEdxEtaDependence(0),
142 fCorrectdEdxMultiplicityDependence(0),
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)
159 //fESDtrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(kTRUE);
160 //fESDtrackCutsV0 = AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(kFALSE);
163 DefineInput(0, TChain::Class());
164 DefineOutput(1, TObjArray::Class());
165 DefineOutput(2, TObjArray::Class());
170 //_________________________________________________
171 AliTPCcalibResidualPID::~AliTPCcalibResidualPID()
173 delete fOutputContainer;
174 fOutputContainer = 0;
179 delete fESDtrackCuts;
182 delete fESDtrackCutsV0;
192 delete fV0motherIndex;
200 //________________________________________________________________________
201 void AliTPCcalibResidualPID::UserCreateOutputObjects()
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);
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
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);
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);
236 fOutputContainer = new TObjArray(2);
237 fOutputContainer->SetName(GetName());
238 fOutputContainer->SetOwner();
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);
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]);
255 fQAList = new TObjArray(4);
256 fQAList->SetName(GetName());
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",
265 fQAList->Add(fhInvMassGamma);
266 fQAList->Add(fhInvMassK0s);
267 fQAList->Add(fhInvMassLambda);
268 fQAList->Add(fhInvMassAntiLambda);
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);
287 fQAList->Add(fhArmenterosAll);
288 fQAList->Add(fhArmenterosGamma);
289 fQAList->Add(fhArmenterosK0s);
290 fQAList->Add(fhArmenterosLambda);
291 fQAList->Add(fhArmenterosAntiLambda);
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};
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);
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);
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);
321 PostData(1,fOutputContainer);
326 //_____________________________________________________________________________
327 void AliTPCcalibResidualPID::UserExec(Option_t *)
329 //calls the Process function
330 AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());
333 printf("ERROR: Could not get ESDInputHandler \n");
335 else fESD = esdH->GetEvent();
337 // If MC, forward MCevent
338 fMC = dynamic_cast<AliMCEvent*>(MCEvent());
342 PostData(1,fOutputContainer);
348 //________________________________________________________________________
349 void AliTPCcalibResidualPID::Process(AliESDEvent *const esdEvent, AliMCEvent *const mcEvent)
352 //called for each event
354 Printf("ERROR: esdEvent not available");
358 if(!((AliESDInputHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))) printf("ESD inputhandler not available \n");
361 fESDpid = ((AliESDInputHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->GetESDpid();
364 if (!fESDpid || !fV0KineCuts)
368 Float_t centralityFper=99;
370 AliCentrality *esdCentrality = esdEvent->GetCentrality();
371 centralityFper = esdCentrality->GetCentralityPercentile("V0M");
373 if (!GetVertexIsOk(esdEvent))
376 const AliESDVertex* fESDvertex = esdEvent->GetPrimaryVertexTracks();
380 Int_t ncontr = fESDvertex->GetNContributors();
385 // Fill V0 arrays with V0s
386 FillV0PIDlist(esdEvent);
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;
394 Int_t nTotTracks = esdEvent->GetNumberOfTracks();
395 for (Int_t iTracks = 0; iTracks < nTotTracks; iTracks++){//begin track loop
396 AliESDtrack *trackESD = esdEvent->GetTrack(iTracks);
398 Printf("ERROR: Could not receive track %d (esd loop)", iTracks);
401 if((TMath::Abs(trackESD->Eta())) > 0.9)
404 // Do not distinguish positively and negatively charged V0's
405 Char_t v0tagAllCharges = TMath::Abs(GetV0tag(iTracks));
406 if (v0tagAllCharges == -99) {
407 AliError(Form("Problem with V0 tag list (requested V0 track for track %d from %d (list status %d))!", iTracks, esdEvent->GetNumberOfTracks(),
412 Bool_t isV0el = v0tagAllCharges == 14;
413 Bool_t isV0pi = v0tagAllCharges == 15;
414 Bool_t isV0pr = v0tagAllCharges == 16;
415 Bool_t isV0 = isV0el || isV0pi || isV0pr;
417 if (mcEvent && fUseMCinfo) {
418 // For MC, do not look for V0s, i.e. demand the non-V0 track cuts
419 if (fESDtrackCuts && !fESDtrackCuts->AcceptTrack(trackESD)) continue;
421 if (fUseTPCCutMIGeo) {
422 // If cut on geometry is active, don't cut on number of clusters, since such a cut is already included.
423 if (!TPCCutMIGeo(trackESD, esdEvent))
427 // If cut on geometry is not active, always cut on num clusters
428 if (trackESD->GetTPCsignalN() < 60)
433 // For data, take V0 AND non-V0 with separate cuts
434 //if (!isV0 && fESDtrackCuts && !fESDtrackCuts->AcceptTrack(trackESD)) continue;
436 if (fESDtrackCutsV0 && !fESDtrackCutsV0->AcceptTrack(trackESD))
440 if (fESDtrackCuts && !fESDtrackCuts->AcceptTrack(trackESD))
444 if (fUseTPCCutMIGeo) {
445 // If cut on geometry is active, don't cut on number of clusters, since such a cut is already included.
447 if (!TPCCutMIGeo(trackESD, esdEvent))
451 // One should not cut on geometry for V0's since they have different topology. (Loosely) cut on num of clusters instead.
452 if (trackESD->GetTPCsignalN() < 60)
457 // If cut on geometry is not active, always cut on num clusters
458 if (trackESD->GetTPCsignalN() < 60)
463 const AliExternalTrackParam *paramIn = trackESD->GetInnerParam();
466 precin=paramIn->GetP();
470 Int_t precdefault=CompareFloat(precin,-1);
471 if(precdefault==1) continue; // momentum cut
474 AliMCParticle* mcTrack = 0x0;
475 Int_t particleID = -1;
478 if (mcEvent && fUseMCinfo) {
479 // MC - particle ID = MC ID
480 Int_t label = trackESD->GetLabel();
483 continue; // If MC is available, reject tracks with negative ESD label
485 mcTrack = dynamic_cast<AliMCParticle*>(mcEvent->GetTrack(TMath::Abs(label)));
487 Printf("ERROR: Could not receive mcTrack with label %d for track %d", label, iTracks);
491 /*// Only accept MC primaries
492 if (!mcEvent->Stack()->IsPhysicalPrimary(TMath::Abs(label))) {
496 Int_t pdgAbs = TMath::Abs(mcTrack->PdgCode());
498 if (pdgAbs == 11) { // electron
501 else if (pdgAbs == 211) { // pion
504 else if (pdgAbs == 321) { // kaon
507 else if (pdgAbs == 2212) { // proton
511 continue; // Reject all other particles
514 // Data - particle ID = V0 ID (if V0)
515 if (isV0pi) { // pion
519 else if (isV0el) { // electron
523 else if (isV0pr) { // proton
527 else { // No V0-ID available (species must be determined via TPC, TOF, ...)
533 Float_t tpcsignal=trackESD->GetTPCsignal();
537 Double_t tpcnsigmaele=-10;
538 Double_t tpcnsigmapion=-10;
540 if ((trackESD->GetStatus() & AliESDtrack::kTOFpid)) iTOFpid = 1;
541 if ((trackESD->GetStatus() & AliESDtrack::kTIME)) ikTIME = 1;
542 Float_t time0 = fESDpid->GetTOFResponse().GetTimeZero();
544 if((iTOFpid==1) &&(ikTIME==1)){
545 Double_t tofnsigmaele= fESDpid->NumberOfSigmasTOF(trackESD,AliPID::kElectron, time0);
546 Double_t tofnsigmapion=fESDpid->NumberOfSigmasTOF(trackESD,AliPID::kPion, time0);
547 if (TMath::Abs(tofnsigmapion)<3) tofbit = 1;
548 if (TMath::Abs(tofnsigmaele)<3) tofbit = 0;
549 tpcnsigmaele=fESDpid->NumberOfSigmasTPC(trackESD,AliPID::kElectron);
550 tpcnsigmapion=fESDpid->NumberOfSigmasTPC(trackESD,AliPID::kPion);
553 Int_t tpcnclusN=trackESD->GetTPCsignalN();
554 Double_t eta=trackESD->Eta();
557 if(fProduceTPCSignalSparse){
558 Double_t contentSignal[9];
559 contentSignal[0]=v0id;
560 contentSignal[1]=tpcsignal;
561 contentSignal[2]=tpcnsigmaele;
562 contentSignal[3]=tpcnsigmapion;
563 contentSignal[4]=tofbit;
564 contentSignal[5]=eta;
565 contentSignal[6]=tpcnclusN;
566 contentSignal[7]=centralityFper;
567 contentSignal[8]=precin;
569 if (fThnspTpc->GetEntries() < 1e6) fThnspTpc->Fill(contentSignal);
570 }//should it be created or not
577 Double_t tpcQA[5] = {fESDpid->NumberOfSigmasTPC(trackESD, AliPID::kElectron),
578 fESDpid->NumberOfSigmasTPC(trackESD, AliPID::kPion),
579 fESDpid->NumberOfSigmasTPC(trackESD, AliPID::kKaon),
580 fESDpid->NumberOfSigmasTPC(trackESD, AliPID::kProton),
582 Double_t tofQA[5] = {fESDpid->NumberOfSigmasTOF(trackESD, AliPID::kElectron, time0),
583 fESDpid->NumberOfSigmasTOF(trackESD, AliPID::kPion, time0),
584 fESDpid->NumberOfSigmasTOF(trackESD, AliPID::kKaon, time0),
585 fESDpid->NumberOfSigmasTOF(trackESD, AliPID::kProton, time0),
588 // id 5 is just again Kaons in restricted eta range
593 // dE/dx in different pad regions
595 AliTPCdEdxInfo * infoTpcPid = trackESD->GetTPCdEdxInfo();
596 Double32_t signal[4]; Char_t ncl[3]; Char_t nrows[3];
598 infoTpcPid->GetTPCSignalRegionInfo(signal, ncl, nrows);
600 for(Int_t iarr = 0; iarr < 3; iarr++) {
608 UInt_t status = trackESD->GetStatus();
609 Bool_t hasTOFout = status&AliESDtrack::kTOFout;
610 Bool_t hasTOFtime = status&AliESDtrack::kTIME;
611 Bool_t hasTOF = kFALSE;
612 if (hasTOFout && hasTOFtime) hasTOF = kTRUE;
613 Float_t length = trackESD->GetIntegratedLength();
614 // Length check only for primaries!
615 if (length < 350 && !isV0) hasTOF = kFALSE;
619 // Make sure that number of sigmas is large in this case, so that the track will be rejected if a TOF cut is applied
620 for (Int_t i = 0; i < 5; i++) {
626 Double_t processedTPCsignal[5] = { tpcsignal, tpcsignal, tpcsignal, tpcsignal, tpcsignal };
629 if (fCorrectdEdxEtaDependence && fCorrectdEdxMultiplicityDependence) {
630 processedTPCsignal[0] = fESDpid->GetTPCResponse().GetEtaAndMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kElectron,
631 AliTPCPIDResponse::kdEdxDefault);
632 processedTPCsignal[1] = fESDpid->GetTPCResponse().GetEtaAndMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kPion,
633 AliTPCPIDResponse::kdEdxDefault);
634 processedTPCsignal[2] = fESDpid->GetTPCResponse().GetEtaAndMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kKaon,
635 AliTPCPIDResponse::kdEdxDefault);
636 processedTPCsignal[3] = fESDpid->GetTPCResponse().GetEtaAndMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kProton,
637 AliTPCPIDResponse::kdEdxDefault);
639 else if (fCorrectdEdxEtaDependence) {
640 processedTPCsignal[0] = fESDpid->GetTPCResponse().GetEtaCorrectedTrackdEdx(trackESD, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault);
641 processedTPCsignal[1] = fESDpid->GetTPCResponse().GetEtaCorrectedTrackdEdx(trackESD, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault);
642 processedTPCsignal[2] = fESDpid->GetTPCResponse().GetEtaCorrectedTrackdEdx(trackESD, AliPID::kKaon, AliTPCPIDResponse::kdEdxDefault);
643 processedTPCsignal[3] = fESDpid->GetTPCResponse().GetEtaCorrectedTrackdEdx(trackESD, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault);
645 else if (fCorrectdEdxMultiplicityDependence) {
646 processedTPCsignal[0] = fESDpid->GetTPCResponse().GetMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault);
647 processedTPCsignal[1] = fESDpid->GetTPCResponse().GetMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault);
648 processedTPCsignal[2] = fESDpid->GetTPCResponse().GetMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kKaon, AliTPCPIDResponse::kdEdxDefault);
649 processedTPCsignal[3] = fESDpid->GetTPCResponse().GetMultiplicityCorrectedTrackdEdx(trackESD, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault);
652 // id 5 is just again Kaons in restricted eta range
653 processedTPCsignal[4] = processedTPCsignal[2];
655 for(Int_t iPart = 0; iPart < 5; iPart++) {
656 // 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)
657 if (iPart == 4 && ((mcEvent && fUseMCinfo) || abs(trackESD->Eta()) > 0.2))
660 Double_t vecHistQA[7] = {precin, processedTPCsignal[iPart], particleID, iPart, tpcQA[iPart], tofQA[iPart], nTotTracks};
661 if (fProduceGlobal) fHistPidQA->Fill(vecHistQA);
662 vecHistQA[1] = signal[0]; vecHistQA[4] = ncl[0];
663 if ((fProduceAllPadTypes || fProduceShortPads)) fHistPidQAshort->Fill(vecHistQA);
665 vecHistQA[1] = signal[1]; vecHistQA[4] = ncl[1];
666 if ((fProduceAllPadTypes || fProduceMediumPads)) fHistPidQAmedium->Fill(vecHistQA);
668 vecHistQA[1] = signal[2]; vecHistQA[4] = ncl[2];
669 if ((fProduceAllPadTypes || fProduceLongPads)) fHistPidQAlong->Fill(vecHistQA);
671 vecHistQA[1] = signal[3]; vecHistQA[4] = nrows[1] + nrows[2];
672 if ((fProduceAllPadTypes || fProduceOroc)) fHistPidQAoroc->Fill(vecHistQA);
676 // Fill QA hists for shared clusters dE/dx
677 Double_t vecHistQA[4] = { precin, -1, trackESD->GetTPCSharedMap().CountBits(), -1 };
678 THnSparse* currHist = fHistSharedClusQAV0Pi;
681 Double_t expectedDeDx = fESDpid->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kPion, AliTPCPIDResponse::kdEdxDefault,
682 fCorrectdEdxEtaDependence, fCorrectdEdxMultiplicityDependence);
683 if (expectedDeDx > 0 ) {
684 vecHistQA[1] = tpcsignal / expectedDeDx;
685 currHist = fHistSharedClusQAV0Pi;
689 Double_t expectedDeDx = fESDpid->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kProton, AliTPCPIDResponse::kdEdxDefault,
690 fCorrectdEdxEtaDependence, fCorrectdEdxMultiplicityDependence);
691 if (expectedDeDx > 0 ) {
692 vecHistQA[1] = tpcsignal / expectedDeDx;
693 currHist = fHistSharedClusQAV0Pr;
697 Double_t expectedDeDx = fESDpid->GetTPCResponse().GetExpectedSignal(trackESD, AliPID::kElectron, AliTPCPIDResponse::kdEdxDefault,
698 fCorrectdEdxEtaDependence, fCorrectdEdxMultiplicityDependence);
699 if (expectedDeDx > 0 ) {
700 vecHistQA[1] = tpcsignal / expectedDeDx;
701 currHist = fHistSharedClusQAV0El;
706 // iRowInd == -1 for "all rows w/o multiple counting"
707 currHist->Fill(vecHistQA);
709 // Fill hist for every pad row with shared cluster
710 for (iRowInd = 0; iRowInd < 159; iRowInd++) {
711 if (trackESD->GetTPCSharedMap().TestBitNumber(iRowInd)) {
712 vecHistQA[3] = iRowInd;
713 currHist->Fill(vecHistQA);
719 // Check, whether the QA for this V0 mother was already filled into the histograms (is the case if the other daughter has already
720 // been processed). If not, set flag to kTRUE and fill the QA.
721 const Int_t iV0 = GetV0motherIndex(iTracks);
722 if (!v0QAadded[iV0]) {
723 v0QAadded[iV0] = kTRUE;
725 AliESDv0* esdV0 = (AliESDv0*)esdEvent->GetV0(iV0);
728 printf("Error: V0 tagged, but does not exist!\n");
732 Float_t armVar[2] = {0.0,0.0};
733 fV0KineCuts->Armenteros(esdV0, armVar);
735 const Int_t motherPDG = GetV0motherPDG(iTracks);
737 // Mother and daughter match the requirements, otherwise it wouldn't be tagged as a V0. Now just fill the QA histos.
738 fhArmenterosAll->Fill(armVar[0], armVar[1]);
739 //if (esdV0->TestBit(BIT(14))) {
740 if (TMath::Abs(motherPDG) == 22) {
741 fhInvMassGamma->Fill(esdV0->GetEffMass(AliPID::kElectron, AliPID::kElectron));
742 fhArmenterosGamma->Fill(armVar[0], armVar[1]);
744 else if (TMath::Abs(motherPDG) == 310) {
745 //else if (esdV0->TestBit(BIT(15))) {
746 fhInvMassK0s->Fill(esdV0->GetEffMass(AliPID::kPion, AliPID::kPion));
747 fhArmenterosK0s->Fill(armVar[0], armVar[1]);
749 else if (motherPDG == 3122) {
750 //else if (esdV0->TestBit(BIT(16))) {
751 fhInvMassLambda->Fill(esdV0->GetEffMass(AliPID::kProton, AliPID::kPion));
752 fhArmenterosLambda->Fill(armVar[0], armVar[1]);
754 else if (motherPDG == -3122) {
755 //else if (esdV0->TestBit(BIT(17))) {
756 fhInvMassAntiLambda->Fill(esdV0->GetEffMass(AliPID::kPion, AliPID::kProton));
757 fhArmenterosAntiLambda->Fill(armVar[0], armVar[1]);
764 // Clear the V0 PID arrays
769 //________________________________________________________________________
770 Int_t AliTPCcalibResidualPID::CompareFloat(Float_t f1, Float_t f2) const
772 //compares if the Float_t f1 is equal with f2 and returns 1 if true and 0 if false
773 Float_t precision = 0.00001;
774 if (((f1 - precision) < f2) &&
775 ((f1 + precision) > f2))
786 //________________________________________________________________________
787 void AliTPCcalibResidualPID::Terminate(const Option_t *)
795 //________________________________________________________________________
796 void AliTPCcalibResidualPID::BinLogAxis(const THnSparseF *h, Int_t axisNumber) {
798 // Method for the correct logarithmic binning of histograms
800 TAxis *axis = h->GetAxis(axisNumber);
801 int bins = axis->GetNbins();
803 Double_t from = axis->GetXmin();
804 Double_t to = axis->GetXmax();
805 Double_t *newBins = new Double_t[bins + 1];
808 Double_t factor = pow(to/from, 1./bins);
810 for (int i = 1; i <= bins; i++) {
811 newBins[i] = factor * newBins[i-1];
813 axis->Set(bins, newBins);
819 //________________________________________________________________________
820 Double_t* AliTPCcalibResidualPID::ExtractResidualPID(THnSparseF * histPidQA, const Bool_t useV0s, const Char_t * outFile,
821 const Char_t * type, const Char_t * period, const Char_t * pass,
822 const Char_t * system, const Double_t * initialParameters,
823 const Char_t *dedxtype,
824 AliTPCcalibResidualPID::FitType fitType) {
826 // (1.) obtain residual graphs
828 TObjArray * arr = 0x0;
830 Bool_t isMC = kFALSE;
831 if (strcmp(type, "MC") == 0) {
832 arr = GetResidualGraphsMC(histPidQA, system);
835 else if (strcmp(type, "DATA") == 0) {
836 arr = GetResidualGraphs(histPidQA, system, useV0s);
839 Printf("ERROR - ExtractResidualPID: Unknown type \"%s\" - must be \"MC\" or \"DATA\"!", type);
844 Bool_t isPPb = kFALSE;
845 if (strcmp(system, "PPB") == 0 || strcmp(system, "PBP") == 0) {
846 Printf("p-Pb/Pb-p detected - Applying special handling!");
850 // (2.) get old-style Bethe-Bloch parameters
852 TF1* parametrisation = FitBB(arr, isMC, isPPb, useV0s, initialParameters, fitType);
854 // (3.) obtain response functions to OADB
856 TObjArray* arrResponse = GetResponseFunctions(parametrisation, arr, type, period, pass, system, dedxtype);
858 // (4.) write results to file and exit
861 TFile outputFile(outFile,"RECREATE");
862 arrResponse->Write();
867 return parametrisation->GetParameters();
871 //________________________________________________________________________
872 TObjArray * AliTPCcalibResidualPID::GetSeparation(THnSparseF * histPidQA, Int_t kParticle1, Int_t kParticle2) {
875 THnSparse * hist = histPidQA;
878 Float_t nSigmaPlus1 = 0, nSigmaMinus1 = 0; //sigma of first particle in the TPC
879 Float_t nSigmaPlus2 = 0, nSigmaMinus2 = 0; //sigma of second particle in the TPC
881 if(kParticle1 == 0){ // electron
882 nSigmaMinus1 = -1.999;
884 } else if(kParticle1 == 1){ //pion
885 nSigmaMinus1 = -1.999;
887 } else if(kParticle1 == 2){ //kaons
888 nSigmaMinus1 = -2.999;
890 } else if(kParticle1 == 3){ //protons
891 nSigmaMinus1 = -2.999;
896 // 1. select and fit first particle
898 hist->GetAxis(3)->SetRangeUser(kParticle1,kParticle1);
899 hist->GetAxis(4)->SetRangeUser(nSigmaMinus1,nSigmaPlus1);
900 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
901 TH2D * histPart1 = (TH2D*) hist->Projection(1,0)->Clone("histPart1");
902 histPart1->SetTitle(";p /(GeV/c) ; TPCSignal /(a.u.)");
903 histPart1->RebinX(4);
906 histPart1->FitSlicesY(0,0,-1,10,"QNR",&arr);
907 TH1D * PartMean1 = (TH1D *) arr.At(1)->Clone("PartMean1");
908 TH1D * PartSigma1 = (TH1D *) arr.At(2)->Clone("PartSigma1");
909 PartMean1->SetTitle(";p /(GeV/c) ; Mean (Gauss)");
910 PartSigma1->SetTitle(";p /(GeV/c) ; Sigma (Gauss)");
912 histPart1->SetMarkerStyle(22);
913 PartMean1->SetMarkerStyle(21);
914 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
915 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
917 if(kParticle2==0){ // electron
918 nSigmaMinus2 = -1.999;
920 } else if(kParticle2 == 1){ //pion
921 nSigmaMinus2 = -1.999;
923 } else if(kParticle2 == 2){ //kaons
924 nSigmaMinus2 = -2.999;
926 } else if(kParticle2 == 3){ //protons
927 nSigmaMinus2 = -2.999;
932 // 2. select and fit second particle
934 hist->GetAxis(3)->SetRangeUser(kParticle2,kParticle2);
935 hist->GetAxis(4)->SetRangeUser(nSigmaMinus2,nSigmaPlus2);
936 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
937 TH2D * histPart2 = (TH2D*)hist->Projection(1,0)->Clone("histPart2");
938 histPart2->RebinX(4);
939 histPart2->FitSlicesY(0,0,-1,10,"QNR",&arr);
940 TH1D * PartMean2 = (TH1D *) arr.At(1)->Clone("PartMean2");
941 TH1D * PartSigma2 = (TH1D *) arr.At(2)->Clone("PartSigma2");
942 PartMean2->SetTitle(";p /(GeV/c) ; Mean (Gauss)");
943 PartSigma2->SetTitle(";p /(GeV/c) ; Sigma (Gauss)");
944 PartMean2->SetMarkerStyle(20);
945 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
946 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
952 TH1F *fHistSeparation=(TH1F*)PartMean1->Clone("fHistSeparation"); //to get same binning
953 fHistSeparation->SetMarkerStyle(22);
954 const Int_t Nbins = PartMean1->GetNbinsX();
955 fHistSeparation->SetTitle(";p /(GeV/c) ; Separation");
957 Float_t DeltaMean[Nbins] ;
958 Float_t DeltaSigma[Nbins];
960 for(Int_t i=0 ; i<Nbins; i++){
962 DeltaMean[i] = TMath::Abs(PartMean1->GetBinContent(i) - PartMean2->GetBinContent(i));
963 DeltaSigma[i] = TMath::Abs((PartSigma1->GetBinContent(i) + PartSigma2->GetBinContent(i)))/2.;
965 if(!(TMath::Abs(DeltaSigma[i])<0.000001))fHistSeparation->SetBinContent(i,DeltaMean[i]/DeltaSigma[i]);
966 }//for(Int_t i=0 ; i<Nbins ; i++)
968 TObjArray *array = new TObjArray();
969 array->Add(histPart1);
970 array->Add(histPart2);
971 array->Add(PartMean1);
972 array->Add(PartSigma1);
973 array->Add(PartMean2);
974 array->Add(PartSigma2);
975 array->Add(fHistSeparation);
981 //________________________________________________________________________
982 TObjArray * AliTPCcalibResidualPID::GetResidualGraphs(THnSparseF * histPidQA, const Char_t * system, Bool_t useV0s) {
984 // Extracts the residual graphs from THnSparse created from data (NOT MC!)
987 const TString momTitle = "#it{p}_{TPC} (GeV/#it{c})";
988 const TString dEdxTitle = "d#it{E}/d#it{x} (arb. unit)";
990 Bool_t isPPb = kFALSE;
991 if (strcmp(system, "PPB") == 0 || strcmp(system, "PBP") == 0) {
992 Printf("p-Pb/Pb-p detected - Applying special handling!");
996 // the following parameters have to be extracted from the data itself
999 Float_t nSigmaPionMinus = -3.999;
1000 Float_t nSigmaPionPlus = 3.999;
1001 Float_t nSigmaKaonMinus = -4.199;
1002 Float_t nSigmaKaonPlus = 4.7999;
1003 Float_t nSigmaElectronMinus = -1.999;
1004 Float_t nSigmaElectronPlus = 4.999;
1006 Int_t cutForFitting = 10;
1007 Double_t heightFractionForFittingRange = 0.1;
1009 THnSparse * hist = histPidQA;
1011 TCanvas * canvasQAtpc = new TCanvas("canvasQAtpcResGraph","Control canvas for residual graphs (TPC)",100,10,1380,800);
1012 canvasQAtpc->Divide(2,2);
1014 TCanvas * canvasQAtof = new TCanvas("canvasQAtofResGraph","Control canvas for residual graphs (TOF)",100,10,1380,800);
1015 canvasQAtof->Divide(2,2);
1017 TCanvas * canvasQAv0 = new TCanvas("canvasQAv0ResGraph","Control canvas for residual graphs (V0)",100,10,1380,800);
1018 canvasQAv0->Divide(2,2);
1020 TCanvas * canvasQAv0plusTOF = new TCanvas("canvasQAv0plusTOFResGraph","Control canvas for residual graphs (V0+TOF)",100,10,1380,800);
1021 canvasQAv0plusTOF->Divide(2,2);
1024 TCanvas * canvasQAv0DeDxPurityEl = new TCanvas("canvasQAv0DeDxPurityEl","Control canvas for residual graphs (V0 el)",100,10,600,400);
1025 TCanvas * canvasQAv0DeDxPurityPi = new TCanvas("canvasQAv0DeDxPurityPi","Control canvas for residual graphs (V0 pi)",100,10,600,400);
1026 TCanvas * canvasQAv0DeDxPurityPr = new TCanvas("canvasQAv0DeDxPurityPr","Control canvas for residual graphs (V0 pr)",100,10,600,400);
1028 canvasQAv0DeDxPurityEl->SetLogx();
1029 canvasQAv0DeDxPurityPi->SetLogx();
1030 canvasQAv0DeDxPurityPr->SetLogx();
1032 canvasQAv0DeDxPurityEl->SetLogz();
1033 canvasQAv0DeDxPurityPi->SetLogz();
1034 canvasQAv0DeDxPurityPr->SetLogz();
1036 canvasQAv0DeDxPurityEl->SetTopMargin(0.03);
1037 canvasQAv0DeDxPurityPi->SetTopMargin(0.03);
1038 canvasQAv0DeDxPurityPr->SetTopMargin(0.03);
1040 for (Int_t i = 1; i <= 4; i++) {
1041 canvasQAtpc->GetPad(i)->SetGrid(1, 1);
1042 canvasQAtof->GetPad(i)->SetGrid(1, 1);
1043 canvasQAv0->GetPad(i)->SetGrid(1, 1);
1044 canvasQAv0plusTOF->GetPad(i)->SetGrid(1, 1);
1046 canvasQAtpc->GetPad(i)->SetLogz();
1047 canvasQAtof->GetPad(i)->SetLogz();
1048 canvasQAv0->GetPad(i)->SetLogz();
1049 canvasQAv0plusTOF->GetPad(i)->SetLogz();
1051 canvasQAtpc->GetPad(i)->SetLogx();
1052 canvasQAtof->GetPad(i)->SetLogx();
1053 canvasQAv0->GetPad(i)->SetLogx();
1054 canvasQAv0plusTOF->GetPad(i)->SetLogx();
1057 // 1. select and fit electrons
1059 hist->GetAxis(2)->SetRangeUser(0,0); // Non-V0s
1060 hist->GetAxis(3)->SetRangeUser(0,0); // electrons
1061 hist->GetAxis(4)->SetRangeUser(nSigmaElectronMinus,nSigmaElectronPlus); // 3sigma in TPC
1062 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1063 TH2D * histElectron = hist->Projection(1,0);
1064 histElectron->SetName("histElectron");
1065 histElectron->RebinX(4);
1066 histElectron->GetXaxis()->SetRangeUser(0.2,3.0);
1068 FitSlicesY(histElectron, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1069 TH1D * electronPoints = (TH1D *) arr.At(1)->Clone();
1071 TGraphErrors * electronGraph = new TGraphErrors(electronPoints);
1072 electronGraph->SetName("electronGraph");
1073 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
1074 Bool_t removePoint = electronGraph->GetY()[ip] < 10 ||
1075 electronGraph->GetEY()[ip]/electronGraph->GetY()[ip] > 0.05 ||
1076 electronGraph->GetX()[ip] > 2.0 ||
1077 electronGraph->GetX()[ip] < 0.5;
1079 electronGraph->RemovePoint(ip);
1086 histElectron->SetTitle("electrons");
1087 histElectron->GetYaxis()->SetRangeUser(50, 120);
1088 histElectron->GetXaxis()->SetTitle(momTitle.Data());
1089 histElectron->GetYaxis()->SetTitle(dEdxTitle.Data());
1090 histElectron->GetXaxis()->SetMoreLogLabels(kTRUE);
1091 histElectron->GetXaxis()->SetNoExponent(kTRUE);
1092 histElectron->Draw("colz");
1093 electronPoints->SetMarkerStyle(24);
1094 electronPoints->Draw("same");
1095 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1096 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1100 hist->GetAxis(2)->SetRangeUser(0,0); // Non-V0s
1101 hist->GetAxis(3)->SetRangeUser(3,3); // protons
1103 //hist->GetAxis(4)->SetRangeUser(nSigmaProtonMinus,nSigmaProtonPlus); // protons --> not reliable, use PATTERN RECOGNITION
1104 TH2D * histProtonTPC = hist->Projection(1,0);
1105 histProtonTPC->SetName("histProtonTPC");
1106 histProtonTPC->GetXaxis()->SetRangeUser(0.15,0.7);
1107 histProtonTPC->GetYaxis()->SetRangeUser(50, hist->GetAxis(1)->GetBinUpEdge(hist->GetAxis(1)->GetNbins()));
1109 // PATTERN RECOGNITION
1110 //OLD TF1 betaSq("betaSq","50./TMath::Power(x,1.3)",0.1,10);
1111 // Add some additional Erf - cuts away kaons for pPb and PbPb and does not hurt in pp
1112 TF1 betaSq("betaSq","50./TMath::Power(x,1.3) + (1-TMath::Erf((x-0.2) / 0.075)) * 100",0.1,10);
1113 for(Int_t ix = 1; ix <= histProtonTPC->GetXaxis()->GetNbins(); ix++) {
1114 for(Int_t jy = 1; jy <= histProtonTPC->GetYaxis()->GetNbins(); jy++) {
1115 Float_t yPos = histProtonTPC->GetYaxis()->GetBinCenter(jy);
1116 Float_t xPos = histProtonTPC->GetXaxis()->GetBinCenter(ix);
1117 Int_t bin = histProtonTPC->GetBin(ix,jy);
1118 if (yPos < betaSq.Eval(xPos)) histProtonTPC->SetBinContent(bin,0);
1122 //TODO Use likelihood option -> Inside fitting range ~no contamination, but little statistics at low momenta requires L
1123 FitSlicesY(histProtonTPC, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
1124 TH1D * protonPointsTPC = (TH1D *) arr.At(1)->Clone();
1126 TGraphErrors * protonTpcGraph = new TGraphErrors(protonPointsTPC);
1127 protonTpcGraph->SetName("protonTpcGraph");
1128 for(Int_t ip = 0; ip < protonTpcGraph->GetN(); ip ++) {
1129 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
1130 || 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
1131 //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
1133 protonTpcGraph->RemovePoint(ip);
1139 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1140 TH2D * histProtonTOF = hist->Projection(1,0);
1141 histProtonTOF->SetName("histProtonTOF");
1142 histProtonTOF->GetXaxis()->SetRangeUser(0.6,2.5);
1144 // Same pattern recognition as before
1145 for(Int_t ix = 1; ix <= histProtonTOF->GetXaxis()->GetNbins(); ix++) {
1146 for(Int_t jy = 1; jy <= histProtonTOF->GetYaxis()->GetNbins(); jy++) {
1147 Float_t yPos = histProtonTOF->GetYaxis()->GetBinCenter(jy);
1148 Float_t xPos = histProtonTOF->GetXaxis()->GetBinCenter(ix);
1149 Int_t bin = histProtonTOF->GetBin(ix,jy);
1150 if (yPos < betaSq.Eval(xPos)) histProtonTOF->SetBinContent(bin,0);
1154 FitSlicesY(histProtonTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1156 TH1D * protonPointsTOF = (TH1D *)arr.At(1)->Clone();
1158 TGraphErrors * protonTofGraph = new TGraphErrors(protonPointsTOF);
1159 protonTofGraph->SetName("protonTofGraph");
1160 for(Int_t ip = 0; ip < protonTofGraph->GetN(); ip ++) {
1161 // If V0s are to be used, TPC+TOF protons are only for reference and can be plotted to higher momenta
1162 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;
1164 protonTofGraph->RemovePoint(ip);
1171 histProtonTPC->SetTitle("protons");
1172 histProtonTPC->GetXaxis()->SetTitle(momTitle.Data());
1173 histProtonTPC->GetYaxis()->SetTitle(dEdxTitle.Data());
1174 histProtonTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
1175 histProtonTPC->GetXaxis()->SetNoExponent(kTRUE);
1176 histProtonTPC->Draw("colz");
1177 betaSq.DrawCopy("same");
1178 protonPointsTPC->SetMarkerStyle(20);
1179 protonPointsTOF->SetMarkerStyle(24);
1180 protonPointsTOF->Draw("same");
1181 protonPointsTPC->Draw("same");
1183 protonTpcGraph->SetMarkerStyle(26);
1184 protonTpcGraph->SetMarkerColor(kMagenta);
1185 protonTpcGraph->DrawClone("p");
1186 protonTofGraph->SetMarkerStyle(25);
1187 protonTofGraph->SetMarkerColor(kMagenta);
1188 protonTofGraph->DrawClone("p");
1191 histProtonTOF->SetTitle("protons");
1192 histProtonTOF->GetYaxis()->SetRangeUser(30, 250);
1193 histProtonTOF->GetXaxis()->SetTitle(momTitle.Data());
1194 histProtonTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1195 histProtonTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1196 histProtonTOF->GetXaxis()->SetNoExponent(kTRUE);
1197 histProtonTOF->Draw("colz");
1198 betaSq.DrawCopy("same");
1199 protonPointsTOF->Draw("same");
1200 protonPointsTPC->Draw("same");
1202 protonTpcGraph->DrawClone("p");
1203 protonTofGraph->DrawClone("p");
1205 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1206 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1210 hist->GetAxis(2)->SetRangeUser(0,0); // Non-V0s
1211 hist->GetAxis(3)->SetRangeUser(1,1); // pions
1213 Double_t lowerPionThreshold = 0.3;
1215 hist->GetAxis(4)->SetRangeUser(nSigmaPionMinus,nSigmaPionPlus); // pions
1216 TH2D * histPionTPC = hist->Projection(1,0);
1217 histPionTPC->SetName("histPionTPC");
1218 histPionTPC->GetXaxis()->SetRangeUser(0.15,0.7);
1219 FitSlicesY(histPionTPC, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1221 // In case of really bad splines comment last 5 lines and use the following 6 lines:
1222 //TH2D * histPionTPC = hist->Projection(1,0);
1223 //histPionTPC->SetName("histPionTPC");
1224 //histPionTPC->GetYaxis()->SetRangeUser(30,100);
1225 //histPionTPC->GetXaxis()->SetRangeUser(0.15,0.7);
1226 //FitSlicesY(histPionTPC, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1227 //lowerPionThreshold = 0.15;
1230 TH1D * pionPointsTPC = (TH1D *) arr.At(1)->Clone();
1232 TGraphErrors * pionTpcGraph = new TGraphErrors(pionPointsTPC);
1233 pionTpcGraph->SetName("pionTpcGraph");
1234 for(Int_t ip = 0; ip < pionTpcGraph->GetN(); ip ++) {
1235 Bool_t removePoint = pionTpcGraph->GetY()[ip] < 10 || pionTpcGraph->GetEY()[ip]/pionTpcGraph->GetY()[ip] > 0.02 || pionTpcGraph->GetX()[ip] > 0.5
1236 || pionTpcGraph->GetX()[ip] < lowerPionThreshold; // Exclude contamination by electrons
1238 pionTpcGraph->RemovePoint(ip);
1244 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1245 TH2D * histPionTOF = hist->Projection(1,0);
1246 histPionTOF->SetName("histPionTOF");
1247 histPionTOF->GetXaxis()->SetRangeUser(0.5,1.1);
1248 FitSlicesY(histPionTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1249 TH1D * pionPointsTOF = (TH1D *) arr.At(1)->Clone();
1250 TGraphErrors * pionTofGraph = new TGraphErrors(pionPointsTOF);
1251 pionTofGraph->SetName("pionTofGraph");
1252 for(Int_t ip = 0; ip < pionTofGraph->GetN(); ip ++) {
1253 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
1255 pionTofGraph->RemovePoint(ip);
1261 histPionTPC->GetYaxis()->SetRangeUser(30, 90);
1262 histPionTPC->SetTitle("pions");
1263 histPionTPC->GetXaxis()->SetTitle(momTitle.Data());
1264 histPionTPC->GetYaxis()->SetTitle(dEdxTitle.Data());
1265 histPionTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
1266 histPionTPC->GetXaxis()->SetNoExponent(kTRUE);
1267 histPionTPC->Draw("colz");
1268 pionPointsTPC->SetMarkerStyle(20);
1269 pionPointsTOF->SetMarkerStyle(24);
1270 pionPointsTOF->Draw("same");
1271 pionPointsTPC->Draw("same");
1273 pionTpcGraph->SetMarkerStyle(26);
1274 pionTpcGraph->SetMarkerColor(kMagenta);
1275 pionTpcGraph->DrawClone("p");
1276 pionTofGraph->SetMarkerStyle(25);
1277 pionTofGraph->SetMarkerColor(kMagenta);
1278 pionTofGraph->DrawClone("p");
1281 histPionTOF->GetYaxis()->SetRangeUser(30, 80);
1282 histPionTOF->GetXaxis()->SetTitle(momTitle.Data());
1283 histPionTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1284 histPionTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1285 histPionTOF->GetXaxis()->SetNoExponent(kTRUE);
1286 histPionTOF->Draw("colz");
1287 histPionTOF->SetTitle("pions");
1288 pionPointsTOF->Draw("same");
1289 pionPointsTPC->Draw("same");
1291 pionTpcGraph->DrawClone("p");
1292 pionTofGraph->DrawClone("p");
1295 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1296 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1300 hist->GetAxis(2)->SetRangeUser(0,0); // Non-V0s
1301 hist->GetAxis(3)->SetRangeUser(2,2); // kaons
1303 hist->GetAxis(4)->SetRangeUser(nSigmaKaonMinus,nSigmaKaonPlus); // kaons
1304 TH2D * histKaonTPC = hist->Projection(1,0);
1305 histKaonTPC->SetName("histKaonTPC");
1306 histKaonTPC->GetXaxis()->SetRangeUser(0.12,0.6999);
1307 FitSlicesY(histKaonTPC, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1308 TH1D * kaonPointsTPC = (TH1D*) arr.At(1)->Clone();
1310 TGraphErrors * kaonTpcGraph = new TGraphErrors(kaonPointsTPC);
1311 kaonTpcGraph->SetName("kaonTpcGraph");
1312 for(Int_t ip = 0; ip < kaonTpcGraph->GetN(); ip ++) {
1313 Bool_t removePoint = kaonTpcGraph->GetY()[ip] < 10 || kaonTpcGraph->GetEY()[ip]/kaonTpcGraph->GetY()[ip] > 0.02
1314 || kaonTpcGraph->GetX()[ip] < 0.12 || kaonTpcGraph->GetX()[ip] > 0.319; //TODO BEN was > 0.399
1316 kaonTpcGraph->RemovePoint(ip);
1323 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // sigma in TOF
1326 hist->GetAxis(5)->SetRangeUser(-1.999,1.999); // sigma in TOF
1328 if (hist->GetAxis(3)->GetNbins() >= 5) {
1329 printf("Using restricted eta range for TPC+TOF Kaons!\n");
1330 hist->GetAxis(3)->SetRangeUser(4,4);
1333 printf("WARNING: Data points for restricted eta range for TPC+TOF Kaons not available! Using full eta range (worse w.r.t. contamination)\n");
1336 TH2D * histKaonTOF = hist->Projection(1,0);
1337 histKaonTOF->SetName("histKaonTOF");
1338 histKaonTOF->GetXaxis()->SetRangeUser(0.3,1.5);
1339 FitSlicesY(histKaonTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1340 TH1D * kaonPointsTOF = (TH1D*) arr.At(1)->Clone();
1342 TGraphErrors * kaonTofGraph = new TGraphErrors(kaonPointsTOF);
1343 kaonTofGraph->SetName("kaonTofGraph");
1345 for(Int_t ip = 0; ip < kaonTofGraph->GetN(); ip ++) {
1346 Bool_t removePoint = kaonTofGraph->GetY()[ip] < 10 || kaonTofGraph->GetEY()[ip]/kaonTofGraph->GetY()[ip] > 0.02 || kaonTofGraph->GetX()[ip] > 1.0
1347 || kaonTofGraph->GetX()[ip] < 0.36; //TODO BEN NOW was 0.5
1349 kaonTofGraph->RemovePoint(ip);
1356 histKaonTPC->SetTitle("kaons");
1357 histKaonTPC->GetYaxis()->SetRangeUser(30, 500);
1358 histKaonTPC->GetXaxis()->SetTitle(momTitle.Data());
1359 histKaonTPC->GetYaxis()->SetTitle(dEdxTitle.Data());
1360 histKaonTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
1361 histKaonTPC->GetXaxis()->SetNoExponent(kTRUE);
1362 histKaonTPC->Draw("colz");
1363 kaonPointsTPC->SetMarkerStyle(20);
1364 kaonPointsTOF->SetMarkerStyle(24);
1365 kaonPointsTOF->Draw("same");
1366 kaonPointsTPC->Draw("same");
1368 kaonTpcGraph->SetMarkerStyle(26);
1369 kaonTpcGraph->SetMarkerColor(kMagenta);
1370 kaonTpcGraph->DrawClone("p");
1371 kaonTofGraph->SetMarkerStyle(25);
1372 kaonTofGraph->SetMarkerColor(kMagenta);
1373 kaonTofGraph->DrawClone("p");
1377 histKaonTOF->GetYaxis()->SetRangeUser(30, 250);
1378 histKaonTOF->SetTitle("kaons");
1379 histKaonTOF->GetXaxis()->SetTitle(momTitle.Data());
1380 histKaonTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1381 histKaonTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1382 histKaonTOF->GetXaxis()->SetNoExponent(kTRUE);
1383 histKaonTOF->Draw("colz");
1384 kaonPointsTOF->Draw("same");
1385 kaonPointsTPC->Draw("same");
1386 kaonTpcGraph->DrawClone("p");
1387 kaonTofGraph->DrawClone("p");
1389 hist->GetAxis(4)->SetRange(0,-1); // RESET RANGES
1390 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1396 hist->GetAxis(2)->SetRangeUser(1,1); // V0 electrons
1397 hist->GetAxis(3)->SetRangeUser(0,0); // electrons
1400 TH2D * histElectronV0 = hist->Projection(1,0);
1401 histElectronV0->SetName("histElectronV0");
1402 //histElectronV0->RebinX(2);
1403 histElectronV0->GetXaxis()->SetRangeUser(0.15,5.0);
1404 FitSlicesY(histElectronV0, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1405 TH1D * electronPointsV0 = (TH1D*) arr.At(1)->Clone();
1407 TGraphErrors * electronV0Graph = new TGraphErrors(electronPointsV0);
1408 electronV0Graph->SetName("electronV0Graph");
1409 for(Int_t ip = 0; ip < electronV0Graph->GetN(); ip ++) {
1410 Bool_t removePoint = electronV0Graph->GetY()[ip] < 10 || electronV0Graph->GetEY()[ip]/electronV0Graph->GetY()[ip] > 0.02;
1413 electronV0Graph->RemovePoint(ip);
1420 histElectronV0->SetTitle("V0 electrons");
1421 histElectronV0->GetYaxis()->SetRangeUser(50, 120);
1422 histElectronV0->GetXaxis()->SetTitle(momTitle.Data());
1423 histElectronV0->GetYaxis()->SetTitle(dEdxTitle.Data());
1424 histElectronV0->GetXaxis()->SetMoreLogLabels(kTRUE);
1425 histElectronV0->GetXaxis()->SetNoExponent(kTRUE);
1426 histElectronV0->SetStats(0);
1427 histElectronV0->Draw("colz");
1428 electronPointsV0->SetMarkerStyle(34);
1429 electronPointsV0->Draw("same");
1430 electronGraph->SetMarkerStyle(25);
1431 electronGraph->SetMarkerColor(kMagenta);
1432 electronGraph->DrawClone("p");
1434 canvasQAv0DeDxPurityEl->cd();
1435 gStyle->SetOptTitle(0);
1436 TH1D* hElNew = (TH1D*)histElectronV0->DrawClone("colz");
1437 hElNew->GetXaxis()->SetTitleOffset(1.0);
1438 hElNew->SetTitle("");
1439 electronPointsV0->DrawClone("same");
1440 gStyle->SetOptTitle(1);
1445 electronV0Graph->SetMarkerStyle(24);
1446 electronV0Graph->SetMarkerColor(kMagenta);
1447 electronV0Graph->DrawClone("p");
1452 hist->GetAxis(2)->SetRangeUser(2,2); // V0 pions
1453 hist->GetAxis(3)->SetRangeUser(1,1); // pions
1455 TH2D * histPionV0 = hist->Projection(1,0);
1456 histPionV0->SetName("histPionV0");
1457 histPionV0->GetXaxis()->SetRangeUser(0.15,10.);
1458 FitSlicesY(histPionV0, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1459 TH1D * pionPointsV0 = (TH1D*) arr.At(1)->Clone();
1461 TGraphErrors * pionV0Graph = new TGraphErrors(pionPointsV0);
1462 pionV0Graph->SetName("pionV0Graph");
1463 for(Int_t ip = 0; ip < pionV0Graph->GetN(); ip ++) {
1464 Bool_t removePoint = pionV0Graph->GetY()[ip] < 10 || pionV0Graph->GetEY()[ip]/pionV0Graph->GetY()[ip] > 0.02;
1467 pionV0Graph->RemovePoint(ip);
1474 histPionV0->SetTitle("V0 pions");
1475 histPionV0->GetYaxis()->SetRangeUser(30, 100);
1476 histPionV0->GetXaxis()->SetTitle(momTitle.Data());
1477 histPionV0->GetYaxis()->SetTitle(dEdxTitle.Data());
1478 histPionV0->GetXaxis()->SetMoreLogLabels(kTRUE);
1479 histPionV0->GetXaxis()->SetNoExponent(kTRUE);
1480 histPionV0->Draw("colz");
1481 pionPointsV0->SetMarkerStyle(34);
1482 pionPointsV0->Draw("same");
1483 pionTofGraph->DrawClone("p");
1484 pionTpcGraph->DrawClone("p");
1486 canvasQAv0DeDxPurityPi->cd();
1487 gStyle->SetOptTitle(0);
1488 TH1D* hPiNew = (TH1D*)histPionV0->DrawClone("colz");
1489 hPiNew->GetXaxis()->SetTitleOffset(1.0);
1490 hPiNew->SetTitle("");
1491 pionPointsV0->DrawClone("same");
1492 gStyle->SetOptTitle(1);
1495 pionV0Graph->SetMarkerStyle(24);
1496 pionV0Graph->SetMarkerColor(kMagenta);
1497 pionV0Graph->DrawClone("p");
1500 pionV0Graph->DrawClone("p");
1505 hist->GetAxis(2)->SetRangeUser(3,3); // V0 protons
1506 hist->GetAxis(3)->SetRangeUser(3,3); // protons
1508 TH2D * histProtonV0 = hist->Projection(1,0);
1509 histProtonV0->SetName("histProtonV0");
1510 histProtonV0->GetXaxis()->SetRangeUser(0.15,10.);
1512 // Remove contamination due to el and pions and low momenta because there the statistics
1513 // for the V0 protons goes down and becomes comparable with the contamination
1514 // -> This spoils the fit, if the contamination is not removed
1516 // PATTERN RECOGNITION
1517 Int_t correctionUpToBin = histProtonV0->GetXaxis()->FindBin(0.6);
1519 for(Int_t ix = 1; ix <= correctionUpToBin; ix++) {
1520 for(Int_t jy = 1; jy <= histProtonV0->GetYaxis()->GetNbins(); jy++) {
1521 Float_t yPos = histProtonV0->GetYaxis()->GetBinCenter(jy);
1522 Float_t xPos = histProtonV0->GetXaxis()->GetBinCenter(ix);
1523 Int_t bin = histProtonV0->GetBin(ix,jy);
1524 if (yPos < betaSq.Eval(xPos)) histProtonV0->SetBinContent(bin,0);
1529 Int_t correctionUpToBin = histProtonV0->GetXaxis()->FindBin(0.4);
1530 Double_t threshold = 120.;
1532 for(Int_t ix = 1; ix <= correctionUpToBin; ix++) {
1533 for(Int_t jy = 1; jy <= histProtonV0->GetYaxis()->GetNbins(); jy++) {
1534 Float_t yPos = histProtonV0->GetYaxis()->GetBinCenter(jy);
1535 Int_t bin = histProtonV0->GetBin(ix,jy);
1536 if (yPos < threshold) histProtonV0->SetBinContent(bin,0);
1542 FitSlicesY(histProtonV0, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1543 TH1D * protonPointsV0 = (TH1D*) arr.At(1)->Clone();
1545 TGraphErrors * protonV0Graph = new TGraphErrors(protonPointsV0);
1546 protonV0Graph->SetName("protonV0Graph");
1547 for(Int_t ip = 0; ip < protonV0Graph->GetN(); ip ++) {
1548 Bool_t removePoint = protonV0Graph->GetY()[ip] < 10 || protonV0Graph->GetEY()[ip]/protonV0Graph->GetY()[ip] > 0.02;
1551 protonV0Graph->RemovePoint(ip);
1558 histProtonV0->SetTitle("V0 protons");
1559 histProtonV0->GetXaxis()->SetTitle(momTitle.Data());
1560 histProtonV0->GetYaxis()->SetTitle(dEdxTitle.Data());
1561 histProtonV0->GetXaxis()->SetMoreLogLabels(kTRUE);
1562 histProtonV0->GetXaxis()->SetNoExponent(kTRUE);
1563 histProtonV0->Draw("colz");
1564 protonPointsV0->SetMarkerStyle(34);
1565 protonPointsV0->Draw("same");
1566 protonTofGraph->DrawClone("p");
1567 protonTpcGraph->DrawClone("p");
1569 canvasQAv0DeDxPurityPr->cd();
1570 gStyle->SetOptTitle(0);
1571 TH1D* hPrNew = (TH1D*)histProtonV0->DrawClone("colz");
1572 hPrNew->GetXaxis()->SetTitleOffset(1.0);
1573 hPrNew->SetTitle("");
1574 protonPointsV0->DrawClone("same");
1575 gStyle->SetOptTitle(1);
1578 protonV0Graph->SetMarkerStyle(24);
1579 protonV0Graph->SetMarkerColor(kMagenta);
1580 protonV0Graph->DrawClone("p");
1583 protonV0Graph->DrawClone("p");
1586 hist->GetAxis(2)->SetRange(0,-1); // RESET RANGES
1587 hist->GetAxis(3)->SetRange(0,-1); // RESET RANGES
1591 // 5. V0 electrons + TOF
1593 hist->GetAxis(2)->SetRangeUser(1,1); // V0 electrons
1594 hist->GetAxis(3)->SetRangeUser(0,0); // electrons
1595 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1597 TH2D * histElectronV0plusTOF = hist->Projection(1,0);
1598 histElectronV0plusTOF->SetName("histElectronV0plusTOF");
1599 histElectronV0plusTOF->RebinX(2);
1600 histElectronV0plusTOF->GetXaxis()->SetRangeUser(0.2,5.0);
1601 FitSlicesY(histElectronV0plusTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1602 TH1D * electronPointsV0plusTOF = (TH1D*) arr.At(1)->Clone();
1604 TGraphErrors * electronV0plusTOFGraph = new TGraphErrors(electronPointsV0plusTOF);
1605 electronV0plusTOFGraph->SetName("electronV0plusTOFGraph");
1606 for(Int_t ip = 0; ip < electronV0plusTOFGraph->GetN(); ip ++) {
1607 Bool_t removePoint = electronV0plusTOFGraph->GetY()[ip] < 10 || electronV0plusTOFGraph->GetEY()[ip]/electronV0plusTOFGraph->GetY()[ip] > 0.02;
1610 electronV0plusTOFGraph->RemovePoint(ip);
1616 canvasQAv0plusTOF->cd(1);
1617 histElectronV0plusTOF->SetTitle("V0+TOF electrons");
1618 histElectronV0plusTOF->GetYaxis()->SetRangeUser(50, 120);
1619 histElectronV0plusTOF->GetXaxis()->SetTitle(momTitle.Data());
1620 histElectronV0plusTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1621 histElectronV0plusTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1622 histElectronV0plusTOF->GetXaxis()->SetNoExponent(kTRUE);
1623 histElectronV0plusTOF->Draw("colz");
1624 electronPointsV0plusTOF->SetMarkerStyle(29);
1625 electronPointsV0plusTOF->Draw("same");
1626 electronGraph->DrawClone("p");
1627 electronV0Graph->DrawClone("p");
1630 electronV0plusTOFGraph->SetMarkerStyle(30);
1631 electronV0plusTOFGraph->SetMarkerColor(kMagenta);
1632 electronV0plusTOFGraph->DrawClone("p");
1635 electronV0plusTOFGraph->DrawClone("p");
1638 // 6. V0 pions + TOF
1640 hist->GetAxis(2)->SetRangeUser(2,2); // V0 pions
1641 hist->GetAxis(3)->SetRangeUser(1,1); // pions
1642 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1644 TH2D * histPionV0plusTOF = hist->Projection(1,0);
1645 histPionV0plusTOF->SetName("histPionV0plusTOF");
1646 histPionV0plusTOF->GetXaxis()->SetRangeUser(0.15,10.);
1647 FitSlicesY(histPionV0plusTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1648 TH1D * pionPointsV0plusTOF = (TH1D*) arr.At(1)->Clone();
1650 TGraphErrors * pionV0plusTOFGraph = new TGraphErrors(pionPointsV0plusTOF);
1651 pionV0plusTOFGraph->SetName("pionV0plusTOFGraph");
1652 for(Int_t ip = 0; ip < pionV0plusTOFGraph->GetN(); ip ++) {
1653 Bool_t removePoint = pionV0plusTOFGraph->GetY()[ip] < 10 || pionV0plusTOFGraph->GetEY()[ip]/pionV0plusTOFGraph->GetY()[ip] > 0.02;
1656 pionV0plusTOFGraph->RemovePoint(ip);
1662 canvasQAv0plusTOF->cd(3);
1663 histPionV0plusTOF->SetTitle("V0+TOF pions");
1664 histPionV0plusTOF->GetYaxis()->SetRangeUser(30, 100);
1665 histPionV0plusTOF->GetXaxis()->SetTitle(momTitle.Data());
1666 histPionV0plusTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1667 histPionV0plusTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1668 histPionV0plusTOF->GetXaxis()->SetNoExponent(kTRUE);
1669 histPionV0plusTOF->Draw("colz");
1670 pionPointsV0plusTOF->SetMarkerStyle(29);
1671 pionPointsV0plusTOF->Draw("same");
1672 pionV0Graph->DrawClone("p");
1673 pionTofGraph->DrawClone("p");
1674 pionTpcGraph->DrawClone("p");
1677 pionV0plusTOFGraph->SetMarkerStyle(30);
1678 pionV0plusTOFGraph->SetMarkerColor(kMagenta);
1679 pionV0plusTOFGraph->DrawClone("p");
1682 pionV0plusTOFGraph->DrawClone("p");
1685 pionV0plusTOFGraph->DrawClone("p");
1688 // 6. V0 protons + TOF
1690 hist->GetAxis(2)->SetRangeUser(3,3); // V0 protons
1691 hist->GetAxis(3)->SetRangeUser(3,3); // protons
1692 hist->GetAxis(5)->SetRangeUser(-2.999,2.999); // 3sigma in TOF
1694 TH2D * histProtonV0plusTOF = hist->Projection(1,0);
1695 histProtonV0plusTOF->SetName("histProtonV0plusTOF");
1696 histProtonV0plusTOF->GetXaxis()->SetRangeUser(0.15,10.);
1698 // Remove contamination due to el and pions and low momenta because there the statistics
1699 // for the V0 protons goes down and becomes comparable with the contamination
1700 // -> This spoils the fit, if the contamination is not removed
1702 // PATTERN RECOGNITION
1703 correctionUpToBin = histProtonV0plusTOF->GetXaxis()->FindBin(0.6);
1705 for(Int_t ix = 1; ix <= correctionUpToBin; ix++) {
1706 for(Int_t jy = 1; jy <= histProtonV0plusTOF->GetYaxis()->GetNbins(); jy++) {
1707 Float_t yPos = histProtonV0plusTOF->GetYaxis()->GetBinCenter(jy);
1708 Float_t xPos = histProtonV0plusTOF->GetXaxis()->GetBinCenter(ix);
1709 Int_t bin = histProtonV0plusTOF->GetBin(ix,jy);
1710 if (yPos < betaSq.Eval(xPos)) histProtonV0plusTOF->SetBinContent(bin,0);
1714 FitSlicesY(histProtonV0plusTOF, heightFractionForFittingRange, cutForFitting, "QNR", &arr);
1715 TH1D * protonPointsV0plusTOF = (TH1D*) arr.At(1)->Clone();
1717 TGraphErrors * protonV0plusTOFGraph = new TGraphErrors(protonPointsV0plusTOF);
1718 protonV0plusTOFGraph->SetName("protonV0plusTOFGraph");
1719 for(Int_t ip = 0; ip < protonV0plusTOFGraph->GetN(); ip ++) {
1720 Bool_t removePoint = protonV0plusTOFGraph->GetY()[ip] < 10 || protonV0plusTOFGraph->GetEY()[ip]/protonV0plusTOFGraph->GetY()[ip] > 0.02;
1723 protonV0plusTOFGraph->RemovePoint(ip);
1729 canvasQAv0plusTOF->cd(2);
1730 histProtonV0plusTOF->SetTitle("V0+TOF protons");
1731 histProtonV0plusTOF->GetXaxis()->SetTitle(momTitle.Data());
1732 histProtonV0plusTOF->GetYaxis()->SetTitle(dEdxTitle.Data());
1733 histProtonV0plusTOF->GetXaxis()->SetMoreLogLabels(kTRUE);
1734 histProtonV0plusTOF->GetXaxis()->SetNoExponent(kTRUE);
1735 histProtonV0plusTOF->Draw("colz");
1736 protonPointsV0plusTOF->SetMarkerStyle(29);
1737 protonPointsV0plusTOF->Draw("same");
1738 protonV0Graph->DrawClone("p");
1739 protonTofGraph->DrawClone("p");
1740 protonTpcGraph->DrawClone("p");
1743 protonV0plusTOFGraph->SetMarkerStyle(30);
1744 protonV0plusTOFGraph->SetMarkerColor(kMagenta);
1745 protonV0plusTOFGraph->DrawClone("p");
1748 protonV0plusTOFGraph->DrawClone("p");
1751 protonV0plusTOFGraph->DrawClone("p");
1753 hist->GetAxis(2)->SetRange(0,-1); // RESET RANGES
1754 hist->GetAxis(3)->SetRange(0,-1); // RESET RANGES
1755 hist->GetAxis(5)->SetRange(0,-1); // RESET RANGES
1758 // Clone (V0, V0+TOF) graphs: Remove some points, which are expected to deviate from the Bethe-Bloch curve, from the original graphs, so that
1759 // these graphs can be used for the BB fit. The original graph will keep all point in order to determine the correction and response
1761 TGraphErrors * electronV0GraphForBBfit = new TGraphErrors(*electronV0Graph);
1762 electronV0GraphForBBfit->SetName("electronV0GraphForBBfit");
1764 for(Int_t ip = 0; ip < electronV0GraphForBBfit->GetN(); ip ++) {
1765 Bool_t removePoint = electronV0GraphForBBfit->GetX()[ip] < (isPPb ? 1.2 : 0.4);// || electronV0GraphForBBfit->GetX()[ip] > 2.2;
1768 electronV0GraphForBBfit->RemovePoint(ip);
1774 TGraphErrors * pionV0GraphForBBfit = new TGraphErrors(*pionV0Graph);
1775 pionV0GraphForBBfit->SetName("pionV0GraphForBBfit");
1777 for(Int_t ip = 0; ip < pionV0GraphForBBfit->GetN(); ip ++) {
1778 Bool_t removePoint = pionV0GraphForBBfit->GetX()[ip] < (isPPb ? 1.0 : 0.76);// || pionV0GraphForBBfit->GetX()[ip] > 6.; //TODO NOW was < 0.4 before
1779 //Bool_t removePoint = pionV0GraphForBBfit->GetX()[ip] < 0.4 || pionV0GraphForBBfit->GetX()[ip] > 0.399;// In this case NOT used for BB fit
1781 pionV0GraphForBBfit->RemovePoint(ip);
1787 TGraphErrors * protonV0GraphForBBfit = new TGraphErrors(*protonV0Graph);
1788 protonV0GraphForBBfit->SetName("protonV0GraphForBBfit");
1790 for(Int_t ip = 0; ip < protonV0GraphForBBfit->GetN(); ip ++) {
1791 Bool_t removePoint = protonV0GraphForBBfit->GetX()[ip] < 0.9 || protonV0GraphForBBfit->GetX()[ip] > 5.0; //TODO NOW was 2.5 before
1792 //Bool_t removePoint = protonV0GraphForBBfit->GetX()[ip] < 0.9 || protonV0GraphForBBfit->GetX()[ip] > 0.599;// In this case NOT used for BB fit
1794 protonV0GraphForBBfit->RemovePoint(ip);
1802 TGraphErrors * electronV0plusTOFGraphForBBfit = new TGraphErrors(*electronV0plusTOFGraph);
1803 electronV0plusTOFGraphForBBfit->SetName("electronV0plusTOFGraphForBBfit");
1805 for(Int_t ip = 0; ip < electronV0plusTOFGraphForBBfit->GetN(); ip ++) {
1806 Bool_t removePoint = electronV0plusTOFGraphForBBfit->GetX()[ip] < (isPPb ? 1.2 : 0.6);//0.4 || electronV0plusTOFGraphForBBfit->GetX()[ip] > 1.3799;
1808 electronV0plusTOFGraphForBBfit->RemovePoint(ip);
1814 TGraphErrors * pionV0plusTOFGraphForBBfit = new TGraphErrors(*pionV0plusTOFGraph);
1815 pionV0plusTOFGraphForBBfit->SetName("pionV0plusTOFGraphForBBfit");
1817 for(Int_t ip = 0; ip < pionV0plusTOFGraphForBBfit->GetN(); ip ++) {
1818 Bool_t removePoint = pionV0plusTOFGraphForBBfit->GetX()[ip] < 0.4;// || pionV0plusTOFGraphForBBfit->GetX()[ip] > 6.;
1820 pionV0plusTOFGraphForBBfit->RemovePoint(ip);
1826 TGraphErrors * protonV0plusTOFGraphForBBfit = new TGraphErrors(*protonV0plusTOFGraph);
1827 protonV0plusTOFGraphForBBfit->SetName("protonV0plusTOFGraphForBBfit");
1829 for(Int_t ip = 0; ip < protonV0plusTOFGraphForBBfit->GetN(); ip ++) {
1830 Bool_t removePoint = protonV0plusTOFGraphForBBfit->GetX()[ip] < 0.9 || protonV0plusTOFGraphForBBfit->GetX()[ip] > 2.5;
1832 protonV0plusTOFGraphForBBfit->RemovePoint(ip);
1840 // rescale graphs to betaGamma
1842 kaonTofGraph->SetMarkerStyle(21);
1843 kaonTpcGraph->SetMarkerStyle(22);
1844 for(Int_t ip = 0; ip < kaonTofGraph->GetN(); ip ++) {
1845 kaonTofGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
1846 kaonTofGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
1848 for(Int_t ip = 0; ip < kaonTpcGraph->GetN(); ip ++) {
1849 kaonTpcGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
1850 kaonTpcGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
1853 electronGraph->SetMarkerStyle(22);
1854 electronV0Graph->SetMarkerStyle(34);
1855 electronV0GraphForBBfit->SetMarkerStyle(34);
1856 electronV0plusTOFGraph->SetMarkerStyle(30);
1857 electronV0plusTOFGraphForBBfit->SetMarkerStyle(30);
1858 electronGraph->SetMarkerColor(2);
1859 electronV0Graph->SetMarkerColor(2);
1860 electronV0GraphForBBfit->SetMarkerColor(2);
1861 electronV0plusTOFGraph->SetMarkerColor(2);
1862 electronV0plusTOFGraphForBBfit->SetMarkerColor(2);
1863 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
1864 electronGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1865 electronGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1867 for(Int_t ip = 0; ip < electronV0Graph->GetN(); ip ++) {
1868 electronV0Graph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1869 electronV0Graph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1871 for(Int_t ip = 0; ip < electronV0GraphForBBfit->GetN(); ip ++) {
1872 electronV0GraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1873 electronV0GraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1875 for(Int_t ip = 0; ip < electronV0plusTOFGraph->GetN(); ip ++) {
1876 electronV0plusTOFGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1877 electronV0plusTOFGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1879 for(Int_t ip = 0; ip < electronV0plusTOFGraphForBBfit->GetN(); ip ++) {
1880 electronV0plusTOFGraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1881 electronV0plusTOFGraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
1884 pionTofGraph->SetMarkerStyle(21);
1885 pionTpcGraph->SetMarkerStyle(22);
1886 pionV0Graph->SetMarkerStyle(34);
1887 pionV0GraphForBBfit->SetMarkerStyle(34);
1888 pionV0plusTOFGraph->SetMarkerStyle(30);
1889 pionV0plusTOFGraphForBBfit->SetMarkerStyle(30);
1890 pionTofGraph->SetMarkerColor(3);
1891 pionTpcGraph->SetMarkerColor(3);
1892 pionV0Graph->SetMarkerColor(3);
1893 pionV0GraphForBBfit->SetMarkerColor(3);
1894 pionV0plusTOFGraph->SetMarkerColor(3);
1895 pionV0plusTOFGraphForBBfit->SetMarkerColor(3);
1896 for(Int_t ip = 0; ip < pionTofGraph->GetN(); ip ++) {
1897 pionTofGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1898 pionTofGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1900 for(Int_t ip = 0; ip < pionTpcGraph->GetN(); ip ++) {
1901 pionTpcGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1902 pionTpcGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1904 for(Int_t ip = 0; ip < pionV0Graph->GetN(); ip ++) {
1905 pionV0Graph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1906 pionV0Graph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1908 for(Int_t ip = 0; ip < pionV0GraphForBBfit->GetN(); ip ++) {
1909 pionV0GraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1910 pionV0GraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1912 for(Int_t ip = 0; ip < pionV0plusTOFGraph->GetN(); ip ++) {
1913 pionV0plusTOFGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1914 pionV0plusTOFGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1916 for(Int_t ip = 0; ip < pionV0plusTOFGraphForBBfit->GetN(); ip ++) {
1917 pionV0plusTOFGraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1918 pionV0plusTOFGraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
1921 protonTofGraph->SetMarkerStyle(21);
1922 protonTpcGraph->SetMarkerStyle(22);
1923 protonV0Graph->SetMarkerStyle(34);
1924 protonV0GraphForBBfit->SetMarkerStyle(34);
1925 protonV0plusTOFGraph->SetMarkerStyle(30);
1926 protonV0plusTOFGraphForBBfit->SetMarkerStyle(30);
1927 protonTofGraph->SetMarkerColor(4);
1928 protonTpcGraph->SetMarkerColor(4);
1929 protonV0Graph->SetMarkerColor(4);
1930 protonV0GraphForBBfit->SetMarkerColor(4);
1931 protonV0plusTOFGraph->SetMarkerColor(4);
1932 protonV0plusTOFGraphForBBfit->SetMarkerColor(4);
1933 for(Int_t ip = 0; ip < protonTofGraph->GetN(); ip ++) {
1934 protonTofGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1935 protonTofGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1937 for(Int_t ip = 0; ip < protonTpcGraph->GetN(); ip ++) {
1938 protonTpcGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1939 protonTpcGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1941 for(Int_t ip = 0; ip < protonV0Graph->GetN(); ip ++) {
1942 protonV0Graph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1943 protonV0Graph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1945 for(Int_t ip = 0; ip < protonV0GraphForBBfit->GetN(); ip ++) {
1946 protonV0GraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1947 protonV0GraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1949 for(Int_t ip = 0; ip < protonV0plusTOFGraph->GetN(); ip ++) {
1950 protonV0plusTOFGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1951 protonV0plusTOFGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1953 for(Int_t ip = 0; ip < protonV0plusTOFGraphForBBfit->GetN(); ip ++) {
1954 protonV0plusTOFGraphForBBfit->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1955 protonV0plusTOFGraphForBBfit->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
1959 TGraphErrors * graphAll = new TGraphErrors();
1960 TList * listColl = new TList();
1962 //listColl->Add(protonTpcGraph);
1963 //listColl->Add(kaonTpcGraph);
1964 listColl->Add(pionTpcGraph);
1965 listColl->Add(electronGraph);
1966 listColl->Add(protonTofGraph);
1967 listColl->Add(kaonTofGraph);
1968 listColl->Add(pionTofGraph);
1971 listColl->Add(pionV0GraphForBBfit);
1972 //listColl->Add(electronV0GraphForBBfit);
1973 listColl->Add(protonV0GraphForBBfit);
1975 //listColl->Add(pionV0plusTOFGraphForBBfit);
1976 listColl->Add(electronV0plusTOFGraphForBBfit);
1977 //listColl->Add(protonV0plusTOFGraphForBBfit);
1979 MergeGraphErrors(graphAll, listColl);
1980 graphAll->SetNameTitle("beamDataPoints","beamDataPoints");
1982 // Create graph out of TPC only, V0, V0+TOF and TPC+TOF to determine correction functions
1983 TList * listCollPr = new TList();
1985 listCollPr->Add(protonTpcGraph);
1986 //listCollPr->Add(protonTofGraph);
1988 TGraphErrors * protonV0GraphCut = new TGraphErrors(*protonV0Graph);
1989 protonV0GraphCut->SetName("protonV0GraphCut");
1990 for(Int_t ip = 0; ip < protonV0GraphCut->GetN(); ip ++) {
1991 Double_t mom = protonV0GraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kProton);
1992 //Bool_t removePoint = mom >= 0.6 || mom < 0.35; // Will take TPC protons instead (statistics) for very low momenta
1993 Bool_t removePoint = mom < (isPPb ? 0.6 : 0.35); // Will take TPC protons instead (statistics) for very low momenta;
1994 // for pPb low statistics for the moment, therefore, go a bit further with TPC protons
1998 protonV0GraphCut->RemovePoint(ip);
2004 TGraphErrors * protonV0plusTOFGraphCut = new TGraphErrors(*protonV0plusTOFGraph);
2005 protonV0plusTOFGraphCut->SetName("protonV0plusTOFGraphCut");
2006 for(Int_t ip = 0; ip < protonV0plusTOFGraphCut->GetN(); ip ++) {
2007 Double_t mom = protonV0plusTOFGraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kProton);
2008 Bool_t removePoint = mom < 0.6;
2011 protonV0plusTOFGraphCut->RemovePoint(ip);
2017 listCollPr->Add(protonV0GraphCut);
2018 //listCollPr->Add(protonV0plusTOFGraphCut);
2021 listCollPr->Add(protonTpcGraph);
2022 listCollPr->Add(protonTofGraph);
2024 TGraphErrors * graphPrCombined = new TGraphErrors();
2025 MergeGraphErrors(graphPrCombined, listCollPr);
2026 graphPrCombined->SetMarkerStyle(22);
2027 graphPrCombined->SetMarkerColor(4);
2028 graphPrCombined->SetNameTitle("Graph_Protons_Combined", "Graph_Protons_Combined");
2030 TList * listCollPi = new TList();
2032 //listCollPi->Add(pionTpcGraph);
2033 //listCollPi->Add(pionTofGraph);
2035 TGraphErrors * pionV0GraphCut = new TGraphErrors(*pionV0Graph);
2036 pionV0GraphCut->SetName("pionV0GraphCut");
2037 for(Int_t ip = 0; ip < pionV0GraphCut->GetN(); ip ++) {
2038 //Double_t mom = pionV0GraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kPion);
2039 Bool_t removePoint = kFALSE;//mom >= 0.4;
2040 //|| mom < 0.2;//TODO NOW NEEDED?
2042 pionV0GraphCut->RemovePoint(ip);
2048 TGraphErrors * pionV0plusTOFGraphCut = new TGraphErrors(*pionV0plusTOFGraph);
2049 pionV0plusTOFGraphCut->SetName("pionV0plusTOFGraphCut");
2050 for(Int_t ip = 0; ip < pionV0plusTOFGraphCut->GetN(); ip ++) {
2051 Double_t mom = pionV0plusTOFGraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kPion);
2052 Bool_t removePoint = mom < 0.4;
2055 pionV0plusTOFGraphCut->RemovePoint(ip);
2061 listCollPi->Add(pionV0GraphCut);
2062 //listCollPi->Add(pionV0plusTOFGraphCut);
2065 listCollPi->Add(pionTpcGraph);
2066 listCollPi->Add(pionTofGraph);
2068 TGraphErrors * graphPiCombined = new TGraphErrors();
2069 MergeGraphErrors(graphPiCombined, listCollPi);
2070 graphPiCombined->SetMarkerStyle(22);
2071 graphPiCombined->SetMarkerColor(3);
2072 graphPiCombined->SetNameTitle("Graph_Pions_Combined", "Graph_Pions_Combined");
2074 TList * listCollKa = new TList();
2075 listCollKa->Add(kaonTpcGraph);
2076 listCollKa->Add(kaonTofGraph);
2077 TGraphErrors * graphKaCombined = new TGraphErrors();
2078 MergeGraphErrors(graphKaCombined, listCollKa);
2079 graphKaCombined->SetMarkerStyle(22);
2080 graphKaCombined->SetMarkerColor(5);
2081 graphKaCombined->SetNameTitle("Graph_Kaons_Combined", "Graph_Kaons_Combined");
2083 TList * listCollEl = new TList();
2085 //listCollEl->Add(electronGraph);
2087 TGraphErrors * electronV0GraphCut = new TGraphErrors(*electronV0Graph);
2088 electronV0GraphCut->SetName("electronV0GraphCut");
2090 for(Int_t ip = 0; ip < electronV0GraphCut->GetN(); ip ++) {
2091 Double_t mom = electronV0GraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kElectron);
2092 Bool_t removePoint = mom > 0.3;
2094 electronV0GraphCut->RemovePoint(ip);
2100 TGraphErrors * electronV0plusTOFGraphCut = new TGraphErrors(*electronV0plusTOFGraph);
2101 electronV0plusTOFGraphCut->SetName("electronV0plusTOFGraphCut");
2102 for(Int_t ip = 0; ip < electronV0plusTOFGraphCut->GetN(); ip ++) {
2103 Double_t mom = electronV0plusTOFGraphCut->GetX()[ip] * AliPID::ParticleMass(AliPID::kElectron);
2104 Bool_t removePoint = mom <= 0.4;
2107 electronV0plusTOFGraphCut->RemovePoint(ip);
2113 listCollEl->Add(electronV0GraphCut);
2114 //listCollEl->Add(electronV0plusTOFGraphCut);
2117 listCollEl->Add(electronGraph);
2119 TGraphErrors * graphElCombined = new TGraphErrors();
2120 MergeGraphErrors(graphElCombined, listCollEl);
2121 graphElCombined->SetMarkerStyle(22);
2122 graphElCombined->SetMarkerColor(2);
2123 graphElCombined->SetNameTitle("Graph_Electrons_Combined", "Graph_Electrons_Combined");
2128 // return array with all graphs
2130 TObjArray * arrGraphs = new TObjArray();
2131 arrGraphs->Add(graphAll);
2133 arrGraphs->Add(electronGraph);
2134 arrGraphs->Add(electronV0Graph);
2135 arrGraphs->Add(electronV0plusTOFGraph);
2136 arrGraphs->Add(electronV0GraphForBBfit);
2137 arrGraphs->Add(pionTpcGraph);
2138 arrGraphs->Add(pionTofGraph);
2139 arrGraphs->Add(pionV0Graph);
2140 arrGraphs->Add(pionV0plusTOFGraph);
2141 arrGraphs->Add(pionV0GraphForBBfit);
2142 arrGraphs->Add(kaonTpcGraph);
2143 arrGraphs->Add(kaonTofGraph);
2144 arrGraphs->Add(protonTpcGraph);
2145 arrGraphs->Add(protonTofGraph);
2146 arrGraphs->Add(protonV0Graph);
2147 arrGraphs->Add(protonV0plusTOFGraph);
2148 arrGraphs->Add(protonV0GraphForBBfit);
2150 arrGraphs->Add(graphElCombined);
2151 arrGraphs->Add(graphPiCombined);
2152 arrGraphs->Add(graphKaCombined);
2153 arrGraphs->Add(graphPrCombined);
2157 canvasQAtpc->SaveAs("splines_QA_ResidualGraphsTPC.root");
2158 canvasQAtof->SaveAs("splines_QA_ResidualGraphsTOF.root");
2159 canvasQAv0->SaveAs("splines_QA_ResidualGraphsV0.root");
2160 canvasQAv0plusTOF->SaveAs("splines_QA_ResidualGraphsV0plusTOF.root");
2163 canvasQAv0DeDxPurityEl->SaveAs("V0_dEdx_purity_el.root");
2164 canvasQAv0DeDxPurityPi->SaveAs("V0_dEdx_purity_Pi.root");
2165 canvasQAv0DeDxPurityPr->SaveAs("V0_dEdx_purity_Pr.root");
2172 //________________________________________________________________________
2173 TObjArray * AliTPCcalibResidualPID::GetResidualGraphsMC(THnSparseF * histPidQA, const Char_t * /*system*/) {
2175 // Extracts the residual graphs from THnSparse created from MC (NOT DATA!)
2178 const TString momTitle = "#it{p}_{TPC} (GeV/#it{c})";
2179 const TString dEdxTitle = "d#it{E}/d#it{x} (arb. unit)";
2181 Int_t cutForFitting = 10;
2182 Double_t heightFractionForFittingRange = 0.1;
2185 THnSparse * hist = histPidQA;
2187 TCanvas * canvasQAmc = new TCanvas("canvasQAmcResGraph","Control canvas for residual graphs (MC)",100,10,1380,800);
2188 canvasQAmc->Divide(2,2);
2190 for (Int_t i = 1; i <= 4; i++) {
2191 canvasQAmc->GetPad(i)->SetGrid(1, 1);
2192 canvasQAmc->GetPad(i)->SetLogz();
2193 canvasQAmc->GetPad(i)->SetLogx();
2196 // 1. select and fit electrons
2198 // 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
2199 hist->GetAxis(2)->SetRangeUser(0,0); // electrons
2200 hist->GetAxis(3)->SetRangeUser(0,0); // electrons (used for nsigma and for the eta correction of the signal)
2201 TH2D * histElectron = hist->Projection(1,0);
2202 histElectron->SetName("histElectron");
2203 histElectron->RebinX(2);
2204 histElectron->GetXaxis()->SetRangeUser(0.15,8.0);
2206 FitSlicesY(histElectron, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
2207 TH1D * electronPoints = (TH1D *) arr.At(1)->Clone();
2209 TGraphErrors * electronGraph = new TGraphErrors(electronPoints);
2210 electronGraph->SetName("electronGraphMC");
2211 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
2212 Bool_t removePoint = electronGraph->GetY()[ip] < 10 || electronGraph->GetEY()[ip]/electronGraph->GetY()[ip] > 0.03
2213 || electronGraph->GetX()[ip] < 0.15;// || electronGraph->GetX()[ip] > 3.1;
2215 electronGraph->RemovePoint(ip);
2222 histElectron->SetTitle("electrons");
2223 histElectron->GetYaxis()->SetRangeUser(50, 120);
2224 histElectron->GetXaxis()->SetTitle(momTitle.Data());
2225 histElectron->GetYaxis()->SetTitle(dEdxTitle.Data());
2226 histElectron->GetXaxis()->SetMoreLogLabels(kTRUE);
2227 histElectron->GetXaxis()->SetNoExponent(kTRUE);
2228 histElectron->Draw("colz");
2229 electronPoints->SetMarkerStyle(24);
2230 electronPoints->Draw("same");
2234 hist->GetAxis(2)->SetRangeUser(3,3); // protons
2235 hist->GetAxis(3)->SetRangeUser(3,3); // protons (used for nsigma and for the eta correction of the signal)
2237 TH2D * histProton = hist->Projection(1,0);
2238 histProton->SetName("histProton");
2239 histProton->GetXaxis()->SetRangeUser(0.15,8);
2240 histProton->GetYaxis()->SetRangeUser(10, hist->GetAxis(1)->GetBinUpEdge(hist->GetAxis(1)->GetNbins()));
2241 FitSlicesY(histProton, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
2242 TH1D * protonPoints = (TH1D *) arr.At(1)->Clone();
2244 TGraphErrors * protonGraph = new TGraphErrors(protonPoints);
2245 protonGraph->SetName("protonGraphMC");
2246 for(Int_t ip = 0; ip < protonGraph->GetN(); ip ++) {
2247 Bool_t removePoint = protonGraph->GetY()[ip] < 10 || protonGraph->GetEY()[ip]/protonGraph->GetY()[ip] > 0.02 ||
2248 protonGraph->GetX()[ip] < 0.15 || protonGraph->GetX()[ip] > 6;
2250 protonGraph->RemovePoint(ip);
2257 histProton->SetTitle("protons");
2258 histProton->GetXaxis()->SetTitle(momTitle.Data());
2259 histProton->GetYaxis()->SetTitle(dEdxTitle.Data());
2260 histProton->GetXaxis()->SetMoreLogLabels(kTRUE);
2261 histProton->GetXaxis()->SetNoExponent(kTRUE);
2262 histProton->Draw("colz");
2263 protonPoints->SetMarkerStyle(20);
2264 protonPoints->Draw("same");
2269 hist->GetAxis(2)->SetRangeUser(1,1); // pions
2270 hist->GetAxis(3)->SetRangeUser(1,1); // pions (used for nsigma and for the eta correction of the signal)
2272 TH2D * histPion = hist->Projection(1,0);
2273 histPion->SetName("histPion");
2274 histPion->GetXaxis()->SetRangeUser(0.15,50);
2275 FitSlicesY(histPion, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
2276 TH1D * pionPoints = (TH1D *) arr.At(1)->Clone();
2278 TGraphErrors * pionGraph = new TGraphErrors(pionPoints);
2279 pionGraph->SetName("pionGraphMC");
2280 for(Int_t ip = 0; ip < pionGraph->GetN(); ip ++) {
2281 Bool_t removePoint = pionGraph->GetY()[ip] < 10 || pionGraph->GetEY()[ip]/pionGraph->GetY()[ip] > 0.005
2282 || pionGraph->GetX()[ip] < 0.15 || pionGraph->GetX()[ip] > 30;
2284 pionGraph->RemovePoint(ip);
2291 histPion->GetYaxis()->SetRangeUser(30, 90);
2292 histPion->GetXaxis()->SetTitle(momTitle.Data());
2293 histPion->GetYaxis()->SetTitle(dEdxTitle.Data());
2294 histPion->GetXaxis()->SetMoreLogLabels(kTRUE);
2295 histPion->GetXaxis()->SetNoExponent(kTRUE);
2296 histPion->Draw("colz");
2297 histPion->SetTitle("pions");
2298 pionPoints->SetMarkerStyle(20);
2299 pionPoints->Draw("same");
2304 hist->GetAxis(2)->SetRangeUser(2,2); // kaons
2305 hist->GetAxis(3)->SetRangeUser(2,2); // kaons (used for nsigma and for the eta correction of the signal)
2307 TH2D * histKaon = hist->Projection(1,0);
2308 histKaon->SetName("histKaon");
2309 histKaon->GetXaxis()->SetRangeUser(0.15,8);
2310 FitSlicesY(histKaon, heightFractionForFittingRange, cutForFitting, "QNRL", &arr);
2311 TH1D * kaonPoints = (TH1D*) arr.At(1)->Clone();
2313 TGraphErrors * kaonGraph = new TGraphErrors(kaonPoints);
2314 kaonGraph->SetName("kaonGraphMC");
2315 for(Int_t ip = 0; ip < kaonGraph->GetN(); ip ++) {
2316 Bool_t removePoint = kaonGraph->GetY()[ip] < 10 || kaonGraph->GetEY()[ip]/kaonGraph->GetY()[ip] > 0.02
2317 || kaonGraph->GetX()[ip] < 0.15;
2319 kaonGraph->RemovePoint(ip);
2326 histKaon->SetTitle("kaons");
2327 histKaon->GetYaxis()->SetRangeUser(30, 500);
2328 histKaon->GetXaxis()->SetTitle(momTitle.Data());
2329 histKaon->GetYaxis()->SetTitle(dEdxTitle.Data());
2330 histKaon->GetXaxis()->SetMoreLogLabels(kTRUE);
2331 histKaon->GetXaxis()->SetNoExponent(kTRUE);
2332 histKaon->Draw("colz");
2333 kaonPoints->SetMarkerStyle(20);
2334 kaonPoints->Draw("same");
2338 hist->GetAxis(2)->SetRange(0,-1); // RESET RANGES
2339 hist->GetAxis(3)->SetRange(0,-1); // RESET RANGES
2342 // Clone graphs to have graphs with the same names as for the data case -> same subsequent functions can be used to determine
2343 // the correction functions and, finally, the response functions.
2344 // In addition: Remove some points, which are expected to deviate from the Bethe-Bloch curve, from the original graphs, so that
2345 // these graphs can be used for the BB fit
2346 TGraphErrors * graphPrCombined = new TGraphErrors(*protonGraph);
2347 graphPrCombined->SetMarkerStyle(22);
2348 graphPrCombined->SetMarkerColor(4);
2349 graphPrCombined->SetNameTitle("Graph_Protons_Combined", "Graph_Protons_Combined");
2351 TGraphErrors * graphPiCombined = new TGraphErrors(*pionGraph);
2352 graphPiCombined->SetMarkerStyle(22);
2353 graphPiCombined->SetMarkerColor(3);
2354 graphPiCombined->SetNameTitle("Graph_Pions_Combined", "Graph_Pions_Combined");
2356 TGraphErrors * graphKaCombined = new TGraphErrors(*kaonGraph);
2357 graphKaCombined->SetMarkerStyle(22);
2358 graphKaCombined->SetMarkerColor(5);
2359 graphKaCombined->SetNameTitle("Graph_Kaons_Combined", "Graph_Kaons_Combined");
2361 TGraphErrors * graphElCombined = new TGraphErrors(*electronGraph);
2362 graphElCombined->SetMarkerStyle(22);
2363 graphElCombined->SetMarkerColor(2);
2364 graphElCombined->SetNameTitle("Graph_Electrons_Combined", "Graph_Electrons_Combined");
2366 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
2367 Bool_t removePoint = electronGraph->GetX()[ip] < 2.5;// || electronGraph->GetX()[ip] > 5.0;
2368 //Bool_t removePoint = electronGraph->GetX()[ip] < 1.2 || electronGraph->GetX()[ip] > 5.0;
2370 electronGraph->RemovePoint(ip);
2376 for(Int_t ip = 0; ip < protonGraph->GetN(); ip ++) {
2377 Bool_t removePoint = protonGraph->GetX()[ip] < 0.9
2378 || protonGraph->GetX()[ip] > 2.5;//3.5; //TODO NEW in order not to get into conflict with pions/kaons
2380 protonGraph->RemovePoint(ip);
2386 for(Int_t ip = 0; ip < pionGraph->GetN(); ip ++) {
2387 Bool_t removePoint = pionGraph->GetX()[ip] < 2.1;//TODO APR18 0.8;
2389 pionGraph->RemovePoint(ip);
2395 for(Int_t ip = 0; ip < kaonGraph->GetN(); ip ++) {
2396 Bool_t removePoint = kaonGraph->GetX()[ip] < 1.25 || kaonGraph->GetX()[ip] > 4.0;// < 0.7;// || kaonGraph->GetX()[ip] > 4;
2398 kaonGraph->RemovePoint(ip);
2404 // rescale graphs to betaGamma
2406 kaonGraph->SetMarkerStyle(22);
2407 for(Int_t ip = 0; ip < kaonGraph->GetN(); ip ++) {
2408 kaonGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2409 kaonGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2411 for(Int_t ip = 0; ip < graphKaCombined->GetN(); ip ++) {
2412 graphKaCombined->GetX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2413 graphKaCombined->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kKaon);
2416 electronGraph->SetMarkerStyle(22);
2417 electronGraph->SetMarkerColor(2);
2418 for(Int_t ip = 0; ip < electronGraph->GetN(); ip ++) {
2419 electronGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2420 electronGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2422 for(Int_t ip = 0; ip < graphElCombined->GetN(); ip ++) {
2423 graphElCombined->GetX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2424 graphElCombined->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kElectron);
2427 pionGraph->SetMarkerStyle(22);
2428 pionGraph->SetMarkerColor(3);
2429 for(Int_t ip = 0; ip < pionGraph->GetN(); ip ++) {
2430 pionGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2431 pionGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2433 for(Int_t ip = 0; ip < graphPiCombined->GetN(); ip ++) {
2434 graphPiCombined->GetX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2435 graphPiCombined->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kPion);
2438 protonGraph->SetMarkerStyle(22);
2439 protonGraph->SetMarkerColor(4);
2440 for(Int_t ip = 0; ip < protonGraph->GetN(); ip ++) {
2441 protonGraph->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2442 protonGraph->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2444 for(Int_t ip = 0; ip < graphPrCombined->GetN(); ip ++) {
2445 graphPrCombined->GetX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2446 graphPrCombined->GetEX()[ip] /= AliPID::ParticleMass(AliPID::kProton);
2451 // Store graphs without further restriction
2452 TGraphErrors * graphPrAll = new TGraphErrors(*graphPrCombined);
2453 graphPrAll->SetNameTitle("Protons_MC_all", "Protons_MC_all");
2455 TGraphErrors * graphPiAll = new TGraphErrors(*graphPiCombined);
2456 graphPiAll->SetNameTitle("Pions_MC_all", "Pions_MC_all");
2458 TGraphErrors * graphKaAll = new TGraphErrors(*graphKaCombined);
2459 graphKaAll->SetNameTitle("Kaons_MC_all", "Kaons_MC_all");
2461 TGraphErrors * graphElAll = new TGraphErrors(*graphElCombined);
2462 graphElAll->SetNameTitle("Electrons_MC_all", "Electrons_MC_all");
2466 TGraphErrors * graphAll = new TGraphErrors();
2467 TList * listColl = new TList();
2468 listColl->Add(electronGraph);
2469 listColl->Add(protonGraph);
2470 listColl->Add(kaonGraph);
2471 listColl->Add(pionGraph);
2472 MergeGraphErrors(graphAll, listColl);
2473 graphAll->SetNameTitle("beamDataPoints","beamDataPoints");
2476 // return array with all graphs
2478 TObjArray * arrGraphs = new TObjArray();
2479 arrGraphs->Add(graphAll);
2481 arrGraphs->Add(electronGraph);
2482 arrGraphs->Add(pionGraph);
2483 arrGraphs->Add(kaonGraph);
2484 arrGraphs->Add(protonGraph);
2486 arrGraphs->Add(graphElAll);
2487 arrGraphs->Add(graphPiAll);
2488 arrGraphs->Add(graphKaAll);
2489 arrGraphs->Add(graphPrAll);
2491 arrGraphs->Add(graphElCombined);
2492 arrGraphs->Add(graphPiCombined);
2493 arrGraphs->Add(graphKaCombined);
2494 arrGraphs->Add(graphPrCombined);
2498 canvasQAmc->SaveAs("splines_QA_ResidualGraphsTPC.root");
2505 //________________________________________________________________________
2506 TObjArray * 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 Bool_t isMC = kFALSE;
2511 if (strcmp(type, "MC") == 0) {
2514 else if (strcmp(type, "DATA") == 0) {
2518 Printf("ERROR - GetResponseFunctions: Unknown type \"%s\" - must be \"MC\" or \"DATA\"!", type);
2523 Bool_t isPbPb = kFALSE;
2524 Bool_t isPPb = kFALSE;
2525 if (strcmp(system, "PBPB") == 0) {
2526 Printf("PbPb detected - Applying special handling!");
2529 else if (strcmp(system, "PPB") == 0 || strcmp(system, "PBP") == 0) {
2530 Printf("p-Pb/Pb-p detected - Applying special handling!");
2534 TCanvas* canvasQA[4] = { 0x0, };
2535 for (Int_t i = 0; i < 4; i++) {
2536 canvasQA[i] = new TCanvas(Form("canvasQAres_%d", i), "Control canvas for residual polynomial",100,10,1380,800);
2537 canvasQA[i]->SetGrid(1, 1);
2538 canvasQA[i]->SetLogx();
2541 TCanvas * canvasQA = new TCanvas("canvasQAres","Control canvas for residual polynomial",100,10,1380,800);
2542 canvasQA->Divide(2,2);
2544 for (Int_t i = 1; i <= 4; i++) {
2545 canvasQA->GetPad(i)->SetGrid(1, 1);
2549 // smallest needed (100MeV proton) bg = 0.1/0.938(=AliPID::ParticleMass(AliPID::kProton)) = 0.1,
2550 // largest needed 100 GeV electron, bg = 100/0.000511(=AliPID::ParticleMass(AliPID::kElectron)) = 200 000
2552 Double_t from = 0.1;
2553 Double_t to = 200000;
2555 TF1* funcBB = new TF1(*parametrisation);
2556 funcBB->SetLineColor(2);
2557 funcBB->SetLineWidth(1);
2559 TString fitFuncString = "[0] + [1] / x + [2] / (x**2) + [3] / (x**3) + [4] / (x**4) + [5] / (x**5) + [6] * x";
2560 TString fitFuncString2 = "pol6";
2562 // 1. extract proton corrections
2564 TGraphErrors * graphProtonTPC = (TGraphErrors *) inputGraphs->FindObject("Graph_Protons_Combined");
2565 TGraphErrors * graphProtonTPCfinal = new TGraphErrors(*graphProtonTPC);
2566 graphProtonTPCfinal->SetName("graphProtonTPCfinal");
2567 for(Int_t ip = 0; ip < graphProtonTPC->GetN(); ip ++) {
2568 graphProtonTPC->GetY()[ip] -= funcBB->Eval(graphProtonTPC->GetX()[ip]);
2569 graphProtonTPC->GetY()[ip] /= funcBB->Eval(graphProtonTPC->GetX()[ip]);
2570 graphProtonTPC->GetEY()[ip] /= funcBB->Eval(graphProtonTPC->GetX()[ip]);;
2575 graphProtonTPC->GetXaxis()->SetTitle("#beta#gamma");
2576 graphProtonTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
2577 graphProtonTPC->GetXaxis()->SetNoExponent(kTRUE);
2578 graphProtonTPC->GetYaxis()->SetLabelSize(0.04);
2579 graphProtonTPC->GetYaxis()->SetTitleOffset(0.85);
2580 graphProtonTPC->GetXaxis()->SetTitleOffset(1.0);
2581 graphProtonTPC->GetYaxis()->SetTitle("(data - fit) / fit");
2582 graphProtonTPC->Draw("ap");
2584 if (graphProtonTPC->GetN() <= 0) {
2585 Printf("ERROR - GetResponseFunctions: Proton graph has no data points!");
2589 graphProtonTPC->Sort(); // Sort points along x. Next, the very first point will be used to determine the starting point of the correction function
2590 TF1 * funcCorrProton = new TF1("funcCorrProton", fitFuncString2.Data(), TMath::Max(graphProtonTPC->GetX()[0], 0.15),1.0); // TODO BEN was 0.18 - 0.85
2591 graphProtonTPC->Fit(funcCorrProton, "QREX0M");
2593 // 2. extract kaon corrections
2595 TGraphErrors * graphKaonTPC = (TGraphErrors *) inputGraphs->FindObject("Graph_Kaons_Combined");
2596 TGraphErrors * graphKaonTPCfinal = new TGraphErrors(*graphKaonTPC);
2597 graphKaonTPCfinal->SetName("graphKaonTPCfinal");
2598 for(Int_t ip = 0; ip < graphKaonTPC->GetN(); ip ++) {
2599 graphKaonTPC->GetY()[ip] -= funcBB->Eval(graphKaonTPC->GetX()[ip]);
2600 graphKaonTPC->GetY()[ip] /= funcBB->Eval(graphKaonTPC->GetX()[ip]);
2601 graphKaonTPC->GetEY()[ip] /= funcBB->Eval(graphKaonTPC->GetX()[ip]);;
2606 graphKaonTPC->GetXaxis()->SetTitle("#beta#gamma");
2607 graphKaonTPC->GetYaxis()->SetTitle("(data - fit) / fit");
2608 graphKaonTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
2609 graphKaonTPC->GetXaxis()->SetNoExponent(kTRUE);
2610 graphKaonTPC->GetYaxis()->SetLabelSize(0.04);
2611 graphKaonTPC->GetYaxis()->SetTitleOffset(0.85);
2612 graphKaonTPC->GetXaxis()->SetTitleOffset(1.0);
2613 graphKaonTPC->Draw("ap");
2615 if (graphKaonTPC->GetN() <= 0) {
2616 Printf("ERROR - GetResponseFunctions: Kaon graph has no data points!");
2620 graphKaonTPC->Sort(); // Sort points along x. Next, the very first point will be used to determine the starting point of the correction function
2622 TF1 * funcCorrKaon = 0x0;
2625 funcCorrKaon = new TF1("funcCorrKaon", fitFuncString.Data(), TMath::Max(graphKaonTPC->GetX()[0], 0.25), isPPb ? 3.44 : 1.981);
2626 graphKaonTPC->Fit(funcCorrKaon, "QREX0M");
2629 // In case of data there are sometimes problems to fit the shape with one function (could describe the overall deviation,
2630 // but will not cover all the details).
2631 // Nevertheless, this shape (including most of the "details") can be fitted with the following approach with two functions
2632 TF1 * funcCorrKaon1 = new TF1("funcCorrKaon1", fitFuncString.Data(),
2633 TMath::Max(graphKaonTPC->GetX()[0], 0.25), 1.981);
2634 graphKaonTPC->Fit(funcCorrKaon1, "QREX0M", "same", TMath::Max(graphKaonTPC->GetX()[0], 0.25), 1.0);
2636 TF1 * funcCorrKaon2 = new TF1("funcCorrKaon2", fitFuncString2.Data(), TMath::Max(graphKaonTPC->GetX()[0], 0.25), 1.981);
2637 graphKaonTPC->Fit(funcCorrKaon2, "QREX0M", "same", (isMC ? 1.981 : 1.0), 1.981);
2639 funcCorrKaon = new TF1("funcCorrKaon",
2640 "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))",
2641 TMath::Max(graphKaonTPC->GetX()[0], 0.25), 1.981);
2643 for (Int_t i = funcCorrKaon1->GetNpar(), j = 0; i < funcCorrKaon1->GetNpar() + funcCorrKaon2->GetNpar(); i++, j++) {
2644 funcCorrKaon->SetParameter(j, funcCorrKaon2->GetParameter(j));
2646 funcCorrKaon->SetLineColor(kRed);
2647 funcCorrKaon->GetHistogram()->DrawClone("csame");
2648 //funcCorrKaon->Draw("same");
2651 TF1 * funcCorrKaon = new TF1("funcCorrKaon", fitFuncString.Data(),//TODO BEN was fitFuncString2
2652 TMath::Max(graphKaonTPC->GetX()[0], 0.25), (isMC ? 1.981 : 1.0)); //TODO BEN was 0.79 for data and 1.45 for MC
2653 graphKaonTPC->Fit(funcCorrKaon, "QREX0M");
2656 // 3. extract pion corrections
2658 TGraphErrors * graphPionTPC = (TGraphErrors *) inputGraphs->FindObject("Graph_Pions_Combined");
2659 TGraphErrors * graphPionTPCfinal = new TGraphErrors(*graphPionTPC);
2660 graphPionTPCfinal->SetName("graphPionTPCfinal");
2661 for(Int_t ip = 0; ip < graphPionTPC->GetN(); ip ++) {
2662 graphPionTPC->GetY()[ip] -= funcBB->Eval(graphPionTPC->GetX()[ip]);
2663 graphPionTPC->GetY()[ip] /= funcBB->Eval(graphPionTPC->GetX()[ip]);
2664 graphPionTPC->GetEY()[ip] /= funcBB->Eval(graphPionTPC->GetX()[ip]);
2669 graphPionTPC->GetXaxis()->SetTitle("#beta#gamma");
2670 graphPionTPC->GetYaxis()->SetTitle("(data - fit) / fit");
2671 graphPionTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
2672 graphPionTPC->GetXaxis()->SetNoExponent(kTRUE);
2673 graphPionTPC->GetYaxis()->SetLabelSize(0.04);
2674 graphPionTPC->GetYaxis()->SetTitleOffset(0.85);
2675 graphPionTPC->GetXaxis()->SetTitleOffset(1.0);
2676 graphPionTPC->Draw("ap");
2678 if (graphPionTPC->GetN() <= 0) {
2679 Printf("ERROR - GetResponseFunctions: Pion graph has no data points!");
2683 graphPionTPC->Sort(); // Sort points along x. Next, the very first point will be used to determine the starting point of the correction function
2684 // In case of PbPb (data, not MC) only correct down to 0.2 GeV/c; otherwise: contamination due to electrons
2685 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));
2686 graphPionTPC->Fit(funcCorrPion, "QREX0M");
2688 // 4. extract electron corrections
2690 TGraphErrors * graphElectronTPC = (TGraphErrors *) inputGraphs->FindObject("Graph_Electrons_Combined");
2691 TGraphErrors * graphElectronTPCfinal = new TGraphErrors(*graphElectronTPC);
2692 graphElectronTPCfinal->SetName("graphElectronTPCfinal");
2693 for(Int_t ip = 0; ip < graphElectronTPC->GetN(); ip ++) {
2694 graphElectronTPC->GetY()[ip] -= funcBB->Eval(graphElectronTPC->GetX()[ip]);
2695 graphElectronTPC->GetY()[ip] /= funcBB->Eval(graphElectronTPC->GetX()[ip]);
2696 graphElectronTPC->GetEY()[ip] /= funcBB->Eval(graphElectronTPC->GetX()[ip]);;
2701 graphElectronTPC->GetXaxis()->SetTitle("#beta#gamma");
2702 graphElectronTPC->GetYaxis()->SetTitle("(data - fit) / fit");
2703 graphElectronTPC->GetXaxis()->SetMoreLogLabels(kTRUE);
2704 graphElectronTPC->GetXaxis()->SetNoExponent(kTRUE);
2705 graphElectronTPC->GetYaxis()->SetLabelSize(0.04);
2706 graphElectronTPC->GetYaxis()->SetTitleOffset(0.85);
2707 graphElectronTPC->GetXaxis()->SetTitleOffset(1.0);
2708 graphElectronTPC->Draw("ap");
2710 if (graphElectronTPC->GetN() <= 0) {
2711 Printf("ERROR - GetResponseFunctions: Electron graph has no data points!");
2715 graphElectronTPC->Sort(); // Sort points along x. Next, the very first point will be used to determine the starting point of the correction function
2716 // In case of PbPb (data, not MC) only correct down to 0.2 GeV/c; otherwise: contamination due to pions
2717 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
2718 // NOTE: For data, the results are almost the same for fitFuncString and fitFuncString2. Maybe, fitFuncString2 is slightly better.
2719 graphElectronTPC->Fit(funcCorrElectron, "QREX0M");
2721 // EXTRACT GRAPHS AND PUT THEM TO THE TOBJARRAY
2723 const Int_t nBins = 500;
2724 Double_t xBetaGamma[nBins];
2725 Double_t yProton[nBins];
2726 Double_t yKaon[nBins];
2727 Double_t yPion[nBins];
2728 Double_t yElectron[nBins];
2729 Double_t yDefault[nBins];
2733 xBetaGamma[0] = from;
2734 Double_t factor = pow(to/from, 1./nBins);
2737 for(Int_t kk = 0; kk < nBins; kk++) {
2738 if (kk > 0) xBetaGamma[kk] = factor * xBetaGamma[kk-1];
2739 yProton[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
2740 yPion[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
2741 yKaon[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
2742 yElectron[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
2743 yDefault[kk] = funcBB->Eval(xBetaGamma[kk])/50.;
2746 Double_t widthFactor = 0.020;
2747 Double_t smoothProton = 0.5*(TMath::Erf((funcCorrProton->GetXmax()-xBetaGamma[kk])*AliPID::ParticleMass(AliPID::kProton)/widthFactor) + 1);
2748 Double_t smoothKaon = 0.5*(TMath::Erf((funcCorrKaon->GetXmax()-xBetaGamma[kk])*AliPID::ParticleMass(AliPID::kKaon)/widthFactor) + 1);
2749 Double_t smoothPion = 0.5*(TMath::Erf((funcCorrPion->GetXmax()-xBetaGamma[kk])*AliPID::ParticleMass(AliPID::kPion)/widthFactor) + 1);
2750 Double_t smoothElectron = 0.5*(TMath::Erf((funcCorrElectron->GetXmax()-xBetaGamma[kk])*AliPID::ParticleMass(AliPID::kElectron)/widthFactor) + 1);
2752 if (xBetaGamma[kk] > funcCorrProton->GetXmax())
2753 yProton[kk] *= (1 + smoothProton*funcCorrProton->Eval(funcCorrProton->GetXmax()));
2754 // Correction is so large that one runs into trouble at low bg for Protons.
2755 // The deviation is smaller if one takes the lower bound of the correction function
2756 else if (xBetaGamma[kk] < funcCorrProton->GetXmin())
2757 yProton[kk] *= (1 + smoothProton*funcCorrProton->Eval(funcCorrProton->GetXmin()));
2759 yProton[kk] *= (1 + smoothProton*funcCorrProton->Eval(xBetaGamma[kk]));
2761 if (xBetaGamma[kk] > funcCorrKaon->GetXmax())
2762 yKaon[kk] *= (1 + smoothKaon*funcCorrKaon->Eval(funcCorrKaon->GetXmax()));
2763 // Correction is so large that one runs into trouble at low bg for Kaons.
2764 // The deviation is smaller if one takes the lower bound of the correction function
2765 else if (xBetaGamma[kk] < funcCorrKaon->GetXmin())
2766 yKaon[kk] *= (1 + smoothKaon*funcCorrKaon->Eval(funcCorrKaon->GetXmin()));
2768 yKaon[kk] *= (1 + smoothKaon*funcCorrKaon->Eval(xBetaGamma[kk]));
2770 if (xBetaGamma[kk] > funcCorrElectron->GetXmax())
2771 yElectron[kk] *= (1 + smoothElectron*funcCorrElectron->Eval(funcCorrElectron->GetXmax()));
2772 else if (xBetaGamma[kk] < funcCorrElectron->GetXmin())
2773 yElectron[kk] *= (1 + smoothElectron*funcCorrElectron->Eval(funcCorrElectron->GetXmin()));
2775 yElectron[kk] *= (1 + smoothElectron*funcCorrElectron->Eval(xBetaGamma[kk]));
2777 // Only true for LHC10d.pass?: Seems not to be needed because any (very small) deviations are most likely due to electron contamination(BEN)
2778 if (xBetaGamma[kk] > funcCorrPion->GetXmax())
2779 yPion[kk] *= (1 + smoothPion*funcCorrPion->Eval(funcCorrPion->GetXmax()));
2780 else if (xBetaGamma[kk] < funcCorrPion->GetXmin())
2781 yPion[kk] *= (1 + smoothPion*funcCorrPion->Eval(funcCorrPion->GetXmin()));
2783 yPion[kk] *= (1 + smoothPion*funcCorrPion->Eval(xBetaGamma[kk]));
2787 Double_t smoothProton = 0.5*(TMath::Erf((funcCorrProton->GetXmax()-xBetaGamma[kk])/0.002) + 1);
2788 Double_t smoothKaon = 0.5*(TMath::Erf((funcCorrKaon->GetXmax()-xBetaGamma[kk])/0.002) + 1);
2789 Double_t smoothPion = 0.5*(TMath::Erf((funcCorrPion->GetXmax()-xBetaGamma[kk])/0.002) + 1);
2791 if (xBetaGamma[kk] < funcCorrProton->GetXmax() && xBetaGamma[kk] > funcCorrProton->GetXmin()) yProton[kk] *= (1 + smoothProton*funcCorrProton->Eval(xBetaGamma[kk]));
2792 if (xBetaGamma[kk] < funcCorrKaon->GetXmax() && xBetaGamma[kk] > funcCorrKaon->GetXmin()) yKaon[kk] *= (1 + smoothKaon*funcCorrKaon->Eval(xBetaGamma[kk]));
2793 if (xBetaGamma[kk] < funcCorrPion->GetXmax() && xBetaGamma[kk] > funcCorrPion->GetXmin()) yPion[kk] *= (1 + smoothPion*funcCorrPion->Eval(xBetaGamma[kk]));
2794 //if (xBetaGamma[kk] < funcCorrElectron->GetXmax()) yElectron[kk] *= (1 + funcCorrElectron->Eval(xBetaGamma[kk]));
2796 if (xBetaGamma[kk] < funcCorrProton->GetXmin()) yProton[kk] *= (1 + funcCorrProton->Eval(funcCorrProton->GetXmin()));
2797 if (xBetaGamma[kk] < funcCorrKaon->GetXmin()) yKaon[kk] *= (1 + funcCorrKaon->Eval(funcCorrKaon->GetXmin()));
2798 if (xBetaGamma[kk] < funcCorrPion->GetXmin()) yPion[kk] *= (1 + funcCorrPion->Eval(funcCorrPion->GetXmin()));
2802 TGraph * graphProton = new TGraph(nBins, xBetaGamma, yProton);
2803 TGraph * graphElectron = new TGraph(nBins, xBetaGamma, yElectron);
2804 TGraph * graphKaon = new TGraph(nBins, xBetaGamma, yKaon);
2805 TGraph * graphPion = new TGraph(nBins, xBetaGamma, yPion);
2806 TGraph * graphDefault = new TGraph(nBins, xBetaGamma, yDefault);
2809 TSpline3 * splineProton = new TSpline3("splineProton", graphProton);
2810 TSpline3 * splineElectron = new TSpline3("splineElectron", graphElectron);
2811 TSpline3 * splineKaon = new TSpline3("splineKaon", graphKaon);
2812 TSpline3 * splinePion = new TSpline3("splinePion", graphPion);
2813 TSpline3 * splineDefault = new TSpline3("splineDefault", graphDefault);
2816 splineProton->SetNameTitle(Form("TSPLINE3_%s_PROTON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
2817 Form("TSPLINE3_%s_PROTON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
2818 splineElectron->SetNameTitle(Form("TSPLINE3_%s_ELECTRON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
2819 Form("TSPLINE3_%s_ELECTRON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
2820 splineKaon->SetNameTitle(Form("TSPLINE3_%s_KAON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
2821 Form("TSPLINE3_%s_KAON_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
2822 splinePion->SetNameTitle(Form("TSPLINE3_%s_PION_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
2823 Form("TSPLINE3_%s_PION_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
2824 splineDefault->SetNameTitle(Form("TSPLINE3_%s_ALL_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype),
2825 Form("TSPLINE3_%s_ALL_%s_%s_%s_%sMEAN",type,period,pass,system,dedxtype));
2827 TObjArray * arrResponse = new TObjArray();
2828 arrResponse->SetName("TPCpidResponseFunctions");
2829 arrResponse->AddLast(splineProton);
2830 arrResponse->AddLast(splineElectron);
2831 arrResponse->AddLast(splineKaon);
2832 arrResponse->AddLast(splinePion);
2833 arrResponse->AddLast(splineDefault);
2836 // Draw deviation from final results
2837 for(Int_t ip = 0; ip < graphProtonTPCfinal->GetN(); ip ++) {
2838 graphProtonTPCfinal->GetY()[ip] -= 50. * splineProton->Eval(graphProtonTPCfinal->GetX()[ip]);
2839 graphProtonTPCfinal->GetY()[ip] /= 50. * splineProton->Eval(graphProtonTPCfinal->GetX()[ip]);
2840 graphProtonTPCfinal->GetEY()[ip] /= 50. * splineProton->Eval(graphProtonTPCfinal->GetX()[ip]);;
2844 graphProtonTPCfinal->SetMarkerStyle(26);
2845 graphProtonTPCfinal->Draw("psame");
2847 for(Int_t ip = 0; ip < graphKaonTPCfinal->GetN(); ip ++) {
2848 graphKaonTPCfinal->GetY()[ip] -= 50. * splineKaon->Eval(graphKaonTPCfinal->GetX()[ip]);
2849 graphKaonTPCfinal->GetY()[ip] /= 50. * splineKaon->Eval(graphKaonTPCfinal->GetX()[ip]);
2850 graphKaonTPCfinal->GetEY()[ip] /= 50. * splineKaon->Eval(graphKaonTPCfinal->GetX()[ip]);;
2854 graphKaonTPCfinal->SetMarkerStyle(26);
2855 graphKaonTPCfinal->Draw("psame");
2857 for(Int_t ip = 0; ip < graphPionTPCfinal->GetN(); ip ++) {
2858 graphPionTPCfinal->GetY()[ip] -= 50. * splinePion->Eval(graphPionTPCfinal->GetX()[ip]);
2859 graphPionTPCfinal->GetY()[ip] /= 50. * splinePion->Eval(graphPionTPCfinal->GetX()[ip]);
2860 graphPionTPCfinal->GetEY()[ip] /= 50. * splinePion->Eval(graphPionTPCfinal->GetX()[ip]);;
2864 graphPionTPCfinal->SetMarkerStyle(26);
2865 graphPionTPCfinal->Draw("psame");
2867 for(Int_t ip = 0; ip < graphElectronTPCfinal->GetN(); ip ++) {
2868 graphElectronTPCfinal->GetY()[ip] -= 50. * splineElectron->Eval(graphElectronTPCfinal->GetX()[ip]);
2869 graphElectronTPCfinal->GetY()[ip] /= 50. * splineElectron->Eval(graphElectronTPCfinal->GetX()[ip]);
2870 graphElectronTPCfinal->GetEY()[ip] /= 50. * splineElectron->Eval(graphElectronTPCfinal->GetX()[ip]);;
2874 graphElectronTPCfinal->SetMarkerStyle(26);
2875 graphElectronTPCfinal->Draw("psame");
2877 TFile* fSave = TFile::Open("splines_QA_ResidualPolynomials.root", "RECREATE");
2879 for (Int_t i = 0; i < 4; i++)
2880 canvasQA[i]->Write();
2883 //canvasQA->SaveAs("splines_QA_ResidualPolynomials.root");
2892 //________________________________________________________________________
2893 TF1* AliTPCcalibResidualPID::FitBB(TObjArray* inputGraphs, Bool_t isMC, Bool_t isPPb, const Bool_t useV0s,
2894 const Double_t * initialParameters, AliTPCcalibResidualPID::FitType fitType) {
2896 // Fit Bethe-Bloch parametrisation to data points (inputGraphs)
2898 const Int_t nPar = 6;
2899 TGraphErrors * graphAll = (TGraphErrors *) inputGraphs->FindObject("beamDataPoints");
2901 Float_t from = 0.9; //TODO ADJUST -> Very important
2902 Float_t to = graphAll->GetXaxis()->GetXmax() * 2;
2908 Double_t parametersBBForward[nPar] = { 0, };
2910 TVirtualFitter::SetMaxIterations(5e6);
2912 if (fitType == AliTPCcalibResidualPID::kSaturatedLund) {
2913 printf("Fit function: Saturated Lund\n");
2915 funcBB = new TF1("SaturatedLund", SaturatedLund, from, to, nPar);
2916 //Double_t parametersBB[nPar] = {34.0446, 8.42221, 4.16724, 1.29473, 80.6663, 0}; //Xianguos values
2917 //Double_t parametersBB[nPar] = {35.5, 8.7, 2.0, 1.09, 75.6, 0}; // No saturation
2918 Double_t parametersBB[nPar] = {61.0, 8.7, 1.86, 0.85, 113.4, -38}; // Yields reasonable results for data and MC ~ all periods
2920 if (isPPb && !isMC) {
2921 parametersBB[0] = 51.6;
2922 parametersBB[1] = 9.7;
2923 parametersBB[2] = 1.62;
2924 parametersBB[3] = 0.99;
2925 parametersBB[4] = 104.4;
2926 parametersBB[5] = -27.0;
2929 parametersBB[0] = 41.4;
2930 parametersBB[1] = 8.6;
2931 parametersBB[2] = 2.2;
2932 parametersBB[3] = 0.92;
2933 parametersBB[4] = 90.4;
2934 parametersBB[5] = -20.0;
2936 funcBB->SetParameters(parametersBB);
2938 Double_t parameterErrorsBB[nPar] = {5., 0.5, 0.2, 0.05, 10, 10};
2939 funcBB->SetParErrors(parameterErrorsBB);
2941 for (Int_t i = 0; i < nPar; i++)
2942 parametersBBForward[i] = parametersBB[i];
2944 else if (fitType == AliTPCcalibResidualPID::kLund) {
2945 printf("Fit function: Lund\n");
2946 printf("****WARNING: Fit settings not tuned for this fit function, only for saturated Lund!\n");
2948 funcBB = new TF1("SaturatedLund", SaturatedLund, from, to, nPar);
2949 //Double_t parametersBB[nPar] = {34.0446, 8.42221, 4.16724, 1.29473, 80.6663, 0}; //Xianguos values
2950 //Double_t parametersBB[nPar] = {35.5, 8.7, 2.0, 1.09, 75.6, 0}; // No saturation
2951 Double_t parametersBB[nPar] = {35.0, 7., 1.86, 1., 75., 0}; // Yields reasonable results for data and MC ~ all periods
2953 funcBB->SetParameters(parametersBB);
2955 Double_t parameterErrorsBB[nPar] = {5., 0.5, 0.2, 0.05, 10, 10};
2956 funcBB->SetParErrors(parameterErrorsBB);
2958 funcBB->FixParameter(5, 0.0); // No saturation
2960 for (Int_t i = 0; i < nPar; i++)
2961 parametersBBForward[i] = parametersBB[i];
2963 else if (fitType == kAlephWithAdditionalParam) {
2964 printf("Fit function: Aleph with additional parameter\n");
2965 printf("****WARNING: Fit settings not tuned for this fit function, only for saturated Lund!\n");
2967 // NOTE: This form is equivalent to the original form, but with parameter [2] redefined for better numerical stability.
2968 // The additional parameter [5] has been introduced later and is unity originally. It seems not to be needed and is, thus,
2970 funcBB = new TF1("funcAleph",
2971 "[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);
2972 //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);
2974 Double_t parametersBB[nPar] = {2.6,14.3,-15,2.2,2.7, 0.06};
2975 //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};
2976 funcBB->SetParameters(parametersBB);
2978 for (Int_t i = 0; i < nPar; i++)
2979 parametersBBForward[i] = parametersBB[i];
2981 else if (fitType == AliTPCcalibResidualPID::kAleph) {
2982 printf("Fit function: Aleph\n");
2983 printf("****WARNING: Fit settings not tuned for this fit function, only for saturated Lund!\n");
2985 // NOTE: This form is equivalent to the original form, but with parameter [2] redefined for better numerical stability.
2986 // The additional parameter [5] has been introduced later and is unity originally. It seems not to be needed and is, thus,
2988 funcBB = new TF1("funcAleph",
2989 "[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);
2990 //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);
2991 //TEST Double_t parametersBB[nPar] = {1.2, 26.0, -30.0, -2.15, 5.6, 1};
2992 Double_t parametersBB[nPar] = {1.25, 27.5, -29.0, 2.2, 5.2, 1};
2994 // For [5] floating: Double_t parametersBB[nPar] = {2.42,15.2,-16,-2.24,2.8, 0.057};
2995 //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};
2996 //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};
2997 funcBB->SetParameters(parametersBB);
2999 // Fix parameter 5 to original value of unity
3000 funcBB->FixParameter(5, 1);
3002 for (Int_t i = 0; i < nPar; i++)
3003 parametersBBForward[i] = parametersBB[i];
3006 printf("Error: fitType not supported!\n");
3010 funcBB->SetLineColor(2);
3011 funcBB->SetLineWidth(1);
3013 // Override initial parameters, if user provides some
3014 if (initialParameters) {
3015 printf("Setting user initial parameters!\n");
3016 funcBB->SetParameters(initialParameters);
3022 TGraphErrors * graphDelta = new TGraphErrors(*graphAll);
3023 graphDelta->SetName("graphDelta");
3025 // In MC case: Remove errors from fit -> Some data points with extremely small errors otherwise completely dominate the fit,
3026 // but these points could still be wrong due to systematics (low p effects, e.g.)
3028 for(Int_t ip = 0; ip < graphAll->GetN(); ip++) {
3029 graphAll->SetPointError(ip, 0, 0);
3033 // Increase weight in plateau by reducing errors. Neccessary because errors are large there compared to other data points
3034 for(Int_t ip = 0; ip < graphAll->GetN(); ip++) {
3035 if (graphAll->GetX()[ip] >= 2500) {
3036 graphAll->SetPointError(ip, 0, graphAll->GetEY()[ip] / 6.0);
3038 // Same for pions in the very rel. rise
3039 if (graphAll->GetX()[ip] >= 25 && graphAll->GetX()[ip] < 1000) {
3040 graphAll->SetPointError(ip, 0, graphAll->GetEY()[ip] / 6.0);
3042 // Same for protons in the MIP region
3043 if (graphAll->GetX()[ip] >= 2 && graphAll->GetX()[ip] < 4) {
3044 graphAll->SetPointError(ip, 0, graphAll->GetEY()[ip] / 6.0);
3048 graphAll->Fit(funcBB, "REX0M");
3049 funcBB->SetRange(from, to);
3050 funcBB->GetParameters(parametersBBForward);
3054 for(Int_t ip = 0; ip < graphDelta->GetN(); ip++) {
3055 graphDelta->GetY()[ip] -= funcBB->Eval(graphDelta->GetX()[ip]);
3056 graphDelta->GetY()[ip] /= funcBB->Eval(graphDelta->GetX()[ip]);
3057 graphDelta->GetEY()[ip] /= funcBB->Eval(graphDelta->GetX()[ip]);
3059 TCanvas * canvDelta_1 = new TCanvas("canvDelta_1","control histogram for Bethe-Bloch fit 1",100,10,1380,800);
3060 TCanvas * canvDelta_2 = new TCanvas("canvDelta_2","control histogram for Bethe-Bloch fit 2",100,10,1380,800);
3061 canvDelta_1->SetGrid(1, 1);
3062 canvDelta_1->SetLogx();
3063 canvDelta_2->SetGrid(1, 1);
3064 canvDelta_2->SetLogx();
3066 canvDelta->Divide(2, 1);
3067 canvDelta->GetPad(1)->SetGrid(1, 1);
3068 canvDelta->GetPad(1)->SetLogx();
3069 canvDelta->GetPad(2)->SetGrid(1, 1);
3070 canvDelta->GetPad(2)->SetLogx();
3075 TH1F *hBBdummy=new TH1F("hBBdummy","BB fit;#beta#gamma;#LTdE/dx#GT (arb. unit)",100,.8,1e4);
3076 hBBdummy->SetMinimum(45);
3077 hBBdummy->SetMaximum(120);
3078 hBBdummy->GetXaxis()->SetTitleOffset(1.1);
3079 hBBdummy->SetStats(kFALSE);
3082 graphAll->SetTitle("BB multi-graph fit");
3083 graphAll->SetMarkerStyle(22);
3084 graphAll->SetMarkerColor(kMagenta);
3085 graphAll->Draw("p");
3087 TLegend *leg=new TLegend(.7,.12,.89,isMC?.4:.6);
3088 leg->SetFillColor(10);
3089 leg->SetBorderSize(1);
3091 //overlay individual graphs
3094 gr=(TGraph*)inputGraphs->FindObject("Protons_MC_all");
3095 gr->SetMarkerColor(kRed);
3096 gr->SetMarkerStyle(24);
3098 leg->AddEntry(gr,"p (MC)","p");
3099 gr=(TGraph*)inputGraphs->FindObject("Pions_MC_all");
3100 gr->SetMarkerColor(kBlue);
3101 gr->SetMarkerStyle(24);
3103 leg->AddEntry(gr,"#pi (MC)","p");
3104 gr=(TGraph*)inputGraphs->FindObject("Kaons_MC_all");
3105 gr->SetMarkerColor(kGreen);
3106 gr->SetMarkerStyle(24);
3108 leg->AddEntry(gr,"K (MC)","p");
3109 gr=(TGraph*)inputGraphs->FindObject("Electrons_MC_all");
3110 gr->SetMarkerColor(kBlack);
3111 gr->SetMarkerStyle(24);
3113 leg->AddEntry(gr,"e (MC)","p");
3116 gr=(TGraph*)inputGraphs->FindObject("protonTpcGraph");
3117 gr->SetMarkerColor(kRed);
3118 gr->SetMarkerStyle(26);
3120 leg->AddEntry(gr,"p (TPC)","p");
3121 gr=(TGraph*)inputGraphs->FindObject("protonTofGraph");
3122 gr->SetMarkerColor(kRed);
3123 gr->SetMarkerStyle(25);
3125 leg->AddEntry(gr,"p (TOF)","p");
3126 gr=(TGraph*)inputGraphs->FindObject("protonV0Graph");//ForBBfit");
3127 gr->SetMarkerColor(kRed);
3128 gr->SetMarkerStyle(24);
3130 leg->AddEntry(gr,"p (V0)","p");
3131 gr=(TGraph*)inputGraphs->FindObject("protonV0plusTOFGraph");//ForBBfit");
3132 gr->SetMarkerColor(kRed);
3133 gr->SetMarkerStyle(30);
3135 leg->AddEntry(gr,"p (V0+TOF)","p");
3136 gr=(TGraph*)inputGraphs->FindObject("pionTpcGraph");
3137 gr->SetMarkerColor(kBlue);
3138 gr->SetMarkerStyle(26);
3140 leg->AddEntry(gr,"#pi (TPC)","p");
3141 gr=(TGraph*)inputGraphs->FindObject("pionTofGraph");
3142 gr->SetMarkerColor(kBlue);
3143 gr->SetMarkerStyle(25);
3145 leg->AddEntry(gr,"#pi (TOF)","p");
3146 gr=(TGraph*)inputGraphs->FindObject("pionV0Graph");//ForBBfit");
3147 gr->SetMarkerColor(kBlue);
3148 gr->SetMarkerStyle(24);
3150 leg->AddEntry(gr,"#pi (V0)","p");
3151 gr=(TGraph*)inputGraphs->FindObject("pionV0plusTOFGraph");//ForBBfit");
3152 gr->SetMarkerColor(kBlue);
3153 gr->SetMarkerStyle(30);
3155 leg->AddEntry(gr,"#pi (V0+TOF)","p");
3156 gr=(TGraph*)inputGraphs->FindObject("kaonTpcGraph");
3157 gr->SetMarkerColor(kGreen);
3158 gr->SetMarkerStyle(26);
3160 leg->AddEntry(gr,"K (TPC)","p");
3161 gr=(TGraph*)inputGraphs->FindObject("kaonTofGraph");
3162 gr->SetMarkerColor(kGreen);
3163 gr->SetMarkerStyle(25);
3165 leg->AddEntry(gr,"K (TOF)","p");
3166 gr=(TGraph*)inputGraphs->FindObject("electronGraph");
3167 gr->SetMarkerColor(kBlack);
3168 gr->SetMarkerStyle(25);
3170 leg->AddEntry(gr,"e","p");
3171 gr=(TGraph*)inputGraphs->FindObject("electronV0Graph");//ForBBfit");
3172 gr->SetMarkerColor(kBlack);
3173 gr->SetMarkerStyle(24);
3175 leg->AddEntry(gr,"e (V0)","p");
3176 gr=(TGraph*)inputGraphs->FindObject("electronV0plusTOFGraph");//ForBBfit");
3177 gr->SetMarkerColor(kBlack);
3178 gr->SetMarkerStyle(30);
3180 leg->AddEntry(gr,"e (V0+TOF)","p");
3183 graphAll->GetXaxis()->SetTitle("#beta#gamma");
3184 graphAll->GetYaxis()->SetTitle("<dE/dx> (arb. unit)");
3185 graphAll->Draw("p");
3186 funcBB->GetHistogram()->DrawClone("csame");
3188 leg->AddEntry(graphAll,"used","p");
3189 leg->AddEntry(funcBB,"fit","l");
3194 TH1F *hBBresdummy=new TH1F("hBBresdummy","residuals of BB fit;#beta#gamma;(data-fit)/fit",100,.8,1e4);
3195 hBBresdummy->SetMinimum(-0.04);
3196 hBBresdummy->SetMaximum(0.04);
3197 hBBresdummy->GetXaxis()->SetTitleOffset(1.1);
3198 hBBresdummy->GetYaxis()->SetTitleOffset(0.8);
3199 hBBresdummy->SetStats(kFALSE);
3200 hBBresdummy->Draw();
3202 graphDelta->SetTitle("residuals of BB fit to multi-graph");
3203 graphDelta->GetXaxis()->SetTitle("#beta#gamma");
3204 graphDelta->GetYaxis()->SetTitle("(data - fit) / fit");
3205 graphDelta->SetMarkerStyle(22);
3206 graphDelta->SetMarkerColor(4);
3207 graphDelta->Draw("p");
3209 TFile* fSave = TFile::Open("splines_QA_BetheBlochFit.root", "RECREATE");
3211 canvDelta_1->Write();
3212 canvDelta_2->Write();
3214 TString fitResults = "Fit results:\n";
3215 for (Int_t i = 0; i < nPar; i++) {
3216 fitResults.Append(Form("par%d:\t%f +- %f\n", i, funcBB->GetParameters()[i], funcBB->GetParErrors()[i]));
3219 TNamed* settings = new TNamed(fitResults.Data(), fitResults.Data());
3224 printf("\n\n%s", fitResults.Data());
3230 //________________________________________________________________________
3231 Double_t AliTPCcalibResidualPID::Lund(Double_t* xx, Double_t* par)
3234 const Double_t bg = xx[0];
3236 const Double_t beta2 = bg*bg / (1.0 + bg*bg);
3238 const Double_t a = par[0];
3239 const Double_t b = par[1];
3240 const Double_t c = par[2];
3241 const Double_t e = par[3];
3242 const Double_t f = par[4];
3244 const Double_t d = TMath::Exp(c*(a - f) / b);
3246 const Double_t powbg = TMath::Power(1.0 + bg, c);
3248 const Double_t value = a / TMath::Power(beta2,e) +
3249 b/c * TMath::Log(powbg / (1.0 + d*powbg));
3255 //________________________________________________________________________
3256 Double_t AliTPCcalibResidualPID::SaturatedLund(Double_t* xx, Double_t* par)
3258 const Double_t qq = Lund(xx, par);
3259 return qq * TMath::Exp(par[5] / qq);
3263 //________________________________________________________________________
3264 void AliTPCcalibResidualPID::FitSlicesY(TH2 *hist, Double_t heightFractionForRange, Int_t cutThreshold, TString fitOption, TObjArray *arr)
3266 //heightPercentageForRange
3267 // custom slices fit
3273 // If old style is to be used
3275 hist->FitSlicesY(0, 0, -1, cutThreshold, fitOption.Data(), &arr);
3284 TAxis *axis=hist->GetXaxis();
3285 const TArrayD *bins = axis->GetXbins();
3286 TH1D** hList = new TH1D*[4];
3288 for (Int_t i = 0; i < 4; i++) {
3289 delete gDirectory->FindObject(Form("%s_%d", hist->GetName(), i));
3291 if (bins->fN == 0) {
3292 hList[i] = new TH1D(Form("%s_%d", hist->GetName(), i), i < 3 ? Form("Fitted value of par[%d]", i) : "Chi2/NDF",
3293 hist->GetNbinsX(), axis->GetXmin(), axis->GetXmax());
3295 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);
3298 (*arr)[i] = hList[i];
3301 for (Int_t ibin=axis->GetFirst(); ibin<=axis->GetLast(); ++ibin){
3302 TH1 *h=hist->ProjectionY("_temp",ibin,ibin);
3306 if (h->GetEntries() < cutThreshold) {
3311 // Average around maximum bin -> Might catch some outliers
3312 Int_t maxBin = h->GetMaximumBin();
3313 Double_t maxVal = h->GetBinContent(maxBin);
3315 if (maxVal < 2) { // It could happen that all entries are in overflow/underflow; don't fit in this case
3320 UChar_t usedBins = 1;
3322 maxVal += h->GetBinContent(maxBin - 1);
3325 if (maxBin < h->GetNbinsX()) {
3326 maxVal += h->GetBinContent(maxBin + 1);
3331 Double_t thresholdFraction = heightFractionForRange * maxVal;
3332 Int_t lowThrBin = TMath::Max(1, h->FindFirstBinAbove(thresholdFraction));
3333 Int_t highThrBin = TMath::Min(h->GetNbinsX(), h->FindLastBinAbove(thresholdFraction));
3335 Double_t lowThreshold = h->GetBinCenter(lowThrBin);
3336 Double_t highThreshold = h->GetBinCenter(highThrBin);
3338 TFitResultPtr res = h->Fit("gaus", Form("%sS", fitOption.Data()), "", lowThreshold, highThreshold);
3340 if ((Int_t)res == 0) {
3341 Int_t resBin = ibin;
3342 hList[0]->SetBinContent(resBin,res->GetParams()[0]);
3343 hList[0]->SetBinError(resBin,res->GetErrors()[0]);
3344 hList[1]->SetBinContent(resBin,res->GetParams()[1]);
3345 hList[1]->SetBinError(resBin,res->GetErrors()[1]);
3346 hList[2]->SetBinContent(resBin,res->GetParams()[2]);
3347 hList[2]->SetBinError(resBin,res->GetErrors()[2]);
3348 hList[3]->SetBinContent(resBin,res->Ndf()>0?res->Chi2()/res->Ndf():0);
3356 //______________________________________________________________________________
3357 Bool_t AliTPCcalibResidualPID::GetVertexIsOk(AliVEvent* event) const
3359 AliAODEvent* aod = 0x0;
3360 AliESDEvent* esd = 0x0;
3362 aod = dynamic_cast<AliAODEvent*>(event);
3364 esd = dynamic_cast<AliESDEvent*>(event);
3367 AliError("Event seems to be neither AOD nor ESD!");
3373 const AliVVertex* trkVtx = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertex()) :
3374 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertex()));
3376 if (!trkVtx || trkVtx->GetNContributors() <= 0)
3379 TString vtxTtl = trkVtx->GetTitle();
3380 if (!vtxTtl.Contains("VertexerTracks"))
3383 Float_t zvtx = trkVtx->GetZ();
3384 const AliVVertex* spdVtx = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertexSPD()) :
3385 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertexSPD()));
3386 if (spdVtx->GetNContributors() <= 0)
3389 TString vtxTyp = spdVtx->GetTitle();
3390 Double_t cov[6] = {0};
3391 spdVtx->GetCovarianceMatrix(cov);
3392 Double_t zRes = TMath::Sqrt(cov[5]);
3393 if (vtxTyp.Contains("vertexer:Z") && (zRes > 0.25))
3396 if (TMath::Abs(spdVtx->GetZ() - trkVtx->GetZ()) > 0.5)
3399 if (TMath::Abs(zvtx) > fZvtxCutEvent) //Default: 10 cm
3407 const AliVVertex* primaryVertex = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertex()) :
3408 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertexTracks()));
3410 if (!primaryVertex || primaryVertex->GetNContributors() <= 0)
3413 if (TMath::Abs(primaryVertex->GetZ()) >= fZvtxCutEvent) //Default: 10 cm
3420 //______________________________________________________________________________
3421 void AliTPCcalibResidualPID::FillV0PIDlist(AliESDEvent* event)
3424 // Fill the PID tag list
3427 // If no event forwarded as parameter (default), cast current input event.
3428 // Dynamic cast to ESD events (DO NOTHING for AOD events)
3430 event = dynamic_cast<AliESDEvent *>(InputEvent());
3432 // If this fails, do nothing
3437 AliError("V0KineCuts not available!");
3441 TString beamType(event->GetBeamType());
3443 if (beamType.CompareTo("Pb-Pb") == 0 || beamType.CompareTo("A-A") == 0) {
3444 fV0KineCuts->SetMode(AliESDv0KineCuts::kPurity, AliESDv0KineCuts::kPbPb);
3447 fV0KineCuts->SetMode(AliESDv0KineCuts::kPurity, AliESDv0KineCuts::kPP);
3452 fV0KineCuts->SetEvent(event);
3454 const Int_t numTracks = event->GetNumberOfTracks();
3455 fV0tags = new Char_t[numTracks];
3456 for (Int_t i = 0; i < numTracks; i++)
3459 fV0motherIndex = new Int_t[numTracks];
3460 for (Int_t i = 0; i < numTracks; i++)
3461 fV0motherIndex[i] = -1;
3463 fV0motherPDG = new Int_t[numTracks];
3464 for (Int_t i = 0; i < numTracks; i++)
3465 fV0motherPDG[i] = 0;
3467 fNumTagsStored = numTracks;
3473 // loop over V0 particles
3474 for (Int_t iv0 = 0; iv0 < event->GetNumberOfV0s(); iv0++) {
3475 AliESDv0* v0 = (AliESDv0*)event->GetV0(iv0);
3480 // Reject onFly V0's <-> Only take V0's from offline V0 finder
3481 if (v0->GetOnFlyStatus())
3484 // Get the particle selection
3485 Bool_t foundV0 = kFALSE;
3486 Int_t pdgV0 = 0, pdgP = 0, pdgN = 0;
3488 foundV0 = fV0KineCuts->ProcessV0(v0, pdgV0, pdgP, pdgN);
3492 Int_t iTrackP = v0->GetPindex(); // positive track
3493 Int_t iTrackN = v0->GetNindex(); // negative track
3496 AliESDtrack* trackP = event->GetTrack(iTrackP);
3497 AliESDtrack* trackN = event->GetTrack(iTrackN);
3499 if (!trackP || !trackN)
3504 Float_t xy = 999, z = 999;
3505 trackP->GetImpactParameters(xy, z);
3507 Bool_t reject = kFALSE;
3508 if (TMath::Abs(z) > 1)
3511 trackN->GetImpactParameters(xy, z);
3512 if (TMath::Abs(z) > 1)
3517 // Fill the Object arrays
3518 // positive particles
3520 fV0tags[iTrackP] = 14;
3522 else if (pdgP == 211) {
3523 fV0tags[iTrackP] = 15;
3525 else if(pdgP == 2212) {
3526 fV0tags[iTrackP] = 16;
3529 fV0motherIndex[iTrackP] = iv0;
3530 fV0motherPDG[iTrackP] = pdgV0;
3532 // negative particles
3534 fV0tags[iTrackN] = -14;
3536 else if( pdgN == -211){
3537 fV0tags[iTrackN] = -15;
3539 else if( pdgN == -2212){
3540 fV0tags[iTrackN] = -16;
3543 fV0motherIndex[iTrackN] = iv0;
3544 fV0motherPDG[iTrackN] = pdgV0;
3550 //______________________________________________________________________________
3551 void AliTPCcalibResidualPID::ClearV0PIDlist()
3554 // Clear the PID tag list
3560 delete fV0motherIndex;
3563 delete fV0motherPDG;
3570 //______________________________________________________________________________
3571 Char_t AliTPCcalibResidualPID::GetV0tag(Int_t trackIndex) const
3574 // Get the tag for the corresponding trackIndex. Returns -99 in case of invalid index/tag list.
3577 if (trackIndex < 0 || trackIndex >= fNumTagsStored || !fV0tags)
3580 return fV0tags[trackIndex];
3584 //______________________________________________________________________________
3585 Int_t AliTPCcalibResidualPID::GetV0motherIndex(Int_t trackIndex) const
3588 // Get the index of the V0 mother for the corresponding trackIndex. Returns -99 in case of invalid index/mother index list.
3591 if (trackIndex < 0 || trackIndex >= fNumTagsStored || !fV0motherIndex)
3594 return fV0motherIndex[trackIndex];
3598 //______________________________________________________________________________
3599 Int_t AliTPCcalibResidualPID::GetV0motherPDG(Int_t trackIndex) const
3602 // Get the PDG code of the V0 mother for the corresponding trackIndex. Returns 0 in case of invalid index/mother index list.
3605 if (trackIndex < 0 || trackIndex >= fNumTagsStored || !fV0motherPDG)
3608 return fV0motherPDG[trackIndex];
3612 //______________________________________________________________________________
3613 Int_t AliTPCcalibResidualPID::MergeGraphErrors(TGraphErrors* mergedGraph, TCollection* li)
3615 // Adds all graphs with errors from the collection to this graph.
3616 // Returns the total number of poins in the result or -1 in case of an error.
3618 // TODO "Normal" merge of latest root trunk will also take into account the error bars,
3619 // so this function can be replaced by the normal root function with the latest root version.
3622 while (TObject* o = next()) {
3623 TGraph *g = dynamic_cast<TGraph*>(o);
3625 Printf("ERROR: Cannot merge an object which doesn't inherit from TGraph found in the list");
3628 int n0 = mergedGraph->GetN();
3629 int n1 = n0+g->GetN();
3630 mergedGraph->Set(n1);
3631 Double_t * x = g->GetX();
3632 Double_t * y = g->GetY();
3633 Double_t * ex = g->GetEX();
3634 Double_t * ey = g->GetEY();
3635 for (Int_t i = 0 ; i < g->GetN(); i++) {
3636 mergedGraph->SetPoint(n0+i, x[i], y[i]);
3637 Double_t exPoint = ex ? ex[i] : 0;
3638 Double_t eyPoint = ey ? ey[i] : 0;
3639 mergedGraph->SetPointError(n0+i, exPoint, eyPoint);
3642 return mergedGraph->GetN();
3645 //________________________________________________________________________
3646 Bool_t AliTPCcalibResidualPID::TPCCutMIGeo(const AliVTrack* track, const AliVEvent* evt, TTreeStream* streamer)
3655 const Short_t sign = track->Charge();
3657 Double_t pxpypz[50];
3661 track->GetPxPyPz(pxpypz);
3663 AliExternalTrackParam* par = new AliExternalTrackParam(xyz, pxpypz, cv, sign);
3664 const AliESDtrack dummy;
3666 const Double_t magField = evt->GetMagneticField();
3667 Double_t varGeom = dummy.GetLengthInActiveZone(par, 3, 236, magField, 0, 0);
3668 Double_t varNcr = track->GetTPCClusterInfo(3, 1);
3669 Double_t varNcls = track->GetTPCsignalN();
3671 const Double_t varEval = 130. - 5. * TMath::Abs(1. / track->Pt());
3672 Bool_t cutGeom = varGeom > fgCutGeo * varEval;
3673 Bool_t cutNcr = varNcr > fgCutNcr * varEval;
3674 Bool_t cutNcls = varNcls > fgCutNcl * varEval;
3676 Bool_t kout = cutGeom && cutNcr && cutNcls;
3679 Double_t dedx = track->GetTPCsignal();
3681 (*streamer)<<"tree"<<
3683 "varGeom="<<varGeom<<
3685 "varNcls="<<varNcls<<
3687 "cutGeom="<<cutGeom<<
3689 "cutNcls="<<cutNcls<<