]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGPP/TRD/AliTRDresolution.cxx
20bd694ca6e095ced75abad07b769d59beb251c4
[u/mrichter/AliRoot.git] / PWGPP / TRD / AliTRDresolution.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercialf purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 /* $Id: AliTRDresolution.cxx 27496 2008-07-22 08:35:45Z cblume $ */
17
18 ////////////////////////////////////////////////////////////////////////////
19 //                                                                        //
20 //  TRD tracking resolution                                               //
21 //
22 // The class performs resolution and residual studies 
23 // of the TRD tracks for the following quantities :
24 //   - spatial position (y, [z])
25 //   - angular (phi) tracklet
26 //   - momentum at the track level
27 // 
28 // The class has to be used for regular detector performance checks using the official macros:
29 //   - $ALICE_ROOT/TRD/qaRec/run.C
30 //   - $ALICE_ROOT/TRD/qaRec/makeResults.C
31 // 
32 // For stand alone usage please refer to the following example: 
33 // {  
34 //   gSystem->Load("libANALYSIS.so");
35 //   gSystem->Load("libTRDqaRec.so");
36 //   AliTRDresolution *res = new AliTRDresolution();
37 //   //res->SetMCdata();
38 //   //res->SetVerbose();
39 //   //res->SetVisual();
40 //   res->Load();
41 //   if(!res->PostProcess()) return;
42 //   res->GetRefFigure(0);
43 // }  
44 //
45 //  Authors:                                                              //
46 //    Alexandru Bercuci <A.Bercuci@gsi.de>                                //
47 //    Markus Fasel <M.Fasel@gsi.de>                                       //
48 //                                                                        //
49 ////////////////////////////////////////////////////////////////////////////
50
51 #include <TFile.h>
52 #include <TSystem.h>
53 #include <TStyle.h>
54 #include <TROOT.h>
55 #include <TObjArray.h>
56 #include <TH3.h>
57 #include <TH2.h>
58 #include <TH1.h>
59 #include <THnSparse.h>
60 #include <TF1.h>
61 #include <TCanvas.h>
62 #include <TGaxis.h>
63 #include <TBox.h>
64 #include <TLegend.h>
65 #include <TGraphErrors.h>
66 #include <TGraphAsymmErrors.h>
67 #include <TLinearFitter.h>
68 #include <TMath.h>
69 #include <TMatrixT.h>
70 #include <TVectorT.h>
71 #include <TTreeStream.h>
72 #include <TGeoManager.h>
73 #include <TDatabasePDG.h>
74
75 #include "AliPID.h"
76 #include "AliLog.h"
77 #include "AliESDtrack.h"
78 #include "AliMathBase.h"
79 #include "AliTrackPointArray.h"
80
81 #include "AliTRDresolution.h"
82 #include "AliTRDgeometry.h"
83 #include "AliTRDtransform.h"
84 #include "AliTRDpadPlane.h"
85 #include "AliTRDcluster.h"
86 #include "AliTRDseedV1.h"
87 #include "AliTRDtrackV1.h"
88 #include "AliTRDReconstructor.h"
89 #include "AliTRDrecoParam.h"
90 #include "AliTRDpidUtil.h"
91 #include "AliTRDinfoGen.h"
92 #include "AliAnalysisManager.h"
93 #include "info/AliTRDclusterInfo.h"
94 #include "info/AliTRDeventInfo.h"
95
96 ClassImp(AliTRDresolution)
97 ClassImp(AliTRDresolution::AliTRDrecoProjection)
98
99 Int_t const   AliTRDresolution::fgkNbins[kNdim] = {
100   Int_t(kNbunchCross)/*bc*/,
101   180/*phi*/,
102   50/*eta*/,
103   50/*dy*/,
104   40/*dphi*/,
105   50/*dz*/,
106   3/*chg*species*/,
107   kNpt/*pt*/
108 };  //! no of bins/projection
109 Double_t const AliTRDresolution::fgkMin[kNdim] = {
110   -1.5,
111   -TMath::Pi(),
112   -1.,
113   -1.5,
114   -10.,
115   -2.5,
116   -1.5,
117   -0.5
118 };    //! low limits for projections
119 Double_t const AliTRDresolution::fgkMax[kNdim] = {
120   1.5,
121   TMath::Pi(),
122   1.,
123   1.5,
124   10.,
125   2.5,
126   1.5,
127   kNpt-0.5
128 };    //! high limits for projections
129 Char_t const *AliTRDresolution::fgkTitle[kNdim] = {
130   "bunch cross",
131   "#phi [rad]",
132   "#eta",
133   "#Deltay [cm]",
134   "#Delta#phi [deg]",
135   "#Deltaz [cm]",
136   "chg*spec*rc",
137   "bin_p_{t}"
138 };  //! title of projection
139
140 Char_t const * AliTRDresolution::fgPerformanceName[kNclasses] = {
141     "Det2Cluster"
142     ,"Cluster2Track"
143     ,"Tracklet2Track"
144     ,"Tracklet2TRDin"
145     ,"Cluster2MC"
146     ,"Tracklet2MC"
147     ,"TRDin2MC"
148     ,"TRD2MC"
149 //    ,"Tracklet2TRDout"
150 //    ,"TRDout2MC"
151 };
152 Float_t AliTRDresolution::fgPtBin[25];
153
154 //________________________________________________________
155 AliTRDresolution::AliTRDresolution()
156   :AliTRDrecoTask()
157   ,fSteer(0)
158   ,fIdxFrame(0)
159   ,fPtThreshold(.3)
160   ,fDyRange(0.75)
161   ,fBCbinTOF(0)
162   ,fBCbinFill(0)
163   ,fBsign(kFALSE)
164   ,fProj(NULL)
165   ,fDBPDG(NULL)
166   ,fCl(NULL)
167   ,fMCcl(NULL)
168 {
169   //
170   // Default constructor
171   //
172   SetNameTitle("TRDresolution", "TRD spatial and momentum resolution");
173   MakePtSegmentation();
174   SetProcesses(kTRUE, kTRUE, kTRUE, kTRUE);
175 }
176
177 //________________________________________________________
178 AliTRDresolution::AliTRDresolution(char* name, Bool_t xchange)
179   :AliTRDrecoTask(name, "TRD spatial and momentum resolution")
180   ,fSteer(0)
181   ,fIdxFrame(0)
182   ,fPtThreshold(.3)
183   ,fDyRange(0.75)
184   ,fBCbinTOF(0)
185   ,fBCbinFill(0)
186   ,fBsign(kFALSE)
187   ,fProj(NULL)
188   ,fDBPDG(NULL)
189   ,fCl(NULL)
190   ,fMCcl(NULL)
191 {
192   //
193   // Default constructor
194   //
195
196   InitFunctorList();
197   MakePtSegmentation();
198   SetProcesses(kTRUE, kTRUE, kTRUE, kTRUE);
199   if(xchange){
200     SetUseExchangeContainers();
201     DefineOutput(kClToTrk, TObjArray::Class()); // cluster2track
202     DefineOutput(kClToMC, TObjArray::Class()); // cluster2mc
203   }
204 }
205
206 //________________________________________________________
207 AliTRDresolution::~AliTRDresolution()
208 {
209   //
210   // Destructor
211   //
212   if (AliAnalysisManager::GetAnalysisManager() && AliAnalysisManager::GetAnalysisManager()->IsProofMode()) return;
213   if(fProj){fProj->Delete(); delete fProj;}
214   if(fCl){fCl->Delete(); delete fCl;}
215   if(fMCcl){fMCcl->Delete(); delete fMCcl;}
216 }
217
218
219 //________________________________________________________
220 void AliTRDresolution::UserCreateOutputObjects()
221 {
222   // spatial resolution
223
224   AliTRDrecoTask::UserCreateOutputObjects();
225   if(UseExchangeContainers()) InitExchangeContainers();
226 }
227
228 //________________________________________________________
229 void AliTRDresolution::InitExchangeContainers()
230 {
231 // Init containers for subsequent tasks (AliTRDclusterResolution)
232
233   fCl = new TObjArray(200); fCl->SetOwner(kTRUE);
234   fMCcl = new TObjArray(); fMCcl->SetOwner(kTRUE);
235   PostData(kClToTrk, fCl);
236   PostData(kClToMC, fMCcl);
237 }
238
239 //________________________________________________________
240 void AliTRDresolution::UserExec(Option_t *opt)
241 {
242   //
243   // Execution part
244   //
245
246   if(fCl) fCl->Delete();
247   if(fMCcl) fMCcl->Delete();
248   AliTRDrecoTask::UserExec(opt);
249 }
250
251 //________________________________________________________
252 Bool_t AliTRDresolution::Pulls(Double_t* /*dyz[2]*/, Double_t* /*cov[3]*/, Double_t /*tilt*/) const
253 {
254 // Helper function to calculate pulls in the yz plane
255 // using proper tilt rotation
256 // Uses functionality defined by AliTRDseedV1.
257
258   return kTRUE;
259 /*
260   Double_t t2(tilt*tilt);
261   // exit door until a bug fix is found for AliTRDseedV1::GetCovSqrt
262
263   // rotate along pad
264   Double_t cc[3];
265   cc[0] = cov[0] - 2.*tilt*cov[1] + t2*cov[2];
266   cc[1] = cov[1]*(1.-t2) + tilt*(cov[0] - cov[2]);
267   cc[2] = t2*cov[0] + 2.*tilt*cov[1] + cov[2];
268   // do sqrt
269   Double_t sqr[3]={0., 0., 0.};
270   if(AliTRDseedV1::GetCovSqrt(cc, sqr)) return kFALSE;
271   Double_t invsqr[3]={0., 0., 0.};
272   if(AliTRDseedV1::GetCovInv(sqr, invsqr)<1.e-40) return kFALSE;
273   Double_t tmp(dyz[0]);
274   dyz[0] = invsqr[0]*tmp + invsqr[1]*dyz[1];
275   dyz[1] = invsqr[1]*tmp + invsqr[2]*dyz[1];
276   return kTRUE;
277 */
278 }
279
280 //________________________________________________________
281 TH1* AliTRDresolution::DetCluster(const TObjArray *cls)
282 {
283   //
284   // Plot the cluster distributions
285   //
286
287   if(cls) fkClusters = cls;
288   if(!fkClusters){
289     AliDebug(4, "No Clusters defined.");
290     return NULL;
291   }
292   Int_t ncl(0);
293   if(!(ncl = fkClusters->GetEntriesFast())){
294     AliDebug(1, "No RecPoints defined.");
295     return NULL;
296   }
297   Int_t det(-1);
298   AliTRDcluster *cl(NULL);
299   for(Int_t icl(0); icl<ncl; icl++){
300     if(!(cl = (AliTRDcluster*)(*fkClusters)[icl])) continue;
301     det = cl->GetDetector(); break;
302   }
303   if(det<0){
304     AliDebug(1, "No useful clusters defined.");
305     return NULL;
306   }
307   THnSparse *H(NULL);
308   if(!fContainer || !(H = ((THnSparse*)fContainer->At(kDetector)))){
309     AliWarning("No output container defined.");
310     return NULL;
311   }
312   Int_t ly(AliTRDgeometry::GetLayer(det)),
313         stk(AliTRDgeometry::GetStack(det));
314   Double_t val[kNdim],
315            alpha((0.5+AliTRDgeometry::GetSector(det))*AliTRDgeometry::GetAlpha()),
316            cs(TMath::Cos(alpha)),
317            sn(TMath::Sin(alpha));
318   for(Int_t icl(0); icl<ncl; icl++){
319     if(!(cl = (AliTRDcluster*)(*fkClusters)[icl])) continue;
320     val[kBC]  = ly;
321     val[kPhi] = TMath::ATan2(cl->GetX()*sn + cl->GetY()*cs, cl->GetX()*cs - cl->GetY()*sn);
322     val[kEta] = (5-stk)*16-cl->GetPadRow()-1-(stk<3?4:0);
323     val[kYrez]= fEvent->GetMultiplicity();
324     val[4]    = TMath::Abs(cl->GetQ());
325     val[5]    = cl->IsFivePad()?1:cl->GetNPads();
326     H->Fill(val);
327   }
328   return NULL;
329 }
330
331 //________________________________________________________
332 TH1* AliTRDresolution::PlotCluster(const AliTRDtrackV1 *track)
333 {
334   //
335   // Plot the cluster distributions
336   //
337
338   if(track) fkTrack = track;
339   if(!fkTrack){
340     AliDebug(4, "No Track defined.");
341     return NULL;
342   }
343   if(fkESD && TMath::Abs(fkESD->GetTOFbc()) > 1){
344     AliDebug(4, Form("Track with BC_index[%d] not used.", fkESD->GetTOFbc()));
345     return NULL;
346   }
347   if(fkESD && fPt<fPtThreshold){
348     AliDebug(4, Form("Track with pt[%6.4f] under threshold.", fPt));
349     return NULL;
350   }
351   THnSparse *H(NULL);
352   if(!fContainer || !(H = ((THnSparse*)fContainer->At(kCluster)))){
353     AliWarning("No output container defined.");
354     return NULL;
355   }
356
357   AliTRDgeometry *geo(AliTRDinfoGen::Geometry());
358   Double_t val[kNdim+2],
359            alpha(0.), cs(-2.), sn(0.); //Float_t exb, vd, t0, s2, dl, dt;
360   TObjArray     *clInfoArr(NULL);
361   AliTRDseedV1  *fTracklet(NULL);
362   AliTRDcluster *c(NULL), *cc(NULL);
363   for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
364     if(!(fTracklet = fkTrack->GetTracklet(ily))) continue;
365     if(!fTracklet->IsOK()) continue;
366     //fTracklet->GetCalibParam(exb, vd, t0, s2, dl, dt);
367     val[kBC]  = ily;
368     if(cs<-1.){
369       alpha = (0.5+AliTRDgeometry::GetSector(fTracklet->GetDetector()))*AliTRDgeometry::GetAlpha();
370       cs    = TMath::Cos(alpha);
371       sn    = TMath::Sin(alpha);
372     }
373     val[kPhi] = TMath::ATan2(fTracklet->GetX()*sn + fTracklet->GetY()*cs, fTracklet->GetX()*cs - fTracklet->GetY()*sn);
374     Float_t tgl = fTracklet->GetZ()/fTracklet->GetX()/TMath::Sqrt(1.+fTracklet->GetY()*fTracklet->GetY()/fTracklet->GetX()/fTracklet->GetX());
375     val[kEta] = -TMath::Log(TMath::Tan(0.5 *  (0.5*TMath::Pi() - TMath::ATan(tgl))));
376     val[kPt]  = TMath::ATan(fTracklet->GetYref(1))*TMath::RadToDeg();
377     Float_t corr = 1./TMath::Sqrt(1.+fTracklet->GetYref(1)*fTracklet->GetYref(1)+fTracklet->GetZref(1)*fTracklet->GetZref(1));
378     Int_t row0(-1);
379     Float_t padCorr(fTracklet->GetTilt()*fTracklet->GetPadLength());
380     fTracklet->ResetClusterIter(kTRUE);
381     while((c = fTracklet->NextCluster())){
382       Float_t xc(c->GetX()),
383               q(TMath::Abs(c->GetQ()));
384       if(row0<0) row0 = c->GetPadRow();
385
386       val[kYrez] = c->GetY() + padCorr*(c->GetPadRow() - row0) -fTracklet->GetYat(xc);
387       val[kPrez] = fTracklet->GetX0()-xc;
388       val[kZrez] = 0.; Int_t ic(0), tb(c->GetLocalTimeBin());;
389       if((cc = fTracklet->GetClusters(tb-1))) {val[kZrez] += TMath::Abs(cc->GetQ()); ic++;}
390       if((cc = fTracklet->GetClusters(tb-2))) {val[kZrez] += TMath::Abs(cc->GetQ()); ic++;}
391       if(ic) val[kZrez] /= (ic*q);
392       val[kSpeciesChgRC]= fTracklet->IsRowCross()?0.:(TMath::Max(q*corr, Float_t(3.)));
393       val[kNdim]   = fEvent?fEvent->GetMultiplicity():0.;
394       val[kNdim+1] = c->IsFivePad()?1:c->GetNPads();
395       H->Fill(val);
396 /*      // tilt rotation of covariance for clusters
397       Double_t sy2(c->GetSigmaY2()), sz2(c->GetSigmaZ2());
398       cov[0] = (sy2+t2*sz2)*corr;
399       cov[1] = tilt*(sz2 - sy2)*corr;
400       cov[2] = (t2*sy2+sz2)*corr;
401       // sum with track covariance
402       cov[0]+=covR[0]; cov[1]+=covR[1]; cov[2]+=covR[2];
403       Double_t dyz[2]= {dy[1], dz[1]};
404       Pulls(dyz, cov, tilt);*/
405
406       // Get z-position with respect to anode wire
407       Float_t yt(fTracklet->GetYref(0)-val[kZrez]*fTracklet->GetYref(1)),
408               zt(fTracklet->GetZref(0)-val[kZrez]*fTracklet->GetZref(1));
409       Int_t istk = geo->GetStack(c->GetDetector());
410       AliTRDpadPlane *pp = geo->GetPadPlane(ily, istk);
411       Float_t rowZ = pp->GetRow0();
412       Float_t d  = rowZ - zt + pp->GetAnodeWireOffset();
413       d -= ((Int_t)(2 * d)) / 2.0;
414       if (d > 0.25) d  = 0.5 - d;
415
416       AliTRDclusterInfo *clInfo(NULL);
417       clInfo = new AliTRDclusterInfo;
418       clInfo->SetCluster(c);
419       //Float_t covF[] = {cov[0], cov[1], cov[2]};
420       clInfo->SetGlobalPosition(yt, zt, fTracklet->GetYref(1), fTracklet->GetZref(1)/*, covF*/);
421       clInfo->SetResolution(val[kYrez]);
422       clInfo->SetAnisochronity(d);
423       clInfo->SetDriftLength(val[kZrez]);
424       clInfo->SetTilt(fTracklet->GetTilt());
425       if(fCl) fCl->Add(clInfo);
426       //else AliDebug(1, "Cl exchange container missing. Activate by calling \"InitExchangeContainers()\"");
427
428       if(DebugLevel()>=2){
429         if(!clInfoArr){
430           clInfoArr=new TObjArray(AliTRDseedV1::kNclusters);
431           clInfoArr->SetOwner(kFALSE);
432         }
433         clInfoArr->Add(clInfo);
434       }
435     }
436     if(DebugLevel()>=2 && clInfoArr){
437       ULong_t status = fkESD->GetStatus();
438       (*DebugStream()) << "cluster"
439         <<"status="  << status
440         <<"clInfo.=" << clInfoArr
441         << "\n";
442       clInfoArr->Clear();
443     }
444   }
445   if(clInfoArr) delete clInfoArr;
446
447   if(!track) return NULL;
448   // special care for EVE usage
449   TH1 *h(NULL);
450   if((h = (TH1*)gDirectory->Get(Form("%s_proj_%d", H->GetName(), kYrez)))) delete h;
451   return H->Projection(kYrez);
452 }
453
454
455 //________________________________________________________
456 TH1* AliTRDresolution::PlotTracklet(const AliTRDtrackV1 *track)
457 {
458 // Plot normalized residuals for tracklets to track.
459 //
460 // We start from the result that if X=N(|m|, |Cov|)
461 // BEGIN_LATEX
462 // (Cov^{-1})^{1/2}X = N((Cov^{-1})^{1/2}*|m|, |1|)
463 // END_LATEX
464 // in our case X=(y_trklt - y_trk z_trklt - z_trk) and |Cov| = |Cov_trklt| + |Cov_trk| at the radial
465 // reference position.
466   if(track) fkTrack = track;
467   if(!fkTrack){
468     AliDebug(4, "No Track defined.");
469     return NULL;
470   }
471   if(fkESD && TMath::Abs(fkESD->GetTOFbc())>1){
472     AliDebug(4, Form("Track with BC_index[%d] not used.", fkESD->GetTOFbc()));
473     //return NULL;
474   }
475   THnSparse *H(NULL);
476   if(!fContainer || !(H = (THnSparse*)fContainer->At(kTracklet))){
477     AliWarning("No output container defined.");
478     return NULL;
479   }
480
481   const Int_t ndim(kNdim+8);
482   Double_t val[ndim],
483            alpha(0.), cs(-2.), sn(0.);
484   Float_t sz[AliTRDseedV1::kNtb], pos[AliTRDseedV1::kNtb];
485   Int_t ntbGap[AliTRDseedV1::kNtb];
486   AliTRDseedV1 *fTracklet(NULL);
487   for(Int_t il(0); il<AliTRDgeometry::kNlayer; il++){
488     if(!(fTracklet = fkTrack->GetTracklet(il))) continue;
489     if(!fTracklet->IsOK() || !fTracklet->IsChmbGood()) continue;
490     val [kBC] = il;
491     if(cs<-1.){
492       alpha = (0.5+AliTRDgeometry::GetSector(fTracklet->GetDetector()))*AliTRDgeometry::GetAlpha();
493       cs    = TMath::Cos(alpha);
494       sn    = TMath::Sin(alpha);
495     }
496     val[kPhi] = TMath::ATan2(fTracklet->GetX()*sn + fTracklet->GetY()*cs, fTracklet->GetX()*cs - fTracklet->GetY()*sn);
497     Float_t tgl = fTracklet->GetZ()/fTracklet->GetX()/TMath::Sqrt(1.+fTracklet->GetY()*fTracklet->GetY()/fTracklet->GetX()/fTracklet->GetX());//fTracklet->GetTgl();
498     val[kEta] = -TMath::Log(TMath::Tan(0.5 *  (0.5*TMath::Pi() - TMath::ATan(tgl))));
499
500     val[kSpeciesChgRC]= fTracklet->IsRowCross()?0:fkTrack->Charge();// fSpecies;
501     val[kPt]  = GetPtBinSignificant(fPt); //fPt<0.8?0:(fPt<1.5?1:2);//GetPtBin(fTracklet->GetMomentum());
502     Double_t dyt(fTracklet->GetYfit(0) - fTracklet->GetYref(0)),
503              dzt(fTracklet->GetZfit(0) - fTracklet->GetZref(0)),
504              dydx(fTracklet->GetYfit(1)),
505              tilt(fTracklet->GetTilt());
506     // correct for tilt rotation
507     val[kYrez] = dyt - dzt*tilt;
508     val[kZrez] = fTracklet->IsRowCross()?(dzt + dyt*tilt):(fTracklet->GetdQdl()*3.e-4-1.5);
509     dydx+= tilt*fTracklet->GetZref(1);
510     val[kPrez] = TMath::ATan((dydx - fTracklet->GetYref(1))/(1.+ fTracklet->GetYref(1)*dydx)) * TMath::RadToDeg();
511     val[kNdim] = fEvent?fEvent->GetMultiplicity():0;
512     val[kNdim+1] = 1.e2*fTracklet->GetTBoccupancy()/AliTRDseedV1::kNtb;
513     Int_t n = fTracklet->GetChargeGaps(sz, pos, ntbGap);
514     val[kNdim+2] = 0.; for(Int_t igap(0); igap<n; igap++) val[kNdim+2] += sz[igap];
515     for(Int_t ifill(0); ifill<3; ifill++){ val[kNdim+3+ifill]=0.;val[kNdim+4+ifill]=0.;}
516     for(Int_t igap(0), ifill(0); igap<n&&ifill<2; igap++){
517       if(ntbGap[igap]<2) continue;
518       val[kNdim+3+ifill] = sz[igap];
519       val[kNdim+4+ifill] = pos[igap];
520       ifill++;
521     }
522     H->Fill(val);
523
524 //     // compute covariance matrix
525 //     fTracklet->GetCovAt(x, cov);
526 //     fTracklet->GetCovRef(covR);
527 //     cov[0] += covR[0]; cov[1] += covR[1]; cov[2] += covR[2];
528 //     Double_t dyz[2]= {dy[1], dz[1]};
529 //     Pulls(dyz, cov, tilt);
530 //     ((TH3S*)arr->At(1))->Fill(sgm[fSegmentLevel], dyz[0], dyz[1]);
531 //     ((TH3S*)arr->At(3))->Fill(tht, dyz[1], rc);
532
533     if(DebugLevel()>=3){
534       Bool_t rc(fTracklet->IsRowCross());
535       UChar_t err(fTracklet->GetErrorMsg());
536       Double_t x(fTracklet->GetX()),
537                pt(fTracklet->GetPt()),
538                yt(fTracklet->GetYref(0)),
539                zt(fTracklet->GetZref(0)),
540                phi(fTracklet->GetYref(1)),
541                tht(fTracklet->GetZref(1));
542       Int_t ncl(fTracklet->GetN()), det(fTracklet->GetDetector());
543       (*DebugStream()) << "tracklet"
544         <<"pt="  << pt
545         <<"x="   << x
546         <<"yt="  << yt
547         <<"zt="  << zt
548         <<"phi=" << phi
549         <<"tht=" << tht
550         <<"det=" << det
551         <<"n="   << ncl
552         <<"dy0=" << dyt
553         <<"dz0=" << dzt
554         <<"dy="  << val[kYrez]
555         <<"dz="  << val[kZrez]
556         <<"dphi="<< val[kPrez]
557         <<"dQ  ="<< val[kNdim]
558         <<"rc="  << rc
559         <<"err=" << err
560         << "\n";
561     }
562   }
563   if(!track) return NULL;
564   // special care for EVE usage
565   TH1 *h(NULL);
566   if((h = (TH1*)gDirectory->Get(Form("%s_proj_%d", H->GetName(), kYrez)))) delete h;
567   return H->Projection(kYrez);
568 }
569
570
571 //________________________________________________________
572 TH1* AliTRDresolution::PlotTrackIn(const AliTRDtrackV1 *track)
573 {
574 // Store resolution/pulls of Kalman before updating with the TRD information
575 // at the radial position of the first tracklet. The following points are used
576 // for comparison
577 //  - the (y,z,snp) of the first TRD tracklet
578 //  - the (y, z, snp, tgl, pt) of the MC track reference
579 //
580 // Additionally the momentum resolution/pulls are calculated for usage in the
581 // PID calculation.
582   //printf("AliTRDresolution::PlotTrackIn() :: track[%p]\n", (void*)track);
583
584   if(track) fkTrack = track;
585   if(!fkTrack){
586     AliDebug(4, "No Track defined.");
587     return NULL;
588   }
589   //fkTrack->Print();
590   TH1 *h(NULL); // EVE projection
591   // check container
592   THnSparseI *H=(THnSparseI*)fContainer->At(kTrackIn);
593   if(!H){
594     AliError(Form("Missing container @ %d", Int_t(kTrackIn)));
595     return NULL;
596   }
597   // check input track status
598   AliExternalTrackParam *tin(NULL);
599   if(!(tin = fkTrack->GetTrackIn())){
600     AliError("Track did not entered TRD fiducial volume.");
601     return NULL;
602   }
603   // check first tracklet
604   AliTRDseedV1 *fTracklet(fkTrack->GetTracklet(0));
605   if(!fTracklet){
606     AliDebug(3, "No Tracklet in ly[0]. Skip track.");
607     if(!track) return NULL;
608     // special care for EVE usage
609     if((h = (TH1*)gDirectory->Get(Form("%s_proj_%d", H->GetName(), kYrez)))) delete h;
610     return H->Projection(kYrez);
611   }
612   if(!fTracklet->IsOK() || !fTracklet->IsChmbGood()){
613     AliDebug(3, "Tracklet or Chamber not OK. Skip track.");
614     if(!track) return NULL;
615     // special care for EVE usage
616     if((h = (TH1*)gDirectory->Get(Form("%s_proj_%d", H->GetName(), kYrez)))) delete h;
617     return H->Projection(kYrez);
618   }
619   // check radial position
620   Double_t x = tin->GetX();
621   if(TMath::Abs(x-fTracklet->GetX())>1.e-3){
622     AliDebug(1, Form("Tracklet did not match Track. dx[cm]=%+4.1f", x-fTracklet->GetX()));
623     if(!track) return NULL;
624     // special care for EVE usage
625     if((h = (TH1*)gDirectory->Get(Form("%s_proj_%d", H->GetName(), kYrez)))) delete h;
626     return H->Projection(kYrez);
627   }
628
629   Int_t bc(fkESD?fkESD->GetTOFbc()/2:0);
630   const Double_t *parR(tin->GetParameter());
631   Double_t dyt(fTracklet->GetYfit(0)-parR[0]), dzt(fTracklet->GetZfit(0)-parR[1]),
632             phit(fTracklet->GetYfit(1)),
633             tilt(fTracklet->GetTilt()),
634             norm(1./TMath::Sqrt((1.-parR[2])*(1.+parR[2])));
635
636   // correct for tilt rotation
637   Double_t dy  = dyt - dzt*tilt,
638            dz  = dzt + dyt*tilt,
639            dx  = dy/(parR[2]*norm-parR[3]*norm*tilt);
640   phit       += tilt*parR[3];
641   Double_t dphi = TMath::ATan(phit) - TMath::ASin(parR[2]);
642
643   Double_t val[kNdim+3];
644   val[kBC]          = bc==0?0:(bc<0?-1.:1.);
645   Double_t alpha = (0.5+AliTRDgeometry::GetSector(fTracklet->GetDetector()))*AliTRDgeometry::GetAlpha(),
646            cs    = TMath::Cos(alpha),
647            sn    = TMath::Sin(alpha);
648   val[kPhi] = TMath::ATan2(fTracklet->GetX()*sn + fTracklet->GetY()*cs, fTracklet->GetX()*cs - fTracklet->GetY()*sn);
649   Float_t tgl = fTracklet->GetZ()/fTracklet->GetX()/TMath::Sqrt(1.+fTracklet->GetY()*fTracklet->GetY()/fTracklet->GetX()/fTracklet->GetX());
650   val[kEta] = -TMath::Log(TMath::Tan(0.5 *  (0.5*TMath::Pi() - TMath::ATan(tgl))));
651   val[kYrez]        = dy;
652   val[kZrez]        = fTracklet->IsRowCross()?dz:(fTracklet->GetdQdl()*5.e-4 - 2.5);
653   val[kPrez]        = dphi*TMath::RadToDeg();
654   val[kSpeciesChgRC]= fTracklet->IsRowCross()?0:fSpecies; //printf("val[%d] = %4.2f\n", kSpeciesChgRC, val[kSpeciesChgRC]);
655   val[kPt]          = GetPtBinSignificant(fPt); //fPt<0.8?0:(fPt<1.5?1:2);//GetPtBin(fPt);
656   val[kNdim]        = GetPtBin(fTracklet->GetMomentum());
657   val[kNdim+1]      = dx;
658   val[kNdim+2]      = fEvent?fEvent->GetBunchFill():0;
659   H->Fill(val);
660   if(DebugLevel()>=3){
661     (*DebugStream()) << "trackIn"
662       <<"tracklet.="  << fTracklet
663       <<"trackIn.="   << tin
664       << "\n";
665   }
666
667   if(!track) return NULL;
668   // special care for EVE usage
669   if((h = (TH1*)gDirectory->Get(Form("%s_proj_%d", H->GetName(), kYrez)))) delete h;
670   return H->Projection(kYrez);
671 }
672
673 /*
674 //________________________________________________________
675 TH1* AliTRDresolution::PlotTrackOut(const AliTRDtrackV1 *track)
676 {
677 // Store resolution/pulls of Kalman after last update with the TRD information
678 // at the radial position of the first tracklet. The following points are used
679 // for comparison
680 //  - the (y,z,snp) of the first TRD tracklet
681 //  - the (y, z, snp, tgl, pt) of the MC track reference
682 //
683 // Additionally the momentum resolution/pulls are calculated for usage in the
684 // PID calculation.
685
686   if(track) fkTrack = track;
687   return NULL;
688 }
689 */
690 //________________________________________________________
691 TH1* AliTRDresolution::PlotMC(const AliTRDtrackV1 *track)
692 {
693   //
694   // Plot MC distributions
695   //
696
697   if(!HasMCdata()) return NULL;
698   if(track) fkTrack = track;
699   if(!fkTrack){
700     AliDebug(4, "No Track defined.");
701     return NULL;
702   }
703   Int_t bc(TMath::Abs(fkESD->GetTOFbc()));
704
705   THnSparse *H(NULL);
706   if(!fContainer){
707     AliWarning("No output container defined.");
708     return NULL;
709   }
710   // retriev track characteristics
711   Int_t pdg = fkMC->GetPDG(),
712         sIdx(AliTRDpidUtil::Pdg2Pid(TMath::Abs(pdg))+1), // species index
713         sign(0),
714 //        sgm[3],
715         label(fkMC->GetLabel());
716 //        fSegmentLevel(0);
717   if(!fDBPDG) fDBPDG=TDatabasePDG::Instance();
718   TParticlePDG *ppdg(fDBPDG->GetParticle(pdg));
719   if(ppdg) sign = ppdg->Charge() > 0. ? 1 : -1;
720
721   TH1 *h(NULL);
722   AliTRDgeometry *geo(AliTRDinfoGen::Geometry());
723   AliTRDseedV1 *fTracklet(NULL); TObjArray *clInfoArr(NULL);
724   UChar_t s;
725   Double_t x, y, z, pt, dydx, dzdx, dzdl;
726   Float_t pt0, x0, y0, z0, dx, dy, dz, dydx0, dzdx0;
727   Double_t covR[7]/*, cov[3]*/;
728
729 /*  if(DebugLevel()>=3){
730     // get first detector
731     Int_t det = -1;
732     for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
733       if(!(fTracklet = fkTrack->GetTracklet(ily))) continue;
734       det = fTracklet->GetDetector();
735       break;
736     }
737     if(det>=0){
738       TVectorD X(12), Y(12), Z(12), dX(12), dY(12), dZ(12), vPt(12), dPt(12), budget(12), cCOV(12*15);
739       Double_t m(-1.);
740       m = fkTrack->GetMass();
741       if(fkMC->PropagateKalman(&X, &Y, &Z, &dX, &dY, &dZ, &vPt, &dPt, &budget, &cCOV, m)){
742         (*DebugStream()) << "MCkalman"
743           << "pdg=" << pdg
744           << "det=" << det
745           << "x="   << &X
746           << "y="   << &Y
747           << "z="   << &Z
748           << "dx="  << &dX
749           << "dy="  << &dY
750           << "dz="  << &dZ
751           << "pt="  << &vPt
752           << "dpt=" << &dPt
753           << "bgt=" << &budget
754           << "cov=" << &cCOV
755           << "\n";
756       }
757     }
758   }*/
759   AliTRDcluster *c(NULL);
760   Double_t val[kNdim+1];
761   for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
762     if(!(fTracklet = fkTrack->GetTracklet(ily)))/* ||
763        !fTracklet->IsOK())*/ continue;
764
765     x= x0 = fTracklet->GetX();
766     Bool_t rc(fTracklet->IsRowCross()); Float_t eta, phi;
767     if(!fkMC->GetDirections(x0, y0, z0, dydx0, dzdx0, pt0, eta, phi, s)) continue;
768
769     // MC track position at reference radial position
770     dx  = x0 - x;
771     Float_t ymc = y0 - dx*dydx0;
772     Float_t zmc = z0 - dx*dzdx0;
773     //phi -= TMath::Pi();
774
775     val[kBC]  = ily;
776     val[kPhi] = phi;
777     val[kEta] = eta;
778     val[kSpeciesChgRC]= rc?0.:sign*sIdx;
779     val[kPt]  = pt0<0.8?0:(pt0<1.5?1:2);//GetPtBin(pt0);
780     Double_t tilt(fTracklet->GetTilt());
781 //             ,t2(tilt*tilt)
782 //             ,corr(1./(1. + t2))
783 //             ,cost(TMath::Sqrt(corr));
784
785     AliExternalTrackParam *tin(fkTrack->GetTrackIn());
786     if(ily==0 && tin){ // trackIn residuals
787       // check radial position
788       if(TMath::Abs(tin->GetX()-x)>1.e-3) AliDebug(1, Form("TrackIn radial mismatch. dx[cm]=%+4.1f", tin->GetX()-x));
789       else{
790         val[kBC]          = (bc>=kNbunchCross)?(kNbunchCross-1):bc;
791         val[kYrez]        = tin->GetY()-ymc;
792         val[kZrez]        = rc?(tin->GetZ()-zmc):(fTracklet->GetdQdl()*1.8e-4 - 0.9);
793         val[kPrez]        = (TMath::ASin(tin->GetSnp())-TMath::ATan(dydx0))*TMath::RadToDeg();
794         if((H = (THnSparseI*)fContainer->At(kMCtrackIn))) H->Fill(val);
795       }
796     }
797     //if(bc>1) break; // do nothing for the rest of TRD objects if satellite bunch
798
799     // track residuals
800     dydx = fTracklet->GetYref(1);
801     dzdx = fTracklet->GetZref(1);
802     dzdl = fTracklet->GetTgl();
803     y  = fTracklet->GetYref(0);
804     dy = y - ymc;
805     z  = fTracklet->GetZref(0);
806     dz = z - zmc;
807     pt = TMath::Abs(fTracklet->GetPt());
808     fTracklet->GetCovRef(covR);
809
810     val[kYrez] = dy;
811     val[kPrez] = TMath::ATan((dydx - dydx0)/(1.+ dydx*dydx0))*TMath::RadToDeg();
812     val[kZrez] = dz;
813     val[kNdim] = 1.e2*(pt/pt0-1.);
814     if((H = (THnSparse*)fContainer->At(kMCtrack))) H->Fill(val);
815 /*      // theta resolution/ tgl pulls
816       Double_t dzdl0 = dzdx0/TMath::Sqrt(1.+dydx0*dydx0),
817                 dtgl = (dzdl - dzdl0)/(1.- dzdl*dzdl0);
818       ((TH2I*)arr->At(6))->Fill(dzdl0, TMath::ATan(dtgl));
819       ((TH2I*)arr->At(7))->Fill(dzdl0, (dzdl - dzdl0)/TMath::Sqrt(covR[4]));
820       // pt resolution  \\ 1/pt pulls \\ p resolution for PID
821       Double_t p0 = TMath::Sqrt(1.+ dzdl0*dzdl0)*pt0,
822               p  = TMath::Sqrt(1.+ dzdl*dzdl)*pt;
823       ((TH3S*)((TObjArray*)arr->At(8)))->Fill(pt0, pt/pt0-1., sign*sIdx);
824       ((TH3S*)((TObjArray*)arr->At(9)))->Fill(1./pt0, (1./pt-1./pt0)/TMath::Sqrt(covR[6]), sign*sIdx);
825       ((TH3S*)((TObjArray*)arr->At(10)))->Fill(p0, p/p0-1., sign*sIdx);*/
826
827     // Fill Debug stream for MC track
828     if(DebugLevel()>=4){
829       Int_t det(fTracklet->GetDetector());
830       (*DebugStream()) << "MC"
831         << "det="     << det
832         << "pdg="     << pdg
833         << "sgn="     << sign
834         << "pt="      << pt0
835         << "x="       << x0
836         << "y="       << y0
837         << "z="       << z0
838         << "dydx="    << dydx0
839         << "dzdx="    << dzdx0
840         << "\n";
841
842       // Fill Debug stream for Kalman track
843       (*DebugStream()) << "MCtrack"
844         << "pt="      << pt
845         << "x="       << x
846         << "y="       << y
847         << "z="       << z
848         << "dydx="    << dydx
849         << "dzdx="    << dzdx
850         << "s2y="     << covR[0]
851         << "s2z="     << covR[2]
852         << "\n";
853     }
854
855     // tracklet residuals
856     dydx = fTracklet->GetYfit(1) + tilt*dzdx0;
857     dzdx = fTracklet->GetZfit(1);
858     y  = fTracklet->GetYfit(0);
859     dy = y - ymc;
860     z  = fTracklet->GetZfit(0);
861     dz = z - zmc;
862     val[kYrez] = dy - dz*tilt;
863     val[kPrez] = TMath::ATan((dydx - dydx0)/(1.+ dydx*dydx0))*TMath::RadToDeg();
864     val[kZrez] = rc?(dz + dy*tilt):(fTracklet->GetdQdl()*3.e-4 - 1.5);
865 //      val[kNdim] = pt/pt0-1.;
866     if((H = (THnSparse*)fContainer->At(kMCtracklet))) H->Fill(val);
867
868
869     // Fill Debug stream for tracklet
870     if(DebugLevel()>=4){
871       Float_t s2y = fTracklet->GetS2Y();
872       Float_t s2z = fTracklet->GetS2Z();
873       (*DebugStream()) << "MCtracklet"
874         << "rc="    << rc
875         << "x="     << x
876         << "y="     << y
877         << "z="     << z
878         << "dydx="  << dydx
879         << "s2y="   << s2y
880         << "s2z="   << s2z
881         << "\n";
882     }
883
884     AliTRDpadPlane *pp = geo->GetPadPlane(ily, AliTRDgeometry::GetStack(fTracklet->GetDetector()));
885     Float_t zr0 = pp->GetRow0() + pp->GetAnodeWireOffset();
886     //Double_t exb = AliTRDCommonParam::Instance()->GetOmegaTau(1.5);
887
888     H = (THnSparse*)fContainer->At(kMCcluster);
889     val[kPt]  = TMath::ATan(dydx0)*TMath::RadToDeg();
890     //Float_t corr = 1./TMath::Sqrt(1.+dydx0*dydx0+dzdx0*dzdx0);
891     Int_t row0(-1);
892     Float_t padCorr(tilt*fTracklet->GetPadLength());
893     fTracklet->ResetClusterIter(kTRUE);
894     while((c = fTracklet->NextCluster())){
895       if(row0<0) row0 = c->GetPadRow();
896       x = c->GetX();//+fXcorr[c->GetDetector()][c->GetLocalTimeBin()];
897       y = c->GetY()  + padCorr*(c->GetPadRow() - row0);
898       z = c->GetZ();
899       dx = x0 - x;
900       ymc= y0 - dx*dydx0;
901       zmc= z0 - dx*dzdx0;
902       dy = y - ymc;
903       dz = z - zmc;
904       val[kYrez] = dy - dz*tilt;
905       val[kPrez] = dx;
906       val[kZrez] = 0.; AliTRDcluster *cc(NULL); Int_t ic(0), tb(c->GetLocalTimeBin()); Float_t  q(TMath::Abs(c->GetQ()));
907       if((cc = fTracklet->GetClusters(tb-1))) {val[kZrez] += TMath::Abs(cc->GetQ()); ic++;}
908       if((cc = fTracklet->GetClusters(tb-2))) {val[kZrez] += TMath::Abs(cc->GetQ()); ic++;}
909       if(ic) val[kZrez] /= (ic*q);
910       if(H) H->Fill(val);
911
912
913       // Fill calibration container
914       Float_t d = zr0 - zmc;
915       d -= ((Int_t)(2 * d)) / 2.0;
916       if (d > 0.25) d  = 0.5 - d;
917       AliTRDclusterInfo *clInfo = new AliTRDclusterInfo;
918       clInfo->SetCluster(c);
919       clInfo->SetMC(pdg, label);
920       clInfo->SetGlobalPosition(ymc, zmc, dydx0, dzdx0);
921       clInfo->SetResolution(dy);
922       clInfo->SetAnisochronity(d);
923       clInfo->SetDriftLength(dx);
924       clInfo->SetTilt(tilt);
925       if(fMCcl) fMCcl->Add(clInfo);
926       else AliDebug(1, "MCcl exchange container missing. Activate by calling \"InitExchangeContainers()\"");
927       if(DebugLevel()>=5){
928         if(!clInfoArr){
929           clInfoArr=new TObjArray(AliTRDseedV1::kNclusters);
930           clInfoArr->SetOwner(kFALSE);
931         }
932         clInfoArr->Add(clInfo);
933       }
934     }
935     // Fill Debug Tree
936     if(DebugLevel()>=5 && clInfoArr){
937       (*DebugStream()) << "MCcluster"
938         <<"clInfo.=" << clInfoArr
939         << "\n";
940       clInfoArr->Clear();
941     }
942   }
943   if(clInfoArr) delete clInfoArr;
944   if(!track) return NULL;
945   // special care for EVE usage
946   if(H && (h = (TH1*)gDirectory->Get(Form("%s_proj_%d", H->GetName(), kYrez)))) delete h;
947   return H?H->Projection(kYrez):NULL;
948 }
949
950
951 //__________________________________________________________________________
952 Int_t AliTRDresolution::GetPtBin(Float_t pt)
953 {
954 // Find pt bin according to local pt segmentation
955   Int_t ipt(-1);
956   while(ipt<24){
957     if(pt<fgPtBin[ipt+1]) break;
958     ipt++;
959   }
960   return ipt;
961 }
962
963
964 //________________________________________________________
965 void AliTRDresolution::GetRangeZ(TH2 *h2, Float_t &min, Float_t &max)
966 {
967 // Get range on Z axis such to avoid outliers
968
969   Double_t cnt[20000], c, m, s;
970   Int_t nx(h2->GetXaxis()->GetNbins()), ny(h2->GetYaxis()->GetNbins()), nc(0);
971   for(Int_t ix(1); ix<=nx; ix++){
972     for(Int_t iy(1); iy<=ny; iy++){
973       if((c = h2->GetBinContent(ix, iy))<10) continue;
974       cnt[nc++] = c;
975       if(nc==20000) break;
976     }
977     if(nc==20000) break;
978   }
979   AliMathBase::EvaluateUni(nc, cnt, m, s, 0);
980   min = m-s; max = m+2.*s;
981 }
982
983 //________________________________________________________
984 Bool_t AliTRDresolution::GetRefFigure(Int_t ifig)
985 {
986   //
987   // Get the reference figures
988   //
989
990   if(!gPad){
991     AliWarning("Please provide a canvas to draw results.");
992     return kFALSE;
993   }
994 /*  Int_t selection[100], n(0), selStart(0); //
995   Int_t ly0(0), dly(5);
996   TList *l(NULL); TVirtualPad *pad(NULL); */
997   switch(ifig){
998   case 0:
999     break;
1000   }
1001   AliWarning(Form("Reference plot [%d] missing result", ifig));
1002   return kFALSE;
1003 }
1004
1005
1006 //________________________________________________________
1007 void AliTRDresolution::MakePtSegmentation(Float_t pt0, Float_t dpt)
1008 {
1009 // Build pt segments
1010   for(Int_t j(0); j<=24; j++){
1011     pt0+=(TMath::Exp(j*j*dpt)-1.);
1012     fgPtBin[j]=pt0;
1013   }
1014 }
1015
1016 //________________________________________________________
1017 void AliTRDresolution::MakeSummary()
1018 {
1019 // Build summary plots
1020
1021   if(!fProj){
1022     AliError("Missing results");
1023     return;
1024   }
1025   TVirtualPad *p(NULL); TCanvas *cOut(NULL);
1026   TObjArray *arr(NULL); TH2 *h2(NULL);
1027
1028   // cluster resolution
1029   // define palette
1030   gStyle->SetPalette(1);
1031   const Int_t nClViews(9);
1032   const Char_t *vClName[nClViews] = {"ClY", "ClYn", "ClYp", "ClQn", "ClQp", "ClYXTCp", "ClYXTCn", "ClYXPh", "ClYXPh"};
1033   const UChar_t vClOpt[nClViews] = {1, 1, 1, 0, 0, 0, 0, 0, 1};
1034   const Float_t vClSignMin[2] = {2.6e2, 4.4e2},
1035                 vClSignMax[2] = {4.4e2, 6.2e2},
1036                 vClMin[nClViews] = {3.2e2, vClSignMin[Int_t(fBsign)], vClSignMin[Int_t(!fBsign)], 0., 0., 0., 0., 0., 3.2e2},
1037                 vClMax[nClViews] = {5.e2, vClSignMax[Int_t(fBsign)], vClSignMax[Int_t(!fBsign)], 0., 0., 0., 0., 0., 5.e2};
1038   const Int_t nTrkltViews(20);
1039   const Char_t *vTrkltName[nTrkltViews] = {
1040     "TrkltY", "TrkltYn", "TrkltYp", "TrkltY", "TrkltYn", "TrkltYp",
1041     "TrkltRCZ",
1042     "TrkltPh", "TrkltPhn", "TrkltPhp",
1043     "TrkltQ", "TrkltQn", "TrkltQp",
1044     "TrkltQS", "TrkltQSn", "TrkltQSp",
1045     "TrkltTBn", "TrkltTBp", "TrkltTBn", "TrkltTBp"
1046 //    "TrkltYnl0", "TrkltYpl0", "TrkltPhnl0", "TrkltPhpl0", "TrkltQnl0", "TrkltQpl0",  // electrons low pt
1047 /*    "TrkltYnl1", "TrkltYpl1", "TrkltPhnl1", "TrkltPhpl1", "TrkltQnl1", "TrkltQpl1",  // muons low pt
1048     "TrkltYnl2", "TrkltYpl2", "TrkltPhnl2", "TrkltPhpl2", "TrkltQnl2", "TrkltQpl2"  // pions low pt*/
1049   };
1050   const UChar_t vTrkltOpt[nTrkltViews] = {
1051     0, 0, 0, 1, 1, 1,
1052     0,
1053     0, 0, 0,
1054     0, 0, 0,
1055     0, 0, 0,
1056     0, 0, 2, 2
1057   };
1058   const Int_t nTrkInViews(5);
1059   const Char_t *vTrkInName[nTrkInViews][6] = {
1060     {"TrkInY", "TrkInYn", "TrkInYp", "TrkInRCZ", "TrkInPhn", "TrkInPhp"},
1061     {"TrkInY", "TrkInYn", "TrkInYp", "TrkInRCZ", "TrkInPhn", "TrkInPhp"},
1062     {"TrkInYnl", "TrkInYni", "TrkInYnh", "TrkInYpl", "TrkInYpi", "TrkInYph"},
1063     {"TrkInXnl", "TrkInXpl", "TrkInXl", "TrkInYnh", "TrkInYph", "TrkInYh"},
1064     {"TrkInPhnl", "TrkInPhni", "TrkInPhnh", "TrkInPhpl", "TrkInPhpi", "TrkInPhph"},
1065     //{"TrkInRCX", "TrkInRCY", "TrkInRCPh", "TrkInRCZl", "TrkInRCZi", "TrkInRCZh"}
1066   };
1067   const UChar_t vTrkInOpt[nTrkInViews] = {0, 1, 0, 0, 0};
1068   const Float_t min[6] = {0.15, 0.15, 0.15, 0.15, 0.5, 0.5};
1069   const Float_t max[6] = {0.6, 0.6, 0.6, 0.6, 2.3, 2.3};
1070   const Char_t *ttt[6] = {"#sigma(#Deltay) [cm]", "#sigma(#Deltay) [cm]", "#sigma(#Deltay) [cm]", "#sigma(#Deltaz) [cm]", "#sigma(#Delta#phi) [deg]", "#sigma(#Delta#phi) [deg]"};
1071
1072   const Int_t nTrkViews(27);
1073   const Char_t *vTrkName[nTrkViews] = {
1074     "TrkY", "TrkYn", "TrkYp",
1075     "TrkPh", "TrkPhn", "TrkPhp",
1076     "TrkDPt", "TrkDPtn", "TrkDPtp",
1077     "TrkYnl0", "TrkYpl0", "TrkPhnl0", "TrkPhpl0", "TrkDPtnl0", "TrkDPtpl0",  // electrons low pt
1078     "TrkYnl1", "TrkYpl1", "TrkPhnl1", "TrkPhpl1", "TrkDPtnl1", "TrkDPtpl1",  // muons low pt
1079     "TrkYnl2", "TrkYpl2", "TrkPhnl2", "TrkPhpl2", "TrkDPtnl2", "TrkDPtpl2"  // pions low pt
1080   };
1081   const Char_t *typName[] = {"", "MC"};
1082   const Int_t nx(2048), ny(1536);
1083
1084   if((arr = (TObjArray*)fProj->At(kDetector))){
1085     cOut = new TCanvas(Form("%s_DetOccupancy", GetName()), "Detector performance", 2*nx, 2*ny);
1086     cOut->Divide(AliTRDgeometry::kNlayer,AliTRDeventInfo::kCentralityClasses, 1.e-5, 1.e-5);
1087     for(Int_t icen(0); icen<AliTRDeventInfo::kCentralityClasses; icen++){
1088       for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1089         p=cOut->cd(icen*AliTRDgeometry::kNlayer+ily+1); p->SetRightMargin(0.1572581);p->SetTopMargin(0.08262712);
1090         if(!(h2 = (TH2*)arr->FindObject(Form("HDet%d%dEn", ily, icen)))) continue;
1091         SetNormZ(h2, 1, -1, 1, -1, 10.);  // cut all bins with < 10 entries
1092         SetRangeZ(h2, -90., 90, -200.);
1093         //h2->GetXaxis()->SetNdivisions(1010);
1094         h2->GetZaxis()->SetTitle("Rel. Det. Occup. [%]");
1095         h2->GetZaxis()->CenterTitle();
1096         h2->SetContour(9); h2->Draw("colz");
1097         MakeDetectorPlot(ily, "pad");
1098       }
1099     }
1100     cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1101     cOut = new TCanvas(Form("%s_DetCharge", GetName()), "Detector performance", nx, ny);
1102     cOut->Divide(3,2, 1.e-5, 1.e-5);
1103     for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1104       p=cOut->cd(ily+1); p->SetRightMargin(0.1572581);p->SetTopMargin(0.08262712);
1105       if(!(h2 = (TH2*)arr->FindObject(Form("HDet%d_2D", ily)))) continue;
1106       SetNormZ(h2, 1, -1, 1, -1, 10.); // cut all <q> < 10
1107       SetRangeZ(h2, -30., 30., -200.);
1108       //h2->GetXaxis()->SetNdivisions(1010);
1109       h2->GetZaxis()->SetTitle("Rel. Mean(q) [%]");
1110       h2->GetZaxis()->CenterTitle();
1111       h2->Draw("colz");
1112       MakeDetectorPlot(ily, "pad");
1113     }
1114     cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1115   }
1116   for(Int_t ityp(0); ityp<(HasMCdata()?2:1); ityp++){
1117     if((arr = (TObjArray*)fProj->At(ityp?kMCcluster:kCluster))){
1118       for(Int_t iview(0); iview<nClViews; iview++){
1119         cOut = new TCanvas(Form("%s_%s%s_%d", GetName(), typName[ityp], vClName[iview], vClOpt[iview]), "Cluster Resolution", nx, ny);
1120         cOut->Divide(3,2, 1.e-5, 1.e-5);
1121         Int_t nplot(0);
1122         for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1123           p=cOut->cd(ily+1);    p->SetRightMargin(0.1572581);p->SetTopMargin(0.08262712);
1124           if(!(h2 = (TH2*)arr->FindObject(Form("H%s%s%d_2D", typName[ityp], vClName[iview], ily)))) continue;
1125           nplot++;
1126           if(vClOpt[iview]==0) h2->Draw("colz");
1127           else if(vClOpt[iview]==1) DrawSigma(h2, "#sigma(#Deltay) [#mum]", vClMin[iview], vClMax[iview], 1.e4);
1128           if(iview<5) MakeDetectorPlot(ily);
1129         }
1130         if(nplot==AliTRDgeometry::kNlayer) cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1131         else delete cOut;
1132       }
1133     }
1134     // tracklet systematic
1135     if((arr = (TObjArray*)fProj->At(ityp?kMCtracklet:kTracklet))){
1136       for(Int_t iview(0); iview<nTrkltViews; iview++){
1137         cOut = new TCanvas(Form("%s_%s%s_%d", GetName(), typName[ityp], vTrkltName[iview], vTrkltOpt[iview]), "Tracklet Resolution", nx, ny);
1138         cOut->Divide(3,2, 1.e-5, 1.e-5);
1139         Int_t nplot(0);
1140         for(Int_t iplot(0); iplot<6; iplot++){
1141           p=cOut->cd(iplot+1); p->SetRightMargin(0.1572581); p->SetTopMargin(0.08262712);
1142           if(!(h2 = (TH2*)arr->FindObject(Form("H%s%s%d_2D", typName[ityp], vTrkltName[iview], iplot)))) continue;
1143           nplot++;
1144           if(vTrkltOpt[iview]==0) h2->Draw("colz");
1145           else if (vTrkltOpt[iview]==1) DrawSigma(h2, "#sigma(#Deltay) [cm]", .15, .4);
1146           else if (vTrkltOpt[iview]==2) DrawSigma(h2, "#sigma(occupancy) [%]", 10.5, 15.);
1147           MakeDetectorPlot(iplot);
1148         }
1149         if(nplot==6){
1150           cOut->Modified();cOut->Update();
1151           cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1152         }
1153         delete cOut;
1154       }
1155     }
1156     // trackIn systematic
1157     if((arr = (TObjArray*)fProj->At(ityp?kMCtrackIn:kTrackIn))){
1158       for(Int_t iview(0); iview<nTrkInViews; iview++){
1159         cOut = new TCanvas(Form("%s_%s%s_%d", GetName(), typName[ityp], vTrkInName[iview][0], vTrkInOpt[iview]), "Track IN Resolution", nx, ny);
1160         cOut->Divide(3,2, 1.e-5, 1.e-5);
1161         Int_t nplot(0);
1162         for(Int_t iplot(0); iplot<6; iplot++){
1163           p=cOut->cd(iplot+1); p->SetRightMargin(0.1572581); p->SetTopMargin(0.08262712);
1164           if(!(h2 = (TH2*)arr->FindObject(Form("H%s%s_2D", typName[ityp], vTrkInName[iview][iplot])))){
1165             AliInfo(Form("Missing H%s%s_2D", typName[ityp], vTrkInName[iview][iplot]));
1166             continue;
1167           }
1168           nplot++;
1169           if(vTrkInOpt[iview]==0){
1170             h2->Draw("colz");
1171             PutTrendValue(vTrkInName[iview][iplot], GetMeanStat(h2, -10., ">"));
1172           } else DrawSigma(h2, ttt[iplot], min[iplot], max[iplot]);
1173           MakeDetectorPlot(0);
1174         }
1175         if(nplot==6) cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1176         else delete cOut;
1177       }
1178       // species
1179       const Float_t zmin[] = {1., 20., 25., 10., 5.},
1180                     zmax[] = {10., 38., 43., 28., 14.};
1181       cOut = new TCanvas(Form("%s_%sTrkInSpc", GetName(), typName[ityp]), "Track IN PID", Int_t(1.5*nx), Int_t(1.5*ny));
1182       cOut->Divide(5,3, 1.e-5, 1.e-5);
1183       Int_t nplot(0); const Char_t *chName[] = {"p", "n", ""};
1184       for(Int_t ich(0), ipad(1); ich<3; ich++){
1185         TH2 *h2s(NULL);
1186         if(!(h2s = (TH2*)arr->FindObject(Form("H%sTrkInY%sEn", typName[ityp], chName[ich])))) {
1187           AliInfo(Form("Missing H%sTrkIn%sEn", typName[ityp], chName[ich]));
1188           continue;
1189         }
1190         for(Int_t ispec(0); ispec<AliPID::kSPECIES; ispec++){
1191           p=cOut->cd(ipad++); p->SetRightMargin(0.1572581); p->SetTopMargin(0.08262712);
1192           if(!(h2 = (TH2*)arr->FindObject(Form("H%sTrkInY%s%dEn", typName[ityp], chName[ich], ispec)))) {
1193             AliInfo(Form("Missing H%sTrkIn%s%dEn", typName[ityp], chName[ich], ispec));
1194             continue;
1195           }
1196           nplot++;
1197           h2->Divide(h2, h2s, 1.e2);
1198           h2->SetContour(9);
1199           h2->GetZaxis()->SetRangeUser(zmin[ispec], zmax[ispec]);
1200           h2->GetZaxis()->SetTitle("Rel. Abundancy [%]");h2->GetZaxis()->CenterTitle();
1201           TString tit(h2->GetTitle()); h2->SetTitle(Form("%s :: Relative Abundancy", ((*(tit.Tokenize("::")))[0])->GetName()));
1202           h2->Draw("colz");
1203           MakeDetectorPlot(0);
1204         }
1205       }
1206       if(nplot==15) cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1207       else delete cOut;
1208
1209       const char *chQ[] = {"Q", "QS"};
1210       for(Int_t iq(0); iq<2; iq++){
1211         cOut = new TCanvas(Form("%s_%sTrkIn%s", GetName(), typName[ityp], chQ[iq]), "Track IN PID", Int_t(1.5*nx), Int_t(1.5*ny));
1212         cOut->Divide(5,3, 1.e-5, 1.e-5);
1213         nplot=0;
1214         for(Int_t ich(0), ipad(1); ich<3; ich++){
1215           for(Int_t ispec(0); ispec<AliPID::kSPECIES; ispec++){
1216             p=cOut->cd(ipad++); p->SetRightMargin(0.1572581); p->SetTopMargin(0.08262712);
1217             if(!(h2 = (TH2*)arr->FindObject(Form("H%sTrkIn%s%s%d_2D", typName[ityp], chQ[iq], chName[ich], ispec)))) {
1218               AliInfo(Form("Missing H%sTrkIn%s%s%d_2D", typName[ityp], chQ[iq], chName[ich], ispec));
1219               continue;
1220             }
1221             nplot++;
1222             h2->Draw("colz");
1223             PutTrendValue(Form("TrkIn%s%s%d", chQ[iq], chName[ich], ispec), GetMeanStat(h2, -10., ">"));
1224             MakeDetectorPlot(0);
1225           }
1226         }
1227         if(nplot==15) cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1228         else delete cOut;
1229       }
1230     }
1231   }
1232   // track MC systematic
1233   if((arr = (TObjArray*)fProj->At(kMCtrack))) {
1234     for(Int_t iview(0); iview<nTrkViews; iview++){
1235       cOut = new TCanvas(Form("%s_MC%s", GetName(), vTrkName[iview]), "Track Resolution", nx, ny);
1236       cOut->Divide(3,2, 1.e-5, 1.e-5);
1237       Int_t nplot(0);
1238       for(Int_t iplot(0); iplot<6; iplot++){
1239         p=cOut->cd(iplot+1); p->SetRightMargin(0.1572581); p->SetTopMargin(0.08262712);
1240         if(!(h2 = (TH2*)arr->FindObject(Form("HMC%s%d_2D", vTrkName[iview], iplot)))) continue;
1241         h2->Draw("colz"); nplot++;
1242       }
1243       if(nplot==6) cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1244       else delete cOut;
1245     }
1246   }
1247
1248
1249   gStyle->SetPalette(1);
1250 }
1251
1252 //________________________________________________________
1253 void AliTRDresolution::DrawSigma(TH2 *h2, const Char_t *title, Float_t m, Float_t M, Float_t scale)
1254 {
1255   // Draw error bars scaled with "scale" instead of content values
1256   //use range [m,M] if limits are specified
1257
1258   if(!h2) return;
1259   TAxis *ax(h2->GetXaxis()), *ay(h2->GetYaxis());
1260   TH2F *h2e = new TH2F(Form("%s_E", h2->GetName()),
1261                 Form("%s;%s;%s;%s", h2->GetTitle(), ax->GetTitle(), ay->GetTitle(), title),
1262                 ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
1263                 ay->GetNbins(), ay->GetXmin(), ay->GetXmax());
1264   h2e->SetContour(9);
1265   TAxis *az(h2e->GetZaxis());
1266   if(M>m) az->SetRangeUser(m, M);
1267   az->CenterTitle();
1268   az->SetTitleOffset(1.5);
1269   for(Int_t ix(1); ix<=h2->GetNbinsX(); ix++){
1270     for(Int_t iy(1); iy<=h2->GetNbinsY(); iy++){
1271       if(h2->GetBinContent(ix, iy)<-100.) continue;
1272       Float_t v(scale*h2->GetBinError(ix, iy));
1273       if(M>m && v<m) v=m+TMath::Abs((M-m)*1.e-3);
1274       h2e->SetBinContent(ix, iy, v);
1275     }
1276   }
1277   h2e->Draw("colz");
1278 }
1279
1280 //________________________________________________________
1281 void AliTRDresolution::GetRange(TH2 *h2, Char_t mod, Float_t *range)
1282 {
1283 // Returns the range of the bulk of data in histogram h2. Removes outliers.
1284 // The "range" vector should be initialized with 2 elements
1285 // Option "mod" can be any of
1286 //   - 0 : gaussian like distribution
1287 //   - 1 : tailed distribution
1288
1289   Int_t nx(h2->GetNbinsX())
1290       , ny(h2->GetNbinsY())
1291       , n(nx*ny);
1292   Double_t *data=new Double_t[n];
1293   for(Int_t ix(1), in(0); ix<=nx; ix++){
1294     for(Int_t iy(1); iy<=ny; iy++)
1295       data[in++] = h2->GetBinContent(ix, iy);
1296   }
1297   Double_t mean, sigm;
1298   AliMathBase::EvaluateUni(n, data, mean, sigm, Int_t(n*.8));
1299
1300   range[0]=mean-3.*sigm; range[1]=mean+3.*sigm;
1301   if(mod==1) range[0]=TMath::Max(Float_t(1.e-3), range[0]);
1302   AliDebug(2, Form("h[%s] range0[%f %f]", h2->GetName(), range[0], range[1]));
1303   TH1S h1("h1SF0", "", 100, range[0], range[1]);
1304   h1.FillN(n,data,0);
1305   delete [] data;
1306
1307   switch(mod){
1308   case 0:// gaussian distribution
1309   {
1310     TF1 fg("fg", "gaus", mean-3.*sigm, mean+3.*sigm);
1311     h1.Fit(&fg, "QN");
1312     mean=fg.GetParameter(1); sigm=fg.GetParameter(2);
1313     range[0] = mean-2.5*sigm;range[1] = mean+2.5*sigm;
1314     AliDebug(2, Form("     rangeG[%f %f]", range[0], range[1]));
1315     break;
1316   }
1317   case 1:// tailed distribution
1318   {
1319     Int_t bmax(h1.GetMaximumBin());
1320     Int_t jBinMin(1), jBinMax(100);
1321     for(Int_t ibin(bmax); ibin--;){
1322       if(h1.GetBinContent(ibin)<1.){
1323         jBinMin=ibin; break;
1324       }
1325     }
1326     for(Int_t ibin(bmax); ibin++;){
1327       if(h1.GetBinContent(ibin)<1.){
1328         jBinMax=ibin; break;
1329       }
1330     }
1331     range[0]=h1.GetBinCenter(jBinMin); range[1]=h1.GetBinCenter(jBinMax);
1332     AliDebug(2, Form("     rangeT[%f %f]", range[0], range[1]));
1333     break;
1334   }
1335   }
1336
1337   return;
1338 }
1339
1340 //________________________________________________________
1341 Bool_t AliTRDresolution::MakeProjectionDetector()
1342 {
1343 // Analyse cluster
1344   const Int_t kNcontours(9);
1345   const Int_t kNstat(100);
1346   if(fProj && fProj->At(kDetector)) return kTRUE;
1347   if(!fContainer){
1348     AliError("Missing data container.");
1349     return kFALSE;
1350   }
1351   THnSparse *H(NULL);
1352   if(!(H = (THnSparse*)fContainer->FindObject("hDet2Cluster"))){
1353     AliInfo(Form("Missing/Wrong data @ hDet2Cluster."));
1354     return kTRUE;
1355   }
1356   Int_t ndim(H->GetNdimensions());
1357   Int_t coord[kNdim]; memset(coord, 0, sizeof(Int_t) * kNdim); Double_t v = 0.;
1358   TAxis *aa[kNdim], *an(NULL); memset(aa, 0, sizeof(TAxis*) * kNdim);
1359   for(Int_t id(0); id<ndim; id++) aa[id] = H->GetAxis(id);
1360   if(ndim < 5) aa[4] = new TAxis(1, -0.5, 0.5);
1361   Int_t nPad(1);
1362   if(ndim > 5){
1363     an = H->GetAxis(5);
1364     nPad = kNpads+1;
1365   }
1366   // build list of projections
1367   const Int_t nsel(8*AliTRDgeometry::kNlayer*AliTRDeventInfo::kCentralityClasses);
1368   // define rebinning strategy
1369   const Int_t nEtaPhi(4); Int_t rebinEtaPhiX[nEtaPhi] = {1, 2, 2, 1}, rebinEtaPhiY[nEtaPhi] = {2, 1, 1, 5};
1370   //const Char_t *cenName[AliTRDeventInfo::kCentralityClasses] = {"0-10%", "10-20%", "20-50%", "50-80%", "80-100%"};
1371   const Char_t *cenName[AliTRDeventInfo::kCentralityClasses] = {"2800-inf", "2100-2799", "1400-2099", "700-1399", "0-699"};
1372   AliTRDrecoProjection hp[kDetNproj];  TObjArray php(kDetNproj);
1373   Int_t ih(0), isel(-1), np[nsel]; memset(np, 0, nsel*sizeof(Int_t));
1374   for(Int_t ipad(0); ipad<nPad; ipad++){
1375     for(Int_t icen(0); icen<AliTRDeventInfo::kCentralityClasses; icen++){
1376       for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1377         isel++; // new selection
1378         hp[ih].Build(Form("HDet%d%d%d", ily, icen, ipad),
1379                     Form("Detectors :: Ly[%d] Cen[%s] Pads[%s]", ily, cenName[icen], ipad?(ipad<kNpads?Form("%d", ipad+1):Form(">%d", kNpads)):"deconv"),
1380                     kEta, kPhi, 4, aa);
1381         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1382         hp[ih].SetShowRange(10., 55.);
1383         php.AddLast(&hp[ih++]); np[isel]++;
1384       }
1385     }
1386   }
1387   AliInfo(Form("Build %3d 3D projections.", ih));
1388
1389   Int_t ly(0), cen(0), npad(0);
1390   for (Long64_t ib(0); ib < H->GetNbins(); ib++) {
1391     v = H->GetBinContent(ib, coord); if(v<1.) continue;
1392     ly = coord[kBC]-1;    // layer selection
1393     cen = coord[kYrez]-1; // centrality selection
1394     npad = 0;             // no. of pads selection
1395     if(an) npad = TMath::Min(coord[5]-1, Int_t(kNpads));
1396     isel = npad*AliTRDeventInfo::kCentralityClasses*AliTRDgeometry::kNlayer+cen*AliTRDgeometry::kNlayer+ly;
1397     ((AliTRDrecoProjection*)php.At(isel))->Increment(coord, v);
1398     //Int_t ioff=isel;for(Int_t jh(0); jh<np[isel]; jh++) ((AliTRDrecoProjection*)php.At(ioff+jh))->Increment(coord, v);
1399   }
1400   TObjArray *arr(NULL);
1401   fProj->AddAt(arr = new TObjArray(kDetNproj), kDetector);
1402
1403   TH2 *h2(NULL);  Int_t jh(0);
1404   for(; ih--; ){
1405     if(!hp[ih].H()) continue;
1406     if(!(h2 = hp[ih].Projection2D(kNstat, kNcontours, 0, kFALSE))) continue;
1407     arr->AddAt(h2, jh++);
1408     if(!(h2 = (TH2*)gDirectory->Get(Form("%sEn", hp[ih].H()->GetName())))) continue;
1409     arr->AddAt(h2, jh++);
1410   }
1411   AliTRDrecoProjection *pr0(NULL), *pr1(NULL);
1412   for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1413     for(Int_t icen(0); icen<AliTRDeventInfo::kCentralityClasses; icen++){
1414       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HDet%d%d%d", ily, icen, 0)))){
1415         for(Int_t ipad(1); ipad<nPad; ipad++){
1416           if((pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HDet%d%d%d", ily, icen, ipad)))){
1417             (*pr0)+=(*pr1);
1418           }
1419         }
1420         pr0->H()->SetNameTitle(Form("HDet%d%d", ily, icen), Form("Detectors :: Ly[%d] Cen[%s]", ily, cenName[icen]));
1421         if((h2 = pr0->Projection2D(kNstat, kNcontours, 0, kFALSE))) arr->AddAt(h2, jh++);
1422         if((h2 = (TH2*)gDirectory->Get(Form("%sEn", pr0->H()->GetName())))) arr->AddAt(h2, jh++);
1423         if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HDet%d%d%d", ily, 0, 0)))) (*pr1)+=(*pr0);
1424       }
1425     }
1426     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HDet%d%d%d", ily, 0, 0)))){
1427       pr0->H()->SetNameTitle(Form("HDet%d", ily), Form("Detectors :: Ly[%d]", ily));
1428       if((h2 = pr0->Projection2D(kNstat, kNcontours))) arr->AddAt(h2, jh++);
1429     }
1430   }
1431   AliInfo(Form("Done %3d 2D projections.", jh));
1432   return kTRUE;
1433 }
1434
1435 //________________________________________________________
1436 Bool_t AliTRDresolution::MakeProjectionCluster(Bool_t mc)
1437 {
1438 // Analyse cluster
1439   const Int_t kNcontours(9);
1440   const Int_t kNstat(100);
1441   Int_t cidx=mc?kMCcluster:kCluster;
1442   if(fProj && fProj->At(cidx)) return kTRUE;
1443   if(!fContainer){
1444     AliError("Missing data container.");
1445     return kFALSE;
1446   }
1447   const Char_t *projName[] = {"hCluster2Track", "hCluster2MC"};
1448   THnSparse *H(NULL);
1449   if(!(H = (THnSparse*)fContainer->FindObject(projName[Int_t(mc)]))){
1450     AliError(Form("Missing/Wrong data @ %s.", projName[Int_t(mc)]));
1451     return kFALSE;
1452   }
1453   Int_t ndim(H->GetNdimensions()); Bool_t debug(ndim>Int_t(kNdimCl));
1454   Int_t coord[10]; memset(coord, 0, sizeof(Int_t) * 10); Double_t v = 0.;
1455   TAxis *aa[kNdim], *as(NULL), *apt(NULL), *acen(NULL), *anp(NULL); memset(aa, 0, sizeof(TAxis*) * kNdim);
1456   for(Int_t id(0); id<ndim; id++) aa[id] = H->GetAxis(id);
1457   if(ndim > Int_t(kPt)) apt = H->GetAxis(kPt);
1458   if(ndim > Int_t(kSpeciesChgRC)) as  = H->GetAxis(kSpeciesChgRC);
1459   if(ndim > Int_t(kNdim)) acen  = H->GetAxis(kNdim);
1460   if(ndim > Int_t(kNdim)+1) anp  = H->GetAxis(kNdim+1);
1461   // calculate size depending on debug level
1462   const Int_t nCh(apt?2:1);
1463   const Int_t nCen(acen?Int_t(AliTRDeventInfo::kCentralityClasses):1);
1464   const Int_t nNpad(anp?(Int_t(kNpads)+1):1);
1465   
1466   // build list of projections
1467   const Int_t nsel(AliTRDgeometry::kNlayer*kNcharge*(kNpads+1)*AliTRDeventInfo::kCentralityClasses);
1468   // define rebinning strategy
1469   const Int_t nEtaPhi(4); Int_t rebinEtaPhiX[nEtaPhi] = {1, 2, 5, 1}, rebinEtaPhiY[nEtaPhi] = {2, 1, 1, 5};
1470   AliTRDrecoProjection hp[kClNproj];  TObjArray php(kClNproj);
1471   const Char_t chName[kNcharge] = {'n', 'p'};const Char_t chSgn[kNcharge] = {'-', '+'};
1472   const Char_t *cenName[AliTRDeventInfo::kCentralityClasses] = {"2800-inf", "2100-2799", "1400-2099", "700-1399", "0-699"};
1473   Int_t ih(0), isel(-1), np[nsel]; memset(np, 0, nsel*sizeof(Int_t));
1474   for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1475     for(Int_t ich(0); ich<nCh; ich++){
1476       for(Int_t icen(0); icen<nCen; icen++){
1477         for(Int_t ipad(0); ipad<nNpad; ipad++){
1478           isel++; // new selection
1479           hp[ih].Build(Form("H%sClY%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, ipad),
1480                       Form("Clusters[%c] :: #Deltay Ly[%d] Cen[%s] Pads[%s]", chSgn[ich], ily, cenName[icen], ipad?(ipad<kNpads?Form("%d", ipad+1):Form(">%d", kNpads)):"deconv"),
1481                       kEta, kPhi, kYrez, aa);
1482           hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1483           php.AddLast(&hp[ih++]); np[isel]++;
1484           if(!debug) break;
1485           hp[ih].Build(Form("H%sClQ%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, ipad),
1486                       Form("Clusters[%c] :: Q Ly[%d] Cen[%s] Pads[%s]", chSgn[ich], ily, cenName[icen], ipad?(ipad<kNpads?Form("%d", ipad+1):Form(">%d", kNpads)):"deconv"),
1487                       kEta, kPhi, kSpeciesChgRC, aa);
1488           hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1489           hp[ih].SetShowRange(24., 33.);
1490           php.AddLast(&hp[ih++]); np[isel]++;
1491           hp[ih].Build(Form("H%sClYXTC%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, ipad),
1492                       Form("Clusters[%c] :: #Deltay(x,TC) Ly[%d] Cen[%s] Pads[%s]", chSgn[ich], ily, cenName[icen], ipad?(ipad<kNpads?Form("%d", ipad+1):Form(">%d", kNpads)):"deconv"),
1493                       kPrez, kZrez, kYrez, aa);
1494           php.AddLast(&hp[ih++]); np[isel]++;
1495           hp[ih].Build(Form("H%sClYXPh%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, ipad),
1496                         Form("Clusters[%c] :: #Deltay(x,#Phi) Ly[%d] Cen[%s] Pads[%s]", chSgn[ich], ily, cenName[icen], ipad?(ipad<kNpads?Form("%d", ipad+1):Form(">%d", kNpads)):"deconv"),
1497                         kPrez, kPt, kYrez, aa);
1498           php.AddLast(&hp[ih++]); np[isel]++;
1499         }
1500       }
1501     }
1502   }
1503   AliInfo(Form("Build %3d 3D projections.", ih));
1504
1505   AliTRDrecoProjection *pr0(NULL), *pr1(NULL);
1506   Int_t ly(0), ch(0), rcBin(as?as->FindBin(0.):-1), chBin(apt?apt->FindBin(0.):-1), ioff(0), cen(0), npad(0);
1507   for (Long64_t ib(0); ib < H->GetNbins(); ib++) {
1508     v = H->GetBinContent(ib, coord); if(v<1.) continue;
1509     ly = coord[kBC]-1;
1510     // RC selection
1511     if(rcBin>0 && coord[kSpeciesChgRC] == rcBin) continue;
1512
1513     // charge selection
1514     ch = 0; // [-] track
1515     if(chBin>0 && coord[kPt] > chBin) ch = 1;  // [+] track
1516     cen = 0; // centrality selection
1517     if(acen) cen = coord[kNdim]-1;
1518     npad = 0;             // no. of pads selection
1519     if(anp) npad = TMath::Min(coord[kNdim+1]-1, Int_t(kNpads));
1520
1521     if(debug){
1522       isel = ly*nCh*nCen*nNpad
1523             +ch*nCen*nNpad
1524             +cen*nNpad
1525             +npad;
1526       ioff=isel*4;
1527     } else {
1528       isel = ly; ioff = isel;
1529     }
1530     if(ioff>=ih){
1531       AliError(Form("Wrong selection %d [%3d]", ioff, ih));
1532       return kFALSE;
1533     }
1534     if(!(pr0=(AliTRDrecoProjection*)php.At(ioff))) {
1535       AliError(Form("Missing projection %d", ioff));
1536       return kFALSE;
1537     }
1538     if(strcmp(pr0->H()->GetName(), Form("H%sClY%c%d%d%d", mc?"MC":"", chName[ch], ly, cen, npad))!=0){
1539       AliError(Form("Projection mismatch :: request[H%sClY%c%d%d%d] found[%s]", mc?"MC":"", chName[ch], ly, cen, npad, pr0->H()->GetName()));
1540       return kFALSE;
1541     }
1542     for(Int_t jh(0); jh<np[isel]; jh++) ((AliTRDrecoProjection*)php.At(ioff+jh))->Increment(coord, v);
1543   }
1544   if(HasDump3DFor(kCluster)){
1545     TDirectory *cwd = gDirectory;
1546     TFile::Open(Form("ResDump_%s.root", H->GetName()), "RECREATE");
1547     for(Int_t ip(0); ip<php.GetEntriesFast(); ip++){
1548       if(!(pr0 = (AliTRDrecoProjection*)php.At(ip))) continue;
1549       if(!pr0->H()) continue;
1550       TH3 *h3=(TH3*)pr0->H()->Clone();
1551       h3->Write();
1552     }
1553     gFile->Close();
1554     cwd->cd();
1555   }
1556
1557   TObjArray *arr(NULL);
1558   fProj->AddAt(arr = new TObjArray(kClNproj), cidx);
1559
1560   TH2 *h2(NULL);  Int_t jh(0);
1561   for(; ih--; ){
1562     if(!hp[ih].H()) continue;
1563     if(strchr(hp[ih].H()->GetName(), 'Q')){
1564       if(!(h2 = hp[ih].Projection2D(kNstat, kNcontours, 0, kFALSE))) continue;
1565       arr->AddAt(h2, jh++);
1566       if(!(h2 = (TH2*)gDirectory->Get(Form("%sEn", hp[ih].H()->GetName())))) continue;
1567       arr->AddAt(h2, jh++);
1568     } else {
1569       if((h2 = hp[ih].Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1570     }
1571   }
1572   for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1573     for(Int_t ich(0); ich<nCh; ich++){
1574       for(Int_t icen(0); icen<nCen; icen++){
1575         /*!dy*/
1576         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClY%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, 0)))){
1577           for(Int_t ipad(1); ipad<nNpad; ipad++){
1578             if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClY%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, ipad)))) continue;
1579             (*pr0)+=(*pr1);
1580           }
1581           pr0->H()->SetNameTitle(Form("H%sClY%c%d%d", mc?"MC":"", chName[ich], ily, icen), Form("Clusters[%c] :: #Deltay Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1582           if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1583           if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClY%c%d%d%d", mc?"MC":"", chName[ich], ily, 0, 0)))) (*pr1)+=(*pr0);
1584         }
1585         /*!Q*/
1586         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClQ%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, 0)))){
1587           for(Int_t ipad(1); ipad<nNpad; ipad++){
1588             if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClQ%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, ipad)))) continue;
1589             (*pr0)+=(*pr1);
1590           }
1591           pr0->H()->SetNameTitle(Form("H%sClQ%c%d%d", mc?"MC":"", chName[ich], ily, icen), Form("Clusters[%c] :: Q Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1592           if((h2 = pr0->Projection2D(kNstat, kNcontours, 2, kFALSE))) arr->AddAt(h2, jh++);
1593           if((h2 = (TH2*)gDirectory->Get(Form("%sEn", pr0->H()->GetName())))) arr->AddAt(h2, jh++);
1594           pr0->H()->SetName(Form("H%sClQS%c%d%d", mc?"MC":"", chName[ich], ily, icen));
1595           if((h2 = pr0->Projection2D(kNstat, kNcontours, 0))) arr->AddAt(h2, jh++);
1596           if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClQ%c%d%d%d", mc?"MC":"", chName[ich], ily, 0, 0)))) (*pr1)+=(*pr0);
1597         }
1598         /*!YXTC*/
1599         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXTC%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, 0)))){
1600           for(Int_t ipad(1); ipad<nNpad; ipad++){
1601             if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXTC%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, ipad)))) continue;
1602             (*pr0)+=(*pr1);
1603           }
1604           pr0->H()->SetNameTitle(Form("H%sClYXTC%c%d%d", mc?"MC":"", chName[ich], ily, icen), Form("Clusters[%c] :: #Deltay(x,TC) Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1605           if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1606           if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXTC%c%d%d%d", mc?"MC":"", chName[ich], ily, 0, 0)))) (*pr1)+=(*pr0);
1607         }
1608         /*!YXPh*/
1609         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXPh%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, 0)))){
1610           for(Int_t ipad(1); ipad<nNpad; ipad++){
1611             if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXPh%c%d%d%d", mc?"MC":"", chName[ich], ily, icen, ipad)))) continue;
1612             (*pr0)+=(*pr1);
1613           }
1614           pr0->H()->SetNameTitle(Form("H%sClYXPh%c%d%d", mc?"MC":"", chName[ich], ily, icen), Form("Clusters[%c] :: #Deltay(x,#Phi) Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1615           if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1616           if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXPh%c%d%d%d", mc?"MC":"", chName[ich], ily, 0, 0)))) (*pr1)+=(*pr0);
1617         }
1618       } // end centrality integration
1619       /*!dy*/
1620       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClY%c%d%d%d", mc?"MC":"", chName[ich], ily, 0, 0)))){
1621         pr0->H()->SetNameTitle(Form("H%sClY%c%d", mc?"MC":"", chName[ich], ily),
1622                               Form("Clusters[%c]:: #Deltay Ly[%d]", chSgn[ich], ily));
1623         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1624         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClY%c%d%d%d", mc?"MC":"", chName[0], ily, 0, 0)))) (*pr1)+=(*pr0);
1625       }
1626       /*!Q*/
1627       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClQ%c%d%d%d", mc?"MC":"", chName[ich], ily, 0, 0)))){
1628         pr0->H()->SetNameTitle(Form("H%sClQ%c%d", mc?"MC":"", chName[ich], ily),
1629                               Form("Clusters[%c]:: Q Ly[%d]", chSgn[ich], ily));
1630         if((h2 = pr0->Projection2D(kNstat, kNcontours, 2))) arr->AddAt(h2, jh++);
1631         pr0->H()->SetName(Form("H%sClQS%c%d", mc?"MC":"", chName[ich], ily));
1632         if((h2 = pr0->Projection2D(kNstat, kNcontours, 0))) arr->AddAt(h2, jh++);
1633         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClQ%c%d%d%d", mc?"MC":"", chName[0], ily, 0, 0)))) (*pr1)+=(*pr0);
1634       }
1635       /*!YXTC*/
1636       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXTC%c%d%d%d", mc?"MC":"", chName[ich], ily, 0, 0)))){
1637         pr0->H()->SetNameTitle(Form("H%sClYXTC%c%d", mc?"MC":"", chName[ich], ily),
1638                               Form("Clusters[%c]:: #Deltay(x,TC) Ly[%d]", chSgn[ich], ily));
1639         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1640         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXTC%c%d%d%d", mc?"MC":"", chName[0], ily, 0, 0)))) (*pr1)+=(*pr0);
1641       }
1642       /*!YXPh*/
1643       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXPh%c%d%d%d", mc?"MC":"", chName[ich], ily, 0, 0)))){
1644         pr0->H()->SetNameTitle(Form("H%sClYXPh%c%d", mc?"MC":"", chName[ich], ily),
1645                               Form("Clusters[%c]:: #Deltay(x,#Phi) Ly[%d]", chSgn[ich], ily));
1646         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1647         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXPh%c%d%d%d", mc?"MC":"", chName[0], ily, 0, 0)))) (*pr1)+=(*pr0);
1648       }
1649     } // end charge integration
1650     /*!dy*/
1651     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClY%c%d%d%d", mc?"MC":"", chName[0], ily, 0, 0)))){
1652       pr0->H()->SetNameTitle(Form("H%sClY%d", mc?"MC":"", ily), Form("Clusters :: #Deltay Ly[%d]", ily));
1653       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1654     }
1655     /*!YXPh*/
1656     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sClYXPh%c%d%d%d", mc?"MC":"", chName[0], ily, 0, 0)))){
1657       pr0->H()->SetNameTitle(Form("H%sClYXPh%d", mc?"MC":"", ily), Form("Clusters :: #Deltay Ly[%d]", ily));
1658       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1659     }
1660
1661   }
1662   AliInfo(Form("Done %3d 2D projections.", jh));
1663   return kTRUE;
1664 }
1665
1666 //________________________________________________________
1667 Bool_t AliTRDresolution::MakeProjectionTracklet(Bool_t mc)
1668 {
1669 // Analyse tracklet
1670   const Int_t kNcontours(9);
1671   const Int_t kNstat(30);
1672   const Int_t kNstatQ(30);
1673   Int_t cidx=mc?kMCtracklet:kTracklet;
1674   if(fProj && fProj->At(cidx)) return kTRUE;
1675   if(!fContainer){
1676     AliError("Missing data container.");
1677     return kFALSE;
1678   }
1679   const Char_t *projName[] = {"hTracklet2Track", "hTracklet2MC"};
1680   THnSparse *H(NULL);
1681   if(!(H = (THnSparse*)fContainer->FindObject(projName[Int_t(mc)]))){
1682     AliError(Form("Missing/Wrong data @ %s.", projName[Int_t(mc)]));
1683     return kFALSE;
1684   }
1685   const Int_t mdim(kNdim+8);
1686   Int_t ndim(H->GetNdimensions()); Bool_t debug(ndim>Int_t(kNdimTrklt));
1687   Int_t coord[mdim]; memset(coord, 0, sizeof(Int_t) * mdim); Double_t v = 0.;
1688   TAxis *aa[mdim], *as(NULL), *ap(NULL), *ac(NULL); memset(aa, 0, sizeof(TAxis*) * mdim);
1689   for(Int_t id(0); id<ndim; id++) aa[id] = H->GetAxis(id);
1690   if(ndim > Int_t(kSpeciesChgRC)) as = H->GetAxis(kSpeciesChgRC); // init species/charge selection
1691   if(ndim > Int_t(kPt))           ap = H->GetAxis(kPt);           // init pt selection
1692   if(ndim > Int_t(kNdim))         ac = H->GetAxis(kNdim);         // init centrality selection
1693   // calculate size depending on debug level
1694   const Int_t nCen(debug?Int_t(AliTRDeventInfo::kCentralityClasses):1);
1695   const Int_t nPt(debug?Int_t(kNpt+2):1);
1696   const Int_t nSpc(1);//ndim>kNdimTrklt?fgkNbins[kSpeciesChgRC]:1);
1697   const Int_t nCh(debug?Int_t(kNcharge):1);
1698
1699   // build list of projections
1700   const Int_t nsel(AliTRDeventInfo::kCentralityClasses*AliTRDgeometry::kNlayer*(kNpt+2)*(AliPID::kSPECIES*kNcharge + 1));
1701   // define rebinning strategy
1702   const Int_t nEtaPhi(4); Int_t rebinEtaPhiX[nEtaPhi] = {1, 2, 5, 1}, rebinEtaPhiY[nEtaPhi] = {2, 1, 1, 5};
1703   AliTRDrecoProjection hp[kTrkltNproj]; TObjArray php(kTrkltNproj);
1704   Int_t ih(0), isel(-1), np[nsel]; memset(np, 0, nsel*sizeof(Int_t));
1705   const Char_t chName[kNcharge] = {'n', 'p'};const Char_t chSgn[kNcharge] = {'-', '+'};
1706   const Char_t ptName[kNpt+2] = {'L', 'l', 'i', 'h', 'H'};
1707   const Char_t *ptCut[kNpt+2] = {"p_{t}[GeV/c]<0.5", "0.5<=p_{t}[GeV/c]<0.8", "0.8<=p_{t}[GeV/c]<1.5", "1.5<=p_{t}[GeV/c]<5.0", "p_{t}[GeV/c]>=5.0"};
1708 //  const Char_t *cenName[AliTRDeventInfo::kCentralityClasses] = {"0-10%", "10-20%", "20-50%", "50-80%", "80-100%"};
1709   const Char_t *cenName[AliTRDeventInfo::kCentralityClasses] = {"2800-inf", "2100-2799", "1400-2099", "700-1399", "0-699"};
1710   for(Int_t icen(0); icen<nCen; icen++){
1711     for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1712       for(Int_t ipt(0); ipt<nPt; ipt++){
1713         for(Int_t isp(0); isp<nSpc; isp++){
1714           for(Int_t ich(0); ich<nCh; ich++){
1715             isel++; // new selection
1716             hp[ih].Build(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], isp, ily, icen),
1717                         Form("Tracklets[%s%c]:: #Deltay{%s} Ly[%d] Cen[%s]", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt], ily, cenName[icen]),
1718                         kEta, kPhi, kYrez, aa);
1719             //hp[ih].SetShowRange(-0.1,0.1);
1720             hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1721             php.AddLast(&hp[ih++]); np[isel]++;
1722             hp[ih].Build(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], isp, ily, icen),
1723                         Form("Tracklets[%s%c]:: #Delta#phi{%s} Ly[%d] Cen[%s]", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt], ily, cenName[icen]),
1724                         kEta, kPhi, kPrez, aa);
1725             //hp[ih].SetShowRange(-0.5,0.5);
1726             hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1727             php.AddLast(&hp[ih++]); np[isel]++;
1728             hp[ih].Build(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], isp, ily, icen),
1729                         Form("Tracklets[%s%c]:: dQdl{%s} Ly[%d] Cen[%s]", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt], ily, cenName[icen]),
1730                         kEta, kPhi, kZrez, aa);
1731             hp[ih].SetShowRange(1.,2.3);
1732             hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1733             php.AddLast(&hp[ih++]); np[isel]++;
1734             hp[ih].Build(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], isp, ily, icen),
1735                         Form("Tracklets[%s%c]:: OccupancyTB{%s} Ly[%d] Cen[%s]", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt], ily, cenName[icen]),
1736                         kEta, kPhi, kNdim+1, aa);
1737             hp[ih].SetShowRange(30., 70.);
1738             hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1739             php.AddLast(&hp[ih++]); np[isel]++;
1740           }
1741         }
1742         if(ndim==kNdimTrklt) continue;
1743
1744         isel++; // new selection
1745         hp[ih].Build(Form("H%sTrkltRCZ%c%d%d", mc?"MC":"", ptName[ipt], ily, icen),
1746                     Form("Tracklets[RC]:: #Deltaz{%s} Ly[%d] Cen[%s]", ptCut[ipt], ily, cenName[icen]),
1747                     kEta, kPhi, kZrez, aa);
1748   //      hp[ih].SetShowRange(-0.1,0.1);
1749         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1750         php.AddLast(&hp[ih++]); np[isel]++;
1751 /*        hp[ih].Build(Form("H%sTrkltRCY%c%d%d", mc?"MC":"", ptName[ipt], ily, icen),
1752                     Form("Tracklets[RC]:: #Deltay{%s} Ly[%d] Cen[%s]", ptCut[ipt], ily, cenName[icen]),
1753                     kEta, kPhi, kYrez, aa);
1754         //hp[ih].SetShowRange(-0.1,0.1);
1755         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1756         php.AddLast(&hp[ih++]); np[isel]++;
1757         hp[ih].Build(Form("H%sTrkltRCPh%c%d%d", mc?"MC":"", ptName[ipt], ily, icen),
1758                     Form("Tracklets[RC]:: #Delta#phi{%s} Ly[%d] Cen[%s]", ptCut[ipt], ily, cenName[icen]),
1759                     kEta, kPhi, kPrez, aa);
1760         //hp[ih].SetShowRange(-0.1,0.1);
1761         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1762         php.AddLast(&hp[ih++]); np[isel]++;
1763         hp[ih].Build(Form("H%sTrkltRCQ%c%d%d", mc?"MC":"", ptName[ipt], ily, icen),
1764                     Form("Tracklets[RC]:: dQdl{%s} Ly[%d] Cen[%s]", ptCut[ipt], ily, cenName[icen]),
1765                     kEta, kPhi, kNdim, aa);
1766         //hp[ih].SetShowRange(-0.1,0.1);
1767         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1768         php.AddLast(&hp[ih++]); np[isel]++;*/
1769       }
1770     }
1771   }
1772   AliInfo(Form("Build %3d 3D projections.", ih));
1773
1774   AliTRDrecoProjection *pr0(NULL), *pr1(NULL);
1775   Int_t ly(0), ch(0), sp(2), rcBin(as?as->FindBin(0.):-1), pt(0), cen(0), ioff(0), jspc(nSpc*nCh+1), kspc(nSpc*nCh*4+1);
1776   for (Long64_t ib(0); ib < H->GetNbins(); ib++) {
1777     v = H->GetBinContent(ib, coord);
1778     if(v<1.) continue;
1779     ly = coord[kBC]-1; // layer selection
1780     // charge selection
1781     ch = 0; sp=0;// [e-] track [dafault]
1782     if(rcBin>0){ // debug mode in which species/charge are also saved
1783       sp = Int_t(TMath::Abs(as->GetBinCenter(coord[kSpeciesChgRC])))-1;
1784       if(coord[kSpeciesChgRC] > rcBin) ch = 1;  // [+] track
1785       else if(coord[kSpeciesChgRC] == rcBin) ch = 2;  // [RC] track
1786     }
1787     // pt selection
1788     pt = 0; // low pt
1789     if(ap) pt = TMath::Min(coord[kPt], Int_t(kNpt)+1);
1790     // centrality selection
1791     cen = 0; // default
1792     if(ac) cen = coord[kNdim]-1;
1793     // global selection
1794     if(ndim==kNdimTrklt){
1795       ioff = ly*4;
1796       isel = ly;
1797     } else {
1798       isel = cen*AliTRDgeometry::kNlayer*nPt*jspc+ly*nPt*jspc+pt*jspc; isel+=sp<0?(nSpc*nCh):ch;
1799       ioff = cen*AliTRDgeometry::kNlayer*nPt*kspc+ly*nPt*kspc+pt*kspc; ioff+=sp<0?((nSpc*nCh)*4):(ch*4);
1800     }
1801     if(ioff>=ih){
1802       AliError(Form("Wrong selection %d [%3d]", ioff, ih));
1803       return kFALSE;
1804     }
1805     if(!(pr0=(AliTRDrecoProjection*)php.At(ioff))) {
1806       AliError(Form("Missing projection %d", ioff));
1807       return kFALSE;
1808     }
1809     if(sp>=0){
1810       if(strcmp(pr0->H()->GetName(), Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[ch], ptName[pt], sp, ly, cen))!=0){
1811         AliError(Form("Projection mismatch :: request[H%sTrkltY%c%c%d%d%d] found[%s]", mc?"MC":"", chName[ch], ptName[pt], sp, ly, cen, pr0->H()->GetName()));
1812         return kFALSE;
1813       }
1814     } else {
1815       if(strcmp(pr0->H()->GetName(), Form("H%sTrkltRCZ%c%d%d", mc?"MC":"", ptName[pt], ly, cen))!=0){
1816         AliError(Form("Projection mismatch :: request[H%sTrkltRCZ%c%d%d] found[%s]", mc?"MC":"", ptName[pt], ly, cen, pr0->H()->GetName()));
1817         return kFALSE;
1818       }
1819     }
1820     for(Int_t jh(0); jh<np[isel]; jh++) ((AliTRDrecoProjection*)php.At(ioff+jh))->Increment(coord, v);
1821   }
1822   if(HasDump3DFor(kTracklet)){
1823     TDirectory *cwd = gDirectory;
1824     TFile::Open(Form("ResDump_%s.root", H->GetName()), "RECREATE");
1825     for(Int_t ip(0); ip<php.GetEntriesFast(); ip++){
1826       if(!(pr0 = (AliTRDrecoProjection*)php.At(ip))) continue;
1827       if(!pr0->H()) continue;
1828       TH3 *h3=(TH3*)pr0->H()->Clone();
1829       h3->Write();
1830     }
1831     gFile->Close();
1832     cwd->cd();
1833   }
1834
1835   TObjArray *arr(NULL);
1836   fProj->AddAt(arr = new TObjArray(kTrkltNproj), cidx);
1837
1838   TH2 *h2(NULL); Int_t jh(0);
1839   for(; ih--; ){
1840     if(!hp[ih].H()) continue;
1841     Int_t mid(0), nstat(kNstat);
1842     if(strchr(hp[ih].H()->GetName(), 'Q')){ mid=2; nstat=kNstatQ;}
1843     if(!(h2 = hp[ih].Projection2D(nstat, kNcontours, mid))) continue;
1844     arr->AddAt(h2, jh++);
1845   }
1846   // build combined performance plots
1847   for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1848     for(Int_t ich(0); ich<nCh; ich++){
1849       for(Int_t icen(0); icen<nCen; icen++){
1850         for(Int_t ipt(0); ipt<nPt; ipt++){
1851           /*!dy*/
1852           if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], 0, ily, icen)))){
1853             for(Int_t isp(1); isp<nSpc; isp++){
1854               if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], isp, ily, icen)))) continue;
1855               (*pr0)+=(*pr1);
1856             }
1857             pr0->H()->SetNameTitle(Form("H%sTrkltY%c%c%d%d", mc?"MC":"", chName[ich], ptName[ipt], ily, icen),
1858                                       Form("Tracklets[%c]:: #Deltay{%s} Ly[%d] Cen[%s]", chSgn[ich], ptCut[ipt], ily, cenName[icen]));
1859             if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1860             if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, icen)))) (*pr1)+=(*pr0);
1861           }
1862           /*!dphi*/
1863           if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], 0, ily, icen)))){
1864             for(Int_t isp(1); isp<nSpc; isp++){
1865               if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], isp, ily, icen)))) continue;
1866               (*pr0)+=(*pr1);
1867             }
1868             pr0->H()->SetNameTitle(Form("H%sTrkltPh%c%c%d%d", mc?"MC":"", chName[ich], ptName[ipt], ily, icen),
1869                                       Form("Tracklets[%c]:: #Delta#phi{%s} Ly[%d] Cen[%s]", chSgn[ich], ptCut[ipt], ily, cenName[icen]));
1870             if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1871             if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, icen)))) (*pr1)+=(*pr0);
1872           }
1873           /*!dQ/dl*/
1874           if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], 0, ily, icen)))){
1875             for(Int_t isp(1); isp<nSpc; isp++){
1876               if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], isp, ily, icen)))) continue;
1877               (*pr0)+=(*pr1);
1878             }
1879             pr0->H()->SetNameTitle(Form("H%sTrkltQ%c%c%d%d", mc?"MC":"", chName[ich], ptName[ipt], ily, icen),
1880                                       Form("Tracklets[%c]:: dQdl{%s} Ly[%d] Cen[%s]", chSgn[ich], ptCut[ipt], ily, cenName[icen]));
1881             if((h2 = pr0->Projection2D(kNstatQ, kNcontours, 2))) arr->AddAt(h2, jh++);
1882             pr0->H()->SetNameTitle(Form("H%sTrkltQS%c%c%d%d", mc?"MC":"", chName[ich], ptName[ipt], ily, icen),
1883                                       Form("Tracklets[%c]:: dQdl{%s} Ly[%d] Cen[%s]", chSgn[ich], ptCut[ipt], ily, cenName[icen]));
1884             pr0->SetShowRange(2.4, 5.1);
1885             if((h2 = pr0->Projection2D(kNstat, kNcontours, 0))) arr->AddAt(h2, jh++);
1886             if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, icen)))) (*pr1)+=(*pr0);
1887           }
1888           /*!TB occupancy*/
1889           if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], 0, ily, icen)))){
1890             for(Int_t isp(1); isp<nSpc; isp++){
1891               if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[ipt], isp, ily, icen)))) continue;
1892               (*pr0)+=(*pr1);
1893             }
1894             pr0->H()->SetNameTitle(Form("H%sTrkltTB%c%c%d%d", mc?"MC":"", chName[ich], ptName[ipt], ily, icen),
1895                                       Form("Tracklets[%c]:: OccupancyTB{%s} Ly[%d] Cen[%s]", chSgn[ich], ptCut[ipt], ily, cenName[icen]));
1896             if((h2 = pr0->Projection2D(kNstat, kNcontours))) arr->AddAt(h2, jh++);
1897             if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, icen)))) (*pr1)+=(*pr0);
1898           }
1899         } // end pt integration
1900         /*!dy*/
1901         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, icen)))){
1902           pr0->H()->SetNameTitle(Form("H%sTrkltY%c%d%d", mc?"MC":"", chName[ich], ily, icen),
1903                                 Form("Tracklets[%c]:: #Deltay Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1904           if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1905           if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, 0)))) (*pr1)+=(*pr0);
1906         }
1907         /*!dphi*/
1908         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, icen)))){
1909           pr0->H()->SetNameTitle(Form("H%sTrkltPh%c%d%d", mc?"MC":"", chName[ich], ily, icen),
1910                                 Form("Tracklets[%c]:: #Delta#phi Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1911           if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1912           if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, 0)))) (*pr1)+=(*pr0);
1913         }
1914         /*!dQ/dl*/
1915         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, icen)))){
1916           pr0->H()->SetNameTitle(Form("H%sTrkltQ%c%d%d", mc?"MC":"", chName[ich], ily, icen),
1917                                 Form("Tracklets[%c]:: dQdl Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1918           pr0->SetShowRange(1.,2.3);
1919           if((h2 = pr0->Projection2D(kNstatQ, kNcontours, 2))) arr->AddAt(h2, jh++);
1920           pr0->H()->SetNameTitle(Form("H%sTrkltQS%c%d%d", mc?"MC":"", chName[ich], ily, icen),
1921                                 Form("Tracklets[%c]:: dQdl Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1922           pr0->SetShowRange(2.4,5.1);
1923           if((h2 = pr0->Projection2D(kNstat, kNcontours, 0))) arr->AddAt(h2, jh++);
1924           if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, 0)))) (*pr1)+=(*pr0);
1925         }
1926         /*!TB occupancy*/
1927         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, icen)))){
1928           pr0->H()->SetNameTitle(Form("H%sTrkltTB%c%d%d", mc?"MC":"", chName[ich], ily, icen),
1929                                 Form("Tracklets[%c]:: OccupancyTB Ly[%d] Cen[%s]", chSgn[ich], ily, cenName[icen]));
1930           if((h2 = pr0->Projection2D(kNstat, kNcontours))) arr->AddAt(h2, jh++);
1931           if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, 0)))) (*pr1)+=(*pr0);
1932         }
1933       } // end centrality integration
1934       /*!dy*/
1935       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, 0)))){
1936         pr0->H()->SetNameTitle(Form("H%sTrkltY%c%d", mc?"MC":"", chName[ich], ily), Form("Tracklets[%c] :: #Deltay Ly[%d]", chSgn[ich], ily));
1937         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1938         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[0], ptName[0], 0, ily, 0)))) (*pr1)+=(*pr0);
1939       }
1940       /*!dphi*/
1941       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, 0)))){
1942         pr0->H()->SetNameTitle(Form("H%sTrkltPh%c%d", mc?"MC":"", chName[ich], ily), Form("Tracklets[%c] :: #Delta#phi Ly[%d]", chSgn[ich], ily));
1943         pr0->SetShowRange(-.9,.9);
1944         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1945         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[0], ptName[0], 0, ily, 0)))) (*pr1)+=(*pr0);
1946       }
1947       /*!dQ/dl*/
1948       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, 0)))){
1949         pr0->H()->SetNameTitle(Form("H%sTrkltQ%c%d", mc?"MC":"", chName[ich], ily), Form("Tracklets[%c] :: dQdl Ly[%d]", chSgn[ich], ily));
1950         pr0->SetShowRange(1.,2.3);
1951         if((h2 = pr0->Projection2D(kNstatQ, kNcontours, 2))) arr->AddAt(h2, jh++);
1952         pr0->H()->SetNameTitle(Form("H%sTrkltQS%c%d", mc?"MC":"", chName[ich], ily), Form("Tracklets[%c] :: dQdl Ly[%d]", chSgn[ich], ily));
1953         pr0->SetShowRange(2.4,5.1);
1954         if((h2 = pr0->Projection2D(kNstat, kNcontours, 0))) arr->AddAt(h2, jh++);
1955         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[0], ptName[0], 0, ily, 0)))) (*pr1)+=(*pr0);
1956       }
1957       /*!TB occupancy*/
1958       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[ich], ptName[0], 0, ily, 0)))){
1959         pr0->H()->SetNameTitle(Form("H%sTrkltTB%c%d", mc?"MC":"", chName[ich], ily), Form("Tracklets[%c] :: OccupancyTB Ly[%d]", chSgn[ich], ily));
1960         if((h2 = pr0->Projection2D(kNstat, kNcontours))) arr->AddAt(h2, jh++);
1961         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[0], ptName[0], 0, ily, 0)))) (*pr1)+=(*pr0);
1962       }
1963     } // end charge integration
1964     /*!dy*/
1965     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltY%c%c%d%d%d", mc?"MC":"", chName[0], ptName[0], 0, ily, 0)))){
1966       pr0->H()->SetNameTitle(Form("H%sTrkltY%d", mc?"MC":"", ily), Form("Tracklets :: #Deltay Ly[%d]", ily));
1967       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1968     }
1969     /*!dphi*/
1970     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltPh%c%c%d%d%d", mc?"MC":"", chName[0], ptName[0], 0, ily, 0)))){
1971       pr0->H()->SetNameTitle(Form("H%sTrkltPh%d", mc?"MC":"", ily), Form("Tracklets :: #Delta#phi Ly[%d]", ily));
1972       pr0->SetShowRange(-.45,.45);
1973       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
1974     }
1975     /*!dQdl*/
1976     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltQ%c%c%d%d%d", mc?"MC":"", chName[0], ptName[0], 0, ily, 0)))){
1977       pr0->H()->SetNameTitle(Form("H%sTrkltQ%d", mc?"MC":"", ily), Form("Tracklets :: dQdl Ly[%d]", ily));
1978       pr0->SetShowRange(1.,2.3);
1979       if((h2 = pr0->Projection2D(kNstat, kNcontours, 2))) arr->AddAt(h2, jh++);
1980       pr0->H()->SetName(Form("H%sTrkltQS%d", mc?"MC":"", ily));
1981       pr0->SetShowRange(2.4,5.1);
1982       if((h2 = pr0->Projection2D(kNstat, kNcontours, 0))) arr->AddAt(h2, jh++);
1983     }
1984     /*!TB occupancy*/
1985     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltTB%c%c%d%d%d", mc?"MC":"", chName[0], ptName[0], 0, ily, 0)))){
1986       pr0->H()->SetNameTitle(Form("H%sTrkltTB%d", mc?"MC":"", ily), Form("Tracklets :: OccupancyTB Ly[%d]", ily));
1987       if((h2 = pr0->Projection2D(kNstat, kNcontours))) arr->AddAt(h2, jh++);
1988     }
1989
1990     /*! Row Cross processing*/
1991     for(Int_t icen(0); icen<nCen; icen++){
1992       /*!RC dz*/
1993       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltRCZ%c%d%d", mc?"MC":"", ptName[0], ily, icen)))){
1994         for(Int_t ipt(0); ipt<kNpt; ipt++){
1995           if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltRCZ%c%d%d", mc?"MC":"", ptName[ipt], ily, icen)))) continue;
1996           (*pr0)+=(*pr1);
1997         }
1998         pr0->H()->SetNameTitle(Form("H%sTrkltRCZ%d%d", mc?"MC":"", ily, icen), Form("Tracklets[RC]:: #Deltaz Ly[%d] Cen[%s]", ily, cenName[icen]));
1999         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2000         if(icen && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltRCZ%c%d%d", mc?"MC":"", ptName[0], ily, 0)))) (*pr1)+=(*pr0);
2001       }
2002     } // end centrality integration for row cross
2003     /*!RC dz*/
2004     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkltRCZ%c%d%d", mc?"MC":"", ptName[0], ily, 0)))){
2005       pr0->H()->SetNameTitle(Form("H%sTrkltRCZ%d", mc?"MC":"", ily), Form("Tracklets[RC] :: #Deltaz Ly[%d]", ily));
2006       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2007     }
2008   } // end layer loop
2009   AliInfo(Form("Done %3d 2D projections.", jh));
2010   return kTRUE;
2011 }
2012
2013 //________________________________________________________
2014 Bool_t AliTRDresolution::MakeProjectionTrackIn(Bool_t mc)
2015 {
2016 // Analyse track in
2017   const Int_t kNcontours(9);
2018   const Int_t kNstat(30);
2019   Int_t cidx=mc?kMCtrackIn:kTrackIn;
2020   if(fProj && fProj->At(cidx)) return kTRUE;
2021   if(!fContainer){
2022     AliError("Missing data container.");
2023     return kFALSE;
2024   }
2025   const Char_t *projName[] = {"hTracklet2TRDin", "hTRDin2MC"};
2026   THnSparse *H(NULL);
2027   if(!(H = (THnSparse*)fContainer->FindObject(projName[Int_t(mc)]))){
2028     AliError(Form("Missing/Wrong data @ %s.", projName[Int_t(mc)]));
2029     return kFALSE;
2030   }
2031
2032   const Int_t mdim(kNdim+3);
2033   Int_t coord[mdim]; memset(coord, 0, sizeof(Int_t) * mdim); Double_t v = 0.;
2034   Int_t ndim(H->GetNdimensions());
2035   TAxis *aa[mdim], *as(NULL), *ap(NULL), *ax(NULL), *abf(NULL); memset(aa, 0, sizeof(TAxis*) * (mdim));
2036   for(Int_t id(0); id<ndim; id++) aa[id] = H->GetAxis(id);
2037   if(ndim > Int_t(kSpeciesChgRC)) as = H->GetAxis(kSpeciesChgRC);
2038   if(ndim > Int_t(kPt))           ap = H->GetAxis(kPt);
2039   if(ndim > Int_t(kNdim)+1)       ax = H->GetAxis(kNdim+1);
2040   if(ndim > Int_t(kNdim)+2)      abf = H->GetAxis(kNdim+2);
2041   //AliInfo(Form("Using : Species[%c] Pt[%c] BunchFill[%c]", as?'y':'n', ap?'y':'n', abf?'y':'n'));
2042   const Int_t nPt(ndim>Int_t(kNdimTrkIn)?Int_t(kNpt+2):1);
2043
2044   // build list of projections
2045   const Int_t nsel((kNpt+2)*(AliPID::kSPECIES*kNcharge + 1));
2046   const Char_t chName[kNcharge] = {'n', 'p'};const Char_t chSgn[kNcharge] = {'-', '+'};
2047   const Char_t ptName[kNpt+2] = {'L', 'l', 'i', 'h', 'H'};
2048   const Char_t *ptCut[kNpt+2] = {"p_{t}[GeV/c]<0.5", "0.5<=p_{t}[GeV/c]<0.8", "0.8<=p_{t}[GeV/c]<1.5", "1.5<=p_{t}[GeV/c]<5.0", "p_{t}[GeV/c]>=5.0"};
2049   // define rebinning strategy
2050   const Int_t nEtaPhi(4); Int_t rebinEtaPhiX[nEtaPhi] = {1, 2, 5, 1}, rebinEtaPhiY[nEtaPhi] = {2, 1, 1, 5};
2051   AliTRDrecoProjection hp[kMCTrkInNproj]; TObjArray php(kMCTrkInNproj+2);
2052   Int_t ih(0), isel(-1), np[nsel]; memset(np, 0, nsel*sizeof(Int_t));
2053   // define list of projections
2054   for(Int_t ipt(0); ipt<nPt; ipt++){
2055     for(Int_t isp(0); isp<AliPID::kSPECIES; isp++){
2056       for(Int_t ich(0); ich<kNcharge; ich++){
2057         isel++; // new selection
2058         hp[ih].Build(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp),
2059                      Form("TrackIn[%s%c]:: #Deltay{%s}", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt]),
2060                      kEta, kPhi, kYrez, aa);
2061         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2062         php.AddLast(&hp[ih++]); np[isel]++;
2063         hp[ih].Build(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp),
2064                      Form("TrackIn[%s%c]:: #Delta#phi{%s}", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt]),
2065                      kEta, kPhi, kPrez, aa);
2066         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2067         php.AddLast(&hp[ih++]); np[isel]++;
2068         hp[ih].Build(Form("H%sTrkInQ%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp),
2069                      Form("TrackIn[%s%c]:: dQdl {%s}", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt]),
2070                      kEta, kPhi, kZrez, aa);
2071         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2072         php.AddLast(&hp[ih++]); np[isel]++;
2073         if(!ax) continue;
2074         hp[ih].Build(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp),
2075                      Form("TrackIn[%s%c]:: #Deltax{%s}", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt]),
2076                      kEta, kPhi, kNdim+1, aa);
2077         hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2078         php.AddLast(&hp[ih++]); np[isel]++;
2079       }
2080     }
2081     isel++; // RC tracks
2082     hp[ih].Build(Form("H%sTrkInRCZ%c", mc?"MC":"", ptName[ipt]),
2083                   Form("TrackIn[RC]:: #Deltaz{%s}", ptCut[ipt]),
2084                   kEta, kPhi, kZrez, aa);
2085     hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2086     php.AddLast(&hp[ih++]); np[isel]++;
2087     hp[ih].Build(Form("H%sTrkInRCY%c", mc?"MC":"", ptName[ipt]),
2088                   Form("TrackIn[RC]:: #Deltay{%s}", ptCut[ipt]),
2089                   kEta, kPhi, kYrez, aa);
2090     hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2091     php.AddLast(&hp[ih++]); np[isel]++;
2092     hp[ih].Build(Form("H%sTrkInRCPh%c", mc?"MC":"", ptName[ipt]),
2093                   Form("TrackIn[RC]:: #Delta#phi{%s}", ptCut[ipt]),
2094                   kEta, kPhi, kPrez, aa);
2095     hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2096     php.AddLast(&hp[ih++]); np[isel]++;
2097     if(!ax) continue;
2098     hp[ih].Build(Form("H%sTrkInRCX%c", mc?"MC":"", ptName[ipt]),
2099                   Form("TrackIn[RC]:: #Deltax{%s}", ptCut[ipt]),
2100                   kEta, kPhi, kNdim+1, aa);
2101     hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2102     php.AddLast(&hp[ih++]); np[isel]++;
2103   }
2104   AliInfo(Form("Build %3d 3D projections.", ih));
2105
2106   // fill projections
2107   Int_t ch(0), pt(0), sp(1), rcBin(as?as->FindBin(0.):-1), ioff(0);
2108   AliTRDrecoProjection *pr0(NULL), *pr1(NULL);
2109   for (Long64_t ib(0); ib < H->GetNbins(); ib++) {
2110     v = H->GetBinContent(ib, coord);
2111     if(v<1.) continue;
2112     if(fBCbinTOF>0 && coord[kBC]!=fBCbinTOF) continue; // TOF bunch cross cut
2113     if(fBCbinFill>0 && abf && coord[kNdim+2]!=fBCbinTOF) continue; // Fill bunch cut
2114     // charge selection
2115     ch = 0; sp=1;// [-] track
2116     if(rcBin>0){ // debug mode in which species are also saved
2117       sp = Int_t(TMath::Abs(as->GetBinCenter(coord[kSpeciesChgRC])))-1;
2118       if(sp>=AliPID::kSPECIES){
2119         AliDebug(2, Form("Wrong SpeciesIndex[%d]. Rescale", sp));
2120         sp = AliPID::kSPECIES-1;
2121       }
2122       if(coord[kSpeciesChgRC] > rcBin) ch = 1;  // [+] track
2123       else if(coord[kSpeciesChgRC] == rcBin) ch = 2;  // [RC] track
2124     }
2125     // pt selection
2126     pt = 0; // low pt
2127     if(ap) pt = TMath::Min(coord[kPt], Int_t(kNpt)+1);
2128     // global selection
2129     isel = pt*(AliPID::kSPECIES*kNcharge+1); isel+=sp<0?(AliPID::kSPECIES*kNcharge):(sp*kNcharge+ch);
2130     ioff = isel*(ax?4:3);
2131     if(ioff>=ih){
2132       AliError(Form("Wrong selection %d [%3d]", ioff, ih));
2133       return kFALSE;
2134     }
2135     if(!(pr0=(AliTRDrecoProjection*)php.At(ioff))) {
2136       AliError(Form("Missing projection %d", ioff));
2137       return kFALSE;
2138     }
2139     if(sp>=0 && ch<2){
2140       if(strcmp(pr0->H()->GetName(), Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ch], ptName[pt], sp))!=0){
2141         AliError(Form("Projection mismatch :: request[H%sTrkInY%c%c%d] found[%s]", mc?"MC":"", chName[ch], ptName[pt], sp, pr0->H()->GetName()));
2142         return kFALSE;
2143       }
2144     } else {
2145       if(strcmp(pr0->H()->GetName(), Form("H%sTrkInRCZ%c", mc?"MC":"", ptName[pt]))!=0){
2146         AliError(Form("Projection mismatch :: request[H%sTrkltRCZ%c] found[%s]", mc?"MC":"", ptName[pt], pr0->H()->GetName()));
2147         return kFALSE;
2148       }
2149     }
2150     for(Int_t jh(0); jh<np[isel]; jh++) ((AliTRDrecoProjection*)php.At(ioff+jh))->Increment(coord, v);
2151   }
2152   if(HasDump3DFor(kTrackIn)){
2153     TDirectory *cwd = gDirectory;
2154     TFile::Open(Form("ResDump_%s.root", H->GetName()), "RECREATE");
2155     for(Int_t ip(0); ip<php.GetEntriesFast(); ip++){
2156       if(!(pr0 = (AliTRDrecoProjection*)php.At(ip))) continue;
2157       if(!pr0->H()) continue;
2158       TH3 *h3=(TH3*)pr0->H()->Clone();
2159       h3->Write();
2160     }
2161     gFile->Close();
2162     cwd->cd();
2163   }
2164
2165   TObjArray *arr(NULL);
2166   fProj->AddAt(arr = new TObjArray(mc?kMCTrkInNproj:kTrkInNproj), cidx);
2167
2168   TH2 *h2(NULL); Int_t jh(0);
2169   for(; ih--; ){
2170     if(!hp[ih].H()) continue;
2171     if(!(h2 = hp[ih].Projection2D(kNstat, kNcontours))) continue;
2172     arr->AddAt(h2, jh++);
2173   }
2174   // build combined performance plots
2175   // combine up the tree of projections
2176   AliTRDrecoProjection xlow[2], specY[kNcharge*AliPID::kSPECIES], specPh[kNcharge*AliPID::kSPECIES], specQ[kNcharge*AliPID::kSPECIES];
2177   for(Int_t ich(0); ich<kNcharge; ich++){
2178     // PID dependency - summation over pt
2179     for(Int_t isp(0); isp<AliPID::kSPECIES; isp++){
2180       /*!dy*/
2181       Int_t idx(ich*AliPID::kSPECIES+isp);
2182       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ich], ptName[0], isp)))){
2183         specY[idx] = (*pr0);
2184         specY[idx].SetNameTitle(Form("H%sTrkInY%c%d", mc?"MC":"", chName[ich], isp), "Sum over pt");
2185         specY[idx].H()->SetNameTitle(Form("H%sTrkInY%c%d", mc?"MC":"", chName[ich], isp),
2186                               Form("TrackIn[%s%c]:: #Deltay", AliPID::ParticleLatexName(isp), chSgn[ich]));
2187         for(Int_t ipt(1); ipt<nPt; ipt++){
2188           if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp)))) continue;
2189           specY[idx]+=(*pr1);
2190         }
2191         php.AddLast(&specY[idx]);
2192         if((h2 = specY[idx].Projection2D(kNstat, kNcontours, 1, kFALSE))) arr->AddAt(h2, jh++);
2193         if((h2 = (TH2*)gDirectory->Get(Form("%sEn", specY[idx].H()->GetName())))) arr->AddAt(h2, jh++);
2194         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%d", mc?"MC":"", chName[0], isp)))) (*pr1)+=specY[idx];
2195       }
2196       /*!dphi*/
2197       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[ich], ptName[0], isp)))){
2198         specPh[idx] = (*pr0);
2199         specPh[idx].SetNameTitle(Form("H%sTrkInPh%c%d", mc?"MC":"", chName[ich], isp), "Sum over pt");
2200         specPh[idx].H()->SetNameTitle(Form("H%sTrkInPh%c%d", mc?"MC":"", chName[ich], isp),
2201                               Form("TrackIn[%s%c]:: #Delta#phi", AliPID::ParticleLatexName(isp), chSgn[ich]));
2202         specPh[idx].SetShowRange(-1.5, 1.5);
2203         for(Int_t ipt(1); ipt<nPt; ipt++){
2204           if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp)))) continue;
2205           specPh[idx]+=(*pr1);
2206         }
2207         php.AddLast(&specPh[idx]);
2208         if((h2 = specPh[idx].Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2209         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%d", mc?"MC":"", chName[0], isp)))) (*pr1)+=specPh[idx];
2210       }
2211       /*!dQdl*/
2212       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInQ%c%c%d", mc?"MC":"", chName[ich], ptName[0], isp)))){
2213         specQ[idx] = (*pr0);
2214         specQ[idx].SetNameTitle(Form("H%sTrkInQ%c%d", mc?"MC":"", chName[ich], isp), "Sum over pt");
2215         specQ[idx].H()->SetNameTitle(Form("H%sTrkInQ%c%d", mc?"MC":"", chName[ich], isp),
2216                               Form("TrackIn[%s%c]:: dQdl", AliPID::ParticleLatexName(isp), chSgn[ich]));
2217         specQ[idx].SetShowRange(-2.2, -1.75);
2218         specQ[idx].H()->GetZaxis()->SetTitle("dQdl [a.u.]");
2219         for(Int_t ipt(1); ipt<nPt; ipt++){
2220           if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInQ%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp)))) continue;
2221           specQ[idx]+=(*pr1);
2222         }
2223         php.AddLast(&specQ[idx]);
2224         if((h2 = specQ[idx].Projection2D(kNstat, kNcontours, 2))) arr->AddAt(h2, jh++);
2225         specQ[idx].H()->SetName(Form("H%sTrkInQS%c%d", mc?"MC":"", chName[ich], isp));
2226         specQ[idx].SetShowRange(-1.85, -1.4);
2227         if((h2 = specQ[idx].Projection2D(kNstat, kNcontours, 0))) arr->AddAt(h2, jh++);
2228         if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInQ%c%d", mc?"MC":"", chName[0], isp)))) (*pr1)+=specQ[idx];
2229       }
2230     } // end PID loop for pt integration
2231
2232     // pt dependency - summation over PID
2233     for(Int_t ipt(0); ipt<nPt; ipt++){
2234       /*!dy*/
2235       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], 0)))){
2236         for(Int_t isp(1); isp<AliPID::kSPECIES; isp++){
2237           if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp)))) continue;
2238           (*pr0)+=(*pr1);
2239         }
2240         pr0->H()->SetNameTitle(Form("H%sTrkInY%c%c", mc?"MC":"", chName[ich], ptName[ipt]),
2241                                   Form("TrackIn[%c]:: #Deltay{%s}", chSgn[ich], ptCut[ipt]));
2242         pr0->SetShowRange(-0.3, 0.3);
2243         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2244         if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ich], ptName[0], 0)))) (*pr1)+=(*pr0);
2245       }
2246       /*!dphi*/
2247       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], 0)))){
2248         for(Int_t isp(1); isp<AliPID::kSPECIES; isp++){
2249           if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp)))) continue;
2250           (*pr0)+=(*pr1);
2251         }
2252         pr0->H()->SetNameTitle(Form("H%sTrkInPh%c%c", mc?"MC":"", chName[ich], ptName[ipt]),
2253                                   Form("TrackIn[%c]:: #Delta#phi{%s}", chSgn[ich], ptCut[ipt]));
2254         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2255         if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[ich], ptName[0], 0)))) (*pr1)+=(*pr0);
2256       }
2257       /*!dx*/
2258       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], 0)))){
2259         for(Int_t isp(1); isp<AliPID::kSPECIES; isp++){
2260           if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[ich], ptName[ipt], isp)))) continue;
2261           (*pr0)+=(*pr1);
2262         }
2263         pr0->H()->SetNameTitle(Form("H%sTrkInX%c%c", mc?"MC":"", chName[ich], ptName[ipt]),
2264                                   Form("TrackIn[%c]:: #Deltax{%s}", chSgn[ich], ptCut[ipt]));
2265         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2266         if(!ipt){
2267           xlow[ich] = (*pr0);
2268           xlow[ich].SetNameTitle(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[ich], ptName[0], 5),
2269                                  Form("TrackIn[%c]:: #Deltax{%s}", chSgn[ich], ptCut[0]));
2270           php.AddLast(&xlow[ich]);
2271         }
2272         if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[ich], ptName[0], 0)))) (*pr1)+=(*pr0);
2273       }
2274     } // end pt loop for PID integration
2275
2276     /*!dy*/
2277     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ich], ptName[0], 0)))){
2278       pr0->H()->SetNameTitle(Form("H%sTrkInY%c", mc?"MC":"", chName[ich]),
2279                             Form("TrackIn[%c]:: #Deltay", chSgn[ich]));
2280       pr0->SetShowRange(-0.3, 0.3);
2281       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1, kFALSE))) arr->AddAt(h2, jh++);
2282       if((h2 = (TH2*)gDirectory->Get(Form("%sEn", pr0->H()->GetName())))) arr->AddAt(h2, jh++);
2283       if(ich && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[0], ptName[0], 0)))) (*pr1)+=(*pr0);
2284     }
2285     /*!dy high pt*/
2286     if(ich && (pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[0], ptName[3], 0)))){
2287       if((pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[ich], ptName[3], 0)))){
2288         (*pr0)+=(*pr1);
2289         pr0->H()->SetNameTitle(Form("H%sTrkInY%c", mc?"MC":"", ptName[3]), Form("TrackIn :: #Deltay{%s}", ptCut[3]));
2290         pr0->SetShowRange(-0.3, 0.3);
2291         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2292       }
2293     }
2294     /*!dphi*/
2295     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[ich], ptName[0], 0)))){
2296       pr0->H()->SetNameTitle(Form("H%sTrkInPh%c", mc?"MC":"", chName[ich]),
2297                             Form("TrackIn[%c]:: #Delta#phi", chSgn[ich]));
2298       pr0->SetShowRange(-1., 1.);
2299       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2300       if(ich==1 && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[0], ptName[0], 0)))) (*pr1)+=(*pr0);
2301     }
2302     /*!dx*/
2303     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[ich], ptName[0], 0)))){
2304       pr0->H()->SetNameTitle(Form("H%sTrkInX%c", mc?"MC":"", chName[ich]),
2305                             Form("TrackIn[%c]:: #Deltax", chSgn[ich]));
2306       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2307       if(ich==1 && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[0], ptName[0], 0)))) (*pr1)+=(*pr0);
2308     }
2309     /*!dx low pt*/
2310     if(ich && (pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[0], ptName[1], 5)))){
2311       if((pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[ich], ptName[1], 5)))){
2312         (*pr0)+=(*pr1);
2313         pr0->H()->SetNameTitle(Form("H%sTrkInX%c", mc?"MC":"", ptName[1]), Form("TrackIn :: #Deltax{%s}", ptCut[1]));
2314         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2315       }
2316     }
2317   } // end charge loop
2318
2319   for(Int_t isp(0); isp<AliPID::kSPECIES; isp++){
2320     /*!dy*/
2321     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%d", mc?"MC":"", chName[0], isp)))){
2322       pr0->H()->SetNameTitle(Form("H%sTrkInY%d", mc?"MC":"", isp), Form("TrackIn[%s] :: #Deltay", AliPID::ParticleLatexName(isp)));
2323       pr0->SetShowRange(-0.3, 0.3);
2324       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1, kFALSE))) arr->AddAt(h2, jh++);
2325       if((h2 = (TH2*)gDirectory->Get(Form("%sEn", pr0->H()->GetName())))) arr->AddAt(h2, jh++);
2326     }
2327     /*!dphi*/
2328     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%d", mc?"MC":"", chName[0], isp)))){
2329       pr0->H()->SetNameTitle(Form("H%sTrkInPh%d", mc?"MC":"", isp), Form("TrackIn[%s] :: #Delta#phi", AliPID::ParticleLatexName(isp)));
2330       pr0->SetShowRange(-1., 1.);
2331       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2332     }
2333     /*!dQdl*/
2334     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInQ%c%d", mc?"MC":"", chName[0], isp)))){
2335       pr0->H()->SetNameTitle(Form("H%sTrkInQ%d", mc?"MC":"", isp), Form("TrackIn[%s] :: dQdl", AliPID::ParticleLatexName(isp)));
2336       pr0->SetShowRange(-2.2, -1.75);
2337       if((h2 = pr0->Projection2D(kNstat, kNcontours, 2))) arr->AddAt(h2, jh++);
2338       pr0->H()->SetName(Form("H%sTrkInQS%d", mc?"MC":"", isp));
2339       pr0->SetShowRange(-1.85, -1.4);
2340       if((h2 = pr0->Projection2D(kNstat, kNcontours, 0))) arr->AddAt(h2, jh++);
2341     }
2342   } // end PID processing
2343
2344   /*!dy*/
2345   if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInY%c%c%d", mc?"MC":"", chName[0], ptName[0], 0)))){
2346     pr0->H()->SetNameTitle(Form("H%sTrkInY", mc?"MC":""), "TrackIn :: #Deltay");
2347     pr0->SetShowRange(-0.3, 0.3);
2348     if((h2 = pr0->Projection2D(kNstat, kNcontours, 1, kFALSE))) arr->AddAt(h2, jh++);
2349     if((h2 = (TH2*)gDirectory->Get(Form("%sEn", pr0->H()->GetName())))) arr->AddAt(h2, jh++);
2350   }
2351   /*!dphi*/
2352   if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInPh%c%c%d", mc?"MC":"", chName[0], ptName[0], 0)))){
2353     pr0->H()->SetNameTitle(Form("H%sTrkInPh", mc?"MC":""), "TrackIn :: #Delta#phi");
2354     if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2355   }
2356   /*!dx*/
2357   if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInX%c%c%d", mc?"MC":"", chName[0], ptName[0], 0)))){
2358     pr0->H()->SetNameTitle(Form("H%sTrkInX", mc?"MC":""), "TrackIn :: #Deltax");
2359     if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2360   }
2361
2362   // Row Cross processing
2363   /*!RC dz*/
2364   if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInRCZ%c", mc?"MC":"", ptName[0])))){
2365     for(Int_t ipt(0); ipt<kNpt; ipt++){
2366       if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInRCZ%c", mc?"MC":"", ptName[ipt])))) continue;
2367       (*pr0)+=(*pr1);
2368     }
2369     pr0->H()->SetNameTitle(Form("H%sTrkInRCZ", mc?"MC":""), "TrackIn[RC]:: #Deltaz");
2370     if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2371   }
2372   /*!RC dy*/
2373   if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInRCY%c", mc?"MC":"", ptName[0])))){
2374     for(Int_t ipt(0); ipt<kNpt; ipt++){
2375       if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInRCY%c", mc?"MC":"", ptName[ipt])))) continue;
2376       (*pr0)+=(*pr1);
2377     }
2378     pr0->H()->SetNameTitle(Form("H%sTrkInRCY", mc?"MC":""), "TrackIn[RC]:: #Deltay");
2379     if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2380   }
2381   /*!RC dphi*/
2382   if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInRCPh%c", mc?"MC":"", ptName[0])))){
2383     for(Int_t ipt(0); ipt<kNpt; ipt++){
2384       if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInRCPh%c", mc?"MC":"", ptName[ipt])))) continue;
2385       (*pr0)+=(*pr1);
2386     }
2387     pr0->H()->SetNameTitle(Form("H%sTrkInRCPh", mc?"MC":""), "TrackIn[RC]:: #Delta#phi");
2388     if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2389   }
2390   /*!RC dx*/
2391   if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInRCX%c", mc?"MC":"", ptName[0])))){
2392     for(Int_t ipt(0); ipt<kNpt; ipt++){
2393       if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("H%sTrkInRCX%c", mc?"MC":"", ptName[ipt])))) continue;
2394       (*pr0)+=(*pr1);
2395     }
2396     pr0->H()->SetNameTitle(Form("H%sTrkInRCX", mc?"MC":""), "TrackIn[RC]:: #Deltax");
2397     if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2398   }
2399   AliInfo(Form("Done %3d 2D projections.", jh));
2400   return kTRUE;
2401 }
2402
2403
2404 //________________________________________________________
2405 Bool_t AliTRDresolution::MakeProjectionTrack()
2406 {
2407 // Analyse tracklet
2408   const Int_t kNcontours(9);
2409   const Int_t kNstat(30);
2410   Int_t cidx(kMCtrack);
2411   if(fProj && fProj->At(cidx)) return kTRUE;
2412   if(!fContainer){
2413     AliError("Missing data container.");
2414     return kFALSE;
2415   }
2416   THnSparse *H(NULL);
2417   if(!(H = (THnSparse*)fContainer->FindObject("hTRD2MC"))){
2418     AliError("Missing/Wrong data @ hTRD2MC.");
2419     return kFALSE;
2420   }
2421   Int_t ndim(H->GetNdimensions());
2422   Int_t coord[kNdim+1]; memset(coord, 0, sizeof(Int_t) * (kNdim+1)); Double_t v = 0.;
2423   TAxis *aa[kNdim+1], *as(NULL), *ap(NULL); memset(aa, 0, sizeof(TAxis*) * (kNdim+1));
2424   for(Int_t id(0); id<ndim; id++) aa[id] = H->GetAxis(id);
2425   if(ndim > kSpeciesChgRC) as = H->GetAxis(kSpeciesChgRC);
2426   if(ndim > kPt) ap = H->GetAxis(kPt);
2427
2428   // build list of projections
2429   const Int_t nsel(AliTRDgeometry::kNlayer*kNpt*AliPID::kSPECIES*7);//, npsel(3);
2430   const Char_t chName[kNcharge] = {'n', 'p'};const Char_t chSgn[kNcharge] = {'-', '+'};
2431   const Char_t ptName[kNpt] = {'l', 'i', 'h'};
2432   const Char_t *ptCut[kNpt] = {"p_{t}[GeV/c]<0.8", "0.8<=p_{t}[GeV/c]<1.5", "p_{t}[GeV/c]>=1.5"};
2433   // define rebinning strategy
2434   const Int_t nEtaPhi(4); Int_t rebinEtaPhiX[nEtaPhi] = {1, 2, 5, 1}, rebinEtaPhiY[nEtaPhi] = {2, 1, 1, 5};
2435   AliTRDrecoProjection hp[kTrkNproj]; TObjArray php(kTrkNproj);
2436   Int_t ih(0), isel(-1), np[nsel]; memset(np, 0, nsel*sizeof(Int_t));
2437   for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
2438     for(Int_t ipt(0); ipt<kNpt; ipt++){
2439       for(Int_t isp(0); isp<AliPID::kSPECIES; isp++){
2440         for(Int_t ich(0); ich<kNcharge; ich++){
2441           isel++; // new selection
2442           hp[ih].Build(Form("HMCTrkY%c%c%d%d", chName[ich], ptName[ipt], isp, ily),
2443                        Form("Tracks[%s%c]:: #Deltay{%s} Ly[%d]", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt], ily),
2444                        kEta, kPhi, kYrez, aa);
2445           hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2446           php.AddLast(&hp[ih++]); np[isel]++;
2447           hp[ih].Build(Form("HMCTrkPh%c%c%d%d", chName[ich], ptName[ipt], isp, ily),
2448                        Form("Tracks[%s%c]:: #Delta#phi{%s} Ly[%d]", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt], ily),
2449                        kEta, kPhi, kPrez, aa);
2450           hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2451           php.AddLast(&hp[ih++]); np[isel]++;
2452           hp[ih].Build(Form("HMCTrkDPt%c%c%d%d", chName[ich], ptName[ipt], isp, ily),
2453                        Form("Tracks[%s%c]:: #Deltap_{t}/p_{t}{%s} Ly[%d]", AliPID::ParticleLatexName(isp), chSgn[ich], ptCut[ipt], ily),
2454                        kEta, kPhi, kNdim, aa);
2455           hp[ih].SetShowRange(0.,10.);
2456           hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2457           php.AddLast(&hp[ih++]); np[isel]++;
2458         }
2459       }
2460       isel++; // new selection
2461       hp[ih].Build(Form("HMCTrkZ%c%d", ptName[ipt], ily),
2462                     Form("Tracks[RC]:: #Deltaz{%s} Ly[%d]", ptCut[ipt], ily),
2463                     kEta, kPhi, kZrez, aa);
2464       hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
2465       php.AddLast(&hp[ih++]); np[isel]++;
2466     }
2467   }
2468
2469   Int_t ly(0), ch(0), pt(0), sp(2), rcBin(as?as->FindBin(0.):-1);
2470   for (Long64_t ib(0); ib < H->GetNbins(); ib++) {
2471     v = H->GetBinContent(ib, coord);
2472     if(v<1.) continue;
2473     ly = coord[kBC]-1; // layer selection
2474     // charge selection
2475     ch=0; sp=2;// [pi-] track [dafault]
2476     if(rcBin>0){ // debug mode in which species are also saved
2477       sp = Int_t(TMath::Abs(as->GetBinCenter(coord[kSpeciesChgRC])))-1;
2478       if(coord[kSpeciesChgRC] > rcBin) ch = 1;        // [+] track
2479       else if(coord[kSpeciesChgRC] == rcBin) ch = 2;  // [RC] track
2480     }
2481     // pt selection
2482     pt = 0; // low pt [default]
2483     if(ap) pt = coord[kPt]-1;
2484     // global selection
2485     Int_t ioff = ly*kNpt*31+pt*31; ioff+=3*(sp<0?10:(sp*kNcharge+ch));
2486     isel = ly*kNpt*11+pt*11; isel+=sp<0?10:(sp*kNcharge+ch);
2487     AliDebug(4, Form("SELECTION[%d] :: ch[%c] pt[%c] sp[%d] ly[%d]\n", np[isel], ch==2?'Z':chName[ch], ptName[pt], sp, ly));
2488     for(Int_t jh(0); jh<np[isel]; jh++) ((AliTRDrecoProjection*)php.At(ioff+jh))->Increment(coord, v);
2489   }
2490   TObjArray *arr(NULL);
2491   fProj->AddAt(arr = new TObjArray(kTrkNproj), cidx);
2492
2493   TH2 *h2(NULL); Int_t jh(0);
2494   for(; ih--; ){
2495     if(!hp[ih].H()) continue;
2496     if(!(h2 = hp[ih].Projection2D(kNstat, kNcontours))) continue;
2497     arr->AddAt(h2, jh++);
2498   }
2499
2500   // combine up the tree of projections
2501   AliTRDrecoProjection *pr0(NULL), *pr1(NULL);
2502   //Int_t iproj(0), jproj(0);
2503   for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
2504     for(Int_t ich(0); ich<kNcharge; ich++){
2505       for(Int_t ipt(0); ipt<kNpt; ipt++){
2506         /*!dy*/
2507         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkY%c%c%d%d", chName[ich], ptName[ipt], 0, ily)))){
2508           for(Int_t isp(1); isp<AliPID::kSPECIES; isp++){
2509             if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkY%c%c%d%d", chName[ich], ptName[ipt], isp, ily)))) continue;
2510             (*pr0)+=(*pr1);
2511           }
2512           AliDebug(2, Form("Rename %s to HMCTrkY%c%c%d", pr0->H()->GetName(), chName[ich], ptName[ipt], ily));
2513           pr0->H()->SetNameTitle(Form("HMCTrkY%c%c%d", chName[ich], ptName[ipt], ily),
2514                                     Form("Tracks[%c]:: #Deltay{%s} Ly[%d]", chSgn[ich], ptCut[ipt], ily));
2515           if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2516           if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkY%c%c%d%d", chName[ich], ptName[0], 0, ily)))) (*pr1)+=(*pr0);
2517         }
2518         /*!dphi*/
2519         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkPh%c%c%d%d", chName[ich], ptName[ipt], 0, ily)))){
2520           for(Int_t isp(1); isp<AliPID::kSPECIES; isp++){
2521             if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkPh%c%c%d%d", chName[ich], ptName[ipt], isp, ily)))) continue;
2522             (*pr0)+=(*pr1);
2523           }
2524           AliDebug(2, Form("Rename %s to HMCTrkPh%c%c%d", pr0->H()->GetName(), chName[ich], ptName[ipt], ily));
2525           pr0->H()->SetNameTitle(Form("HMCTrkPh%c%c%d", chName[ich], ptName[ipt], ily),
2526                                     Form("Tracks[%c]:: #Delta#phi{%s} Ly[%d]", chSgn[ich], ptCut[ipt], ily));
2527           if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2528           if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkPh%c%c%d%d", chName[ich], ptName[0], 0, ily)))) (*pr1)+=(*pr0);
2529         }
2530
2531         /*!dpt/pt*/
2532         if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkDPt%c%c%d%d", chName[ich], ptName[ipt], 0, ily)))){
2533           for(Int_t isp(1); isp<AliPID::kSPECIES; isp++){
2534             if(!(pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkDPt%c%c%d%d", chName[ich], ptName[ipt], isp, ily)))) continue;
2535             (*pr0)+=(*pr1);
2536           }
2537           AliDebug(2, Form("Rename %s to HMCTrkDPt%c%c%d", pr0->H()->GetName(), chName[ich], ptName[ipt], ily));
2538           pr0->H()->SetNameTitle(Form("HMCTrkDPt%c%c%d", chName[ich], ptName[ipt], ily),
2539                                     Form("Tracks[%c]:: #Deltap_{t}/p_{t}{%s} Ly[%d]", chSgn[ich], ptCut[ipt], ily));
2540           if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2541           if(ipt && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkDPt%c%c%d%d", chName[ich], ptName[0], 0, ily)))) (*pr1)+=(*pr0);
2542         }
2543       }
2544       /*!dy*/
2545       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkY%c%c%d%d", chName[ich], ptName[0], 0, ily)))){
2546         pr0->H()->SetNameTitle(Form("HMCTrkY%c%d", chName[ich], ily),
2547                               Form("Tracks[%c]:: #Deltay Ly[%d]", chSgn[ich], ily));
2548         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2549         if(ich==1 && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkY%c%c%d%d", chName[0], ptName[0], 0, ily)))) (*pr1)+=(*pr0);
2550       }
2551       /*!dphi*/
2552       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkPh%c%c%d%d", chName[ich], ptName[0], 0, ily)))){
2553         pr0->H()->SetNameTitle(Form("HMCTrkPh%c%d", chName[ich], ily),
2554                               Form("Tracks[%c]:: #Delta#phi Ly[%d]", chSgn[ich], ily));
2555         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2556         if(ich==1 && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkPh%c%c%d%d", chName[0], ptName[0], 0, ily)))) (*pr1)+=(*pr0);
2557       }
2558       /*!dpt/pt*/
2559       if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkDPt%c%c%d%d", chName[ich], ptName[0], 0, ily)))){
2560         pr0->H()->SetNameTitle(Form("HMCTrkDPt%c%d", chName[ich], ily),
2561                               Form("Tracks[%c]:: #Deltap_{t}/p_{t} Ly[%d]", chSgn[ich], ily));
2562         if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2563         if(ich==1 && (pr1 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkDPt%c%c%d%d", chName[0], ptName[0], 0, ily)))) (*pr1)+=(*pr0);
2564       }
2565     }
2566     /*!dy*/
2567     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkY%c%c%d%d", chName[0], ptName[0], 0, ily)))){
2568       pr0->H()->SetNameTitle(Form("HMCTrkY%d", ily), Form("Tracks :: #Deltay Ly[%d]", ily));
2569       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2570     }
2571     /*!dphi*/
2572     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkPh%c%c%d%d", chName[0], ptName[0], 0, ily)))){
2573       pr0->H()->SetNameTitle(Form("HMCTrkPh%d", ily), Form("Tracks :: #Delta#phi Ly[%d]", ily));
2574       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2575     }
2576     /*!dpt/pt*/
2577     if((pr0 = (AliTRDrecoProjection*)php.FindObject(Form("HMCTrkDPt%c%c%d%d", chName[0], ptName[0], 0, ily)))){
2578       pr0->H()->SetNameTitle(Form("HMCTrkDPt%d", ily), Form("Tracks :: #Deltap_{t}/p_{t} Ly[%d]", ily));
2579       if((h2 = pr0->Projection2D(kNstat, kNcontours, 1))) arr->AddAt(h2, jh++);
2580     }
2581   }
2582   AliInfo(Form("Done %3d 2D projections.", jh));
2583   return kTRUE;
2584 }
2585
2586 //________________________________________________________
2587 Bool_t AliTRDresolution::PostProcess()
2588 {
2589 // Fit, Project, Combine, Extract values from the containers filled during execution
2590
2591   if (!fContainer) {
2592     AliError("ERROR: list not available");
2593     return kFALSE;
2594   }
2595   if(!fProj){
2596     AliInfo("Building array of projections ...");
2597     fProj = new TObjArray(kNclasses); fProj->SetOwner(kTRUE);
2598   }
2599
2600   //PROCESS EXPERIMENTAL DISTRIBUTIONS
2601   // Clusters detector
2602   if(HasProcess(kDetector)) if(!MakeProjectionDetector()) return kFALSE;
2603   // Clusters residuals
2604   if(HasProcess(kCluster)) if(!MakeProjectionCluster()) return kFALSE;
2605   fNRefFigures = 3;
2606   // Tracklet residual/pulls
2607   if(HasProcess(kTracklet)) if(!MakeProjectionTracklet()) return kFALSE;
2608   fNRefFigures = 7;
2609   // TRDin residual/pulls
2610   if(HasProcess(kTrackIn)) if(!MakeProjectionTrackIn()) return kFALSE;
2611   fNRefFigures = 11;
2612
2613   if(!HasMCdata()) return kTRUE;
2614   //PROCESS MC RESIDUAL DISTRIBUTIONS
2615
2616   // CLUSTER Y RESOLUTION/PULLS
2617   if(HasProcess(kCluster)) if(!MakeProjectionCluster(kTRUE)) return kFALSE;
2618   fNRefFigures = 17;
2619
2620   // TRACKLET RESOLUTION/PULLS
2621   if(HasProcess(kTracklet)) if(!MakeProjectionTracklet(kTRUE)) return kFALSE;
2622   fNRefFigures = 21;
2623
2624   // TRACK RESOLUTION/PULLS
2625   if(HasProcess(kTracklet)) if(!MakeProjectionTrack()) return kFALSE;
2626   fNRefFigures+=16;
2627
2628   // TRACK TRDin RESOLUTION/PULLS
2629   if(HasProcess(kTrackIn)) if(!MakeProjectionTrackIn(kTRUE)) return kFALSE;
2630   fNRefFigures+=8;
2631
2632   return kTRUE;
2633 }
2634
2635
2636 //________________________________________________________
2637 void AliTRDresolution::Terminate(Option_t *opt)
2638 {
2639   AliTRDrecoTask::Terminate(opt);
2640   if(HasPostProcess()) PostProcess();
2641 }
2642
2643 //________________________________________________________
2644 void AliTRDresolution::AdjustF1(TH1 *h, TF1 *f)
2645 {
2646 // Helper function to avoid duplication of code
2647 // Make first guesses on the fit parameters
2648
2649   // find the intial parameters of the fit !! (thanks George)
2650   Int_t nbinsy = Int_t(.5*h->GetNbinsX());
2651   Double_t sum = 0.;
2652   for(Int_t jbin=nbinsy-4; jbin<=nbinsy+4; jbin++) sum+=h->GetBinContent(jbin); sum/=9.;
2653   f->SetParLimits(0, 0., 3.*sum);
2654   f->SetParameter(0, .9*sum);
2655   Double_t rms = h->GetRMS();
2656   f->SetParLimits(1, -rms, rms);
2657   f->SetParameter(1, h->GetMean());
2658
2659   f->SetParLimits(2, 0., 2.*rms);
2660   f->SetParameter(2, rms);
2661   if(f->GetNpar() <= 4) return;
2662
2663   f->SetParLimits(3, 0., sum);
2664   f->SetParameter(3, .1*sum);
2665
2666   f->SetParLimits(4, -.3, .3);
2667   f->SetParameter(4, 0.);
2668
2669   f->SetParLimits(5, 0., 1.e2);
2670   f->SetParameter(5, 2.e-1);
2671 }
2672
2673 //________________________________________________________
2674 TObjArray* AliTRDresolution::BuildMonitorContainerCluster(const char* name, Bool_t expand, Float_t range)
2675 {
2676 // Build performance histograms for AliTRDcluster.vs TRD track or MC
2677 //  - y reziduals/pulls
2678
2679   TObjArray *arr = new TObjArray(2);
2680   arr->SetName(name); arr->SetOwner();
2681   TH1 *h(NULL); char hname[100], htitle[300];
2682
2683   // tracklet resolution/pull in y direction
2684   snprintf(hname, 100, "%s_%s_Y", GetNameId(), name);
2685   snprintf(htitle, 300, "Y res for \"%s\" @ %s;tg(#phi);#Delta y [cm];%s", GetNameId(), name, "Detector");
2686   Float_t rr = range<0.?fDyRange:range;
2687   if(!(h = (TH3S*)gROOT->FindObject(hname))){
2688     Int_t nybins=50;
2689     if(expand) nybins*=2;
2690     h = new TH3S(hname, htitle,
2691                  48, -.48, .48,            // phi
2692                  60, -rr, rr,              // dy
2693                  nybins, -0.5, nybins-0.5);// segment
2694   } else h->Reset();
2695   arr->AddAt(h, 0);
2696   snprintf(hname, 100, "%s_%s_YZpull", GetNameId(), name);
2697   snprintf(htitle, 300, "YZ pull for \"%s\" @ %s;%s;#Delta y  / #sigma_{y};#Delta z  / #sigma_{z}", GetNameId(), name, "Detector");
2698   if(!(h = (TH3S*)gROOT->FindObject(hname))){
2699     h = new TH3S(hname, htitle, 540, -0.5, 540-0.5, 100, -4.5, 4.5, 100, -4.5, 4.5);
2700   } else h->Reset();
2701   arr->AddAt(h, 1);
2702
2703   return arr;
2704 }
2705
2706 //________________________________________________________
2707 TObjArray* AliTRDresolution::BuildMonitorContainerTracklet(const char* name, Bool_t expand)
2708 {
2709 // Build performance histograms for AliExternalTrackParam.vs TRD tracklet
2710 //  - y reziduals/pulls
2711 //  - z reziduals/pulls
2712 //  - phi reziduals
2713   TObjArray *arr = BuildMonitorContainerCluster(name, expand, 0.05);
2714   arr->Expand(5);
2715   TH1 *h(NULL); char hname[100], htitle[300];
2716
2717   // tracklet resolution/pull in z direction
2718   snprintf(hname, 100, "%s_%s_Z", GetNameId(), name);
2719   snprintf(htitle, 300, "Z res for \"%s\" @ %s;tg(#theta);#Delta z [cm]", GetNameId(), name);
2720   if(!(h = (TH2S*)gROOT->FindObject(hname))){
2721     h = new TH2S(hname, htitle, 50, -1., 1., 100, -.05, .05);
2722   } else h->Reset();
2723   arr->AddAt(h, 2);
2724   snprintf(hname, 100, "%s_%s_Zpull", GetNameId(), name);
2725   snprintf(htitle, 300, "Z pull for \"%s\" @ %s;tg(#theta);#Delta z  / #sigma_{z};row cross", GetNameId(), name);
2726   if(!(h = (TH3S*)gROOT->FindObject(hname))){
2727     h = new TH3S(hname, htitle, 50, -1., 1., 100, -5.5, 5.5, 2, -0.5, 1.5);
2728     h->GetZaxis()->SetBinLabel(1, "no RC");
2729     h->GetZaxis()->SetBinLabel(2, "RC");
2730   } else h->Reset();
2731   arr->AddAt(h, 3);
2732
2733   // tracklet to track phi resolution
2734   snprintf(hname, 100, "%s_%s_PHI", GetNameId(), name);
2735   snprintf(htitle, 300, "#Phi res for \"%s\" @ %s;tg(#phi);#Delta #phi [rad];%s", GetNameId(), name, "Detector");
2736   Int_t nsgms=540;
2737   if(!(h = (TH3S*)gROOT->FindObject(hname))){
2738     h = new TH3S(hname, htitle, 48, -.48, .48, 100, -.5, .5, nsgms, -0.5, nsgms-0.5);
2739   } else h->Reset();
2740   arr->AddAt(h, 4);
2741
2742   return arr;
2743 }
2744
2745 //________________________________________________________
2746 TObjArray* AliTRDresolution::BuildMonitorContainerTrack(const char* name)
2747 {
2748 // Build performance histograms for AliExternalTrackParam.vs MC
2749 //  - y resolution/pulls
2750 //  - z resolution/pulls
2751 //  - phi resolution, snp pulls
2752 //  - theta resolution, tgl pulls
2753 //  - pt resolution, 1/pt pulls, p resolution
2754
2755   TObjArray *arr = BuildMonitorContainerTracklet(name);
2756   arr->Expand(11);
2757   TH1 *h(NULL); char hname[100], htitle[300];
2758   //TAxis *ax(NULL);
2759
2760   // snp pulls
2761   snprintf(hname, 100, "%s_%s_SNPpull", GetNameId(), name);
2762   snprintf(htitle, 300, "SNP pull for \"%s\" @ %s;tg(#phi);#Delta snp  / #sigma_{snp};entries", GetNameId(), name);
2763   if(!(h = (TH2I*)gROOT->FindObject(hname))){
2764     h = new TH2I(hname, htitle, 60, -.3, .3, 100, -4.5, 4.5);
2765   } else h->Reset();
2766   arr->AddAt(h, 5);
2767
2768   // theta resolution
2769   snprintf(hname, 100, "%s_%s_THT", GetNameId(), name);
2770   snprintf(htitle, 300, "#Theta res for \"%s\" @ %s;tg(#theta);#Delta #theta [rad];entries", GetNameId(), name);
2771   if(!(h = (TH2I*)gROOT->FindObject(hname))){
2772     h = new TH2I(hname, htitle, 100, -1., 1., 100, -5e-3, 5e-3);
2773   } else h->Reset();
2774   arr->AddAt(h, 6);
2775   // tgl pulls
2776   snprintf(hname, 100, "%s_%s_TGLpull", GetNameId(), name);
2777   snprintf(htitle, 300, "TGL pull for \"%s\" @ %s;tg(#theta);#Delta tgl  / #sigma_{tgl};entries", GetNameId(), name);
2778   if(!(h = (TH2I*)gROOT->FindObject(hname))){
2779     h = new TH2I(hname, htitle, 100, -1., 1., 100, -4.5, 4.5);
2780   } else h->Reset();
2781   arr->AddAt(h, 7);
2782
2783   const Int_t kNdpt(150);
2784   const Int_t kNspc = 2*AliPID::kSPECIES+1;
2785   Float_t lPt=0.1, lDPt=-.1, lSpc=-5.5;
2786   Float_t binsPt[kNpt+1], binsSpc[kNspc+1], binsDPt[kNdpt+1];
2787   for(Int_t i=0;i<kNpt+1; i++,lPt=TMath::Exp(i*.15)-1.) binsPt[i]=lPt;
2788   for(Int_t i=0; i<kNspc+1; i++,lSpc+=1.) binsSpc[i]=lSpc;
2789   for(Int_t i=0; i<kNdpt+1; i++,lDPt+=2.e-3) binsDPt[i]=lDPt;
2790
2791   // Pt resolution
2792   snprintf(hname, 100, "%s_%s_Pt", GetNameId(), name);
2793   snprintf(htitle, 300, "#splitline{P_{t} res for}{\"%s\" @ %s};p_{t} [GeV/c];#Delta p_{t}/p_{t}^{MC};SPECIES", GetNameId(), name);
2794   if(!(h = (TH3S*)gROOT->FindObject(hname))){
2795     h = new TH3S(hname, htitle,
2796                  kNpt, binsPt, kNdpt, binsDPt, kNspc, binsSpc);
2797     //ax = h->GetZaxis();
2798     //for(Int_t ib(1); ib<=ax->GetNbins(); ib++) ax->SetBinLabel(ib, fgParticle[ib-1]);
2799   } else h->Reset();
2800   arr->AddAt(h, 8);
2801   // 1/Pt pulls
2802   snprintf(hname, 100, "%s_%s_1Pt", GetNameId(), name);
2803   snprintf(htitle, 300, "#splitline{1/P_{t} pull for}{\"%s\" @ %s};1/p_{t}^{MC} [c/GeV];#Delta(1/p_{t})/#sigma(1/p_{t});SPECIES", GetNameId(), name);
2804   if(!(h = (TH3S*)gROOT->FindObject(hname))){
2805     h = new TH3S(hname, htitle,
2806                  kNpt, 0., 2., 100, -4., 4., kNspc, -5.5, 5.5);
2807     //ax = h->GetZaxis();
2808     //for(Int_t ib(1); ib<=ax->GetNbins(); ib++) ax->SetBinLabel(ib, fgParticle[ib-1]);
2809   } else h->Reset();
2810   arr->AddAt(h, 9);
2811   // P resolution
2812   snprintf(hname, 100, "%s_%s_P", GetNameId(), name);
2813   snprintf(htitle, 300, "P res for \"%s\" @ %s;p [GeV/c];#Delta p/p^{MC};SPECIES", GetNameId(), name);
2814   if(!(h = (TH3S*)gROOT->FindObject(hname))){
2815     h = new TH3S(hname, htitle,
2816                  kNpt, binsPt, kNdpt, binsDPt, kNspc, binsSpc);
2817     //ax = h->GetZaxis();
2818     //for(Int_t ib(1); ib<=ax->GetNbins(); ib++) ax->SetBinLabel(ib, fgParticle[ib-1]);
2819   } else h->Reset();
2820   arr->AddAt(h, 10);
2821
2822   return arr;
2823 }
2824
2825
2826 //________________________________________________________
2827 TObjArray* AliTRDresolution::Histos()
2828 {
2829   //
2830   // Define histograms
2831   //
2832
2833   if(fContainer) return fContainer;
2834
2835   fContainer  = new TObjArray(kNclasses); fContainer->SetOwner(kTRUE);
2836   THnSparse *H(NULL);
2837   const Int_t nhn(100); Char_t hn[nhn]; TString st;
2838
2839   //++++++++++++++++++++++
2840   // cluster to detector
2841   snprintf(hn, nhn, "h%s", fgPerformanceName[kDetector]);
2842   if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
2843     const Int_t mdim(6);
2844     const Char_t *cldTitle[mdim] = {"layer", fgkTitle[kPhi], "pad row", "centrality", "q [a.u.]", "no. of pads"/*, "tb [10 Hz]"*/};
2845     const Int_t cldNbins[mdim]   = {AliTRDgeometry::kNlayer, fgkNbins[kPhi], 76, AliTRDeventInfo::kCentralityClasses, 50, kNpads};
2846     const Double_t cldMin[mdim]  = {-0.5, fgkMin[kPhi], -0.5, -0.5, 0., 0.5},
2847                    cldMax[mdim]  = {AliTRDgeometry::kNlayer-0.5, fgkMax[kPhi], 75.5, AliTRDeventInfo::kCentralityClasses - 0.5, 1200., kNpads+.5};
2848     st = "cluster proprieties;";
2849     // define minimum info to be saved in non debug mode
2850     Int_t ndim=DebugLevel()>=1?mdim:Int_t(kNdimDet);
2851     for(Int_t idim(0); idim<ndim; idim++){ st += cldTitle[idim]; st+=";";}
2852     H = new THnSparseI(hn, st.Data(), ndim, cldNbins, cldMin, cldMax);
2853   } else H->Reset();
2854   fContainer->AddAt(H, kDetector);
2855   //++++++++++++++++++++++
2856   // cluster to tracklet residuals/pulls
2857   snprintf(hn, nhn, "h%s", fgPerformanceName[kCluster]);
2858   if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
2859     const Int_t mdim(10);
2860     const Char_t *clTitle[mdim] = {"layer", fgkTitle[kPhi], fgkTitle[kEta], fgkTitle[kYrez], "#Deltax [cm]", "Q</Q", "Q/angle", "#Phi [deg]", "centrality", "no. of pads"};
2861     const Int_t clNbins[mdim]   = {AliTRDgeometry::kNlayer, fgkNbins[kPhi], fgkNbins[kEta], fgkNbins[kYrez], 45, 30, 30, 15, AliTRDeventInfo::kCentralityClasses, kNpads};
2862     const Double_t clMin[mdim]  = {-0.5, fgkMin[kPhi], fgkMin[kEta], fgkMin[kYrez]/10., -.5, 0.1, -2., -45, -0.5, 0.5},
2863                    clMax[mdim]  = {AliTRDgeometry::kNlayer-0.5, fgkMax[kPhi], fgkMax[kEta], fgkMax[kYrez]/10., 4., 2.1, 118., 45, AliTRDeventInfo::kCentralityClasses - 0.5, kNpads+.5};
2864     st = "cluster spatial&charge resolution;";
2865     // define minimum info to be saved in non debug mode
2866     Int_t ndim=DebugLevel()>=1?mdim:Int_t(kNdimCl);
2867     for(Int_t idim(0); idim<ndim; idim++){ st += clTitle[idim]; st+=";";}
2868     H = new THnSparseI(hn, st.Data(), ndim, clNbins, clMin, clMax);
2869   } else H->Reset();
2870   fContainer->AddAt(H, kCluster);
2871   //++++++++++++++++++++++
2872   // tracklet to TRD track
2873   snprintf(hn, nhn, "h%s", fgPerformanceName[kTracklet]);
2874   if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
2875     const Int_t mdim(kNdim+8);
2876     Char_t *trTitle[mdim]; memcpy(trTitle, fgkTitle, kNdim*sizeof(Char_t*));
2877     Int_t trNbins[mdim]; memcpy(trNbins, fgkNbins, kNdim*sizeof(Int_t));
2878     Double_t trMin[mdim]; memcpy(trMin, fgkMin, kNdim*sizeof(Double_t));
2879     Double_t trMax[mdim]; memcpy(trMax, fgkMax, kNdim*sizeof(Double_t));
2880     // set specific fields
2881     trMin[kYrez] = -0.45; trMax[kYrez] = 0.45;
2882     trMin[kPrez] = -4.5; trMax[kPrez] = 4.5;
2883     trMin[kZrez] = -1.5; trMax[kZrez] = 1.5;
2884     trTitle[kBC]=StrDup("layer"); trNbins[kBC] = AliTRDgeometry::kNlayer; trMin[kBC] = -0.5; trMax[kBC] = AliTRDgeometry::kNlayer-0.5;
2885     Int_t jdim(kNdim);
2886     trTitle[jdim]=StrDup("centrality"); trNbins[jdim] = AliTRDeventInfo::kCentralityClasses; trMin[jdim] = -.5; trMax[jdim] = AliTRDeventInfo::kCentralityClasses - 0.5;
2887     jdim++; trTitle[jdim]=StrDup("occupancy [%]"); trNbins[jdim] = 12; trMin[jdim] = 25.; trMax[jdim] = 85.;
2888 //    jdim++; trTitle[jdim]=StrDup("gap [cm]"); trNbins[jdim] = 80; trMin[jdim] = 0.1; trMax[jdim] = 2.1;
2889 //     jdim++; trTitle[jdim]=StrDup("size_{0} [cm]"); trNbins[jdim] = 16; trMin[jdim] = 0.15; trMax[jdim] = 1.75;
2890 //     jdim++; trTitle[jdim]=StrDup("pos_{0} [cm]"); trNbins[jdim] = 10; trMin[jdim] = 0.; trMax[jdim] = 3.5;
2891 //     jdim++; trTitle[jdim]=StrDup("size_{1} [cm]"); trNbins[jdim] = 16; trMin[jdim] = 0.15; trMax[jdim] = 1.75;
2892 //     jdim++; trTitle[jdim]=StrDup("pos_{1} [cm]"); trNbins[jdim] = 10; trMin[jdim] = 0.; trMax[jdim] = 3.5;
2893
2894     st = "tracklet spatial&charge resolution;";
2895     // define minimum info to be saved in non debug mode
2896     Int_t ndim=DebugLevel()>=1?(jdim+1):kNdimTrklt;
2897     for(Int_t idim(0); idim<ndim; idim++){ st += trTitle[idim]; st+=";";}
2898     H = new THnSparseI(hn, st.Data(), ndim, trNbins, trMin, trMax);
2899   } else H->Reset();
2900   fContainer->AddAt(H, kTracklet);
2901   //++++++++++++++++++++++
2902   // tracklet to TRDin
2903   snprintf(hn, nhn, "h%s", fgPerformanceName[kTrackIn]);
2904   if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
2905     // set specific fields
2906     const Int_t mdim(kNdim+3);
2907     Char_t *trinTitle[mdim]; memcpy(trinTitle, fgkTitle, kNdim*sizeof(Char_t*));
2908     Int_t trinNbins[mdim];   memcpy(trinNbins, fgkNbins, kNdim*sizeof(Int_t));
2909     Double_t trinMin[mdim];  memcpy(trinMin, fgkMin, kNdim*sizeof(Double_t));
2910     Double_t trinMax[mdim];  memcpy(trinMax, fgkMax, kNdim*sizeof(Double_t));
2911     trinNbins[kSpeciesChgRC] = Int_t(kNcharge)*AliPID::kSPECIES+1; trinMin[kSpeciesChgRC] = -AliPID::kSPECIES-0.5; trinMax[kSpeciesChgRC] = AliPID::kSPECIES+0.5;
2912     trinTitle[kNdim]=StrDup("p [GeV/c]"); trinNbins[kNdim] = 24; trinMin[kNdim] = -0.5; trinMax[kNdim] = 23.5;
2913     trinTitle[kNdim+1]=StrDup("dx [cm]"); trinNbins[kNdim+1]=48; trinMin[kNdim+1]=-2.4; trinMax[kNdim+1]=2.4;
2914     trinTitle[kNdim+2]=StrDup("Fill Bunch"); trinNbins[kNdim+2]=3500; trinMin[kNdim+2]=-0.5; trinMax[kNdim+2]=3499.5;
2915     st = "r-#phi/z/angular residuals @ TRD entry;";
2916     // define minimum info to be saved in non debug mode
2917     Int_t ndim=DebugLevel()>=1?mdim:kNdim;//kNdimTrkIn;
2918     for(Int_t idim(0); idim<ndim; idim++){st+=trinTitle[idim]; st+=";";}
2919     H = new THnSparseI(hn, st.Data(), ndim, trinNbins, trinMin, trinMax);
2920   } else H->Reset();
2921   fContainer->AddAt(H, kTrackIn);
2922   // tracklet to TRDout
2923 //  fContainer->AddAt(BuildMonitorContainerTracklet("TrkOUT"), kTrackOut);
2924
2925
2926   // Resolution histos
2927   if(!HasMCdata()) return fContainer;
2928
2929   //++++++++++++++++++++++
2930   // cluster to TrackRef residuals/pulls
2931   snprintf(hn, nhn, "h%s", fgPerformanceName[kMCcluster]);
2932   if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
2933     const Char_t *clTitle[kNdim] = {"layer", fgkTitle[kPhi], fgkTitle[kEta], fgkTitle[kYrez], "#Deltax [cm]", "Q</Q", fgkTitle[kSpeciesChgRC], "#Phi [deg]"};
2934     const Int_t clNbins[kNdim]   = {AliTRDgeometry::kNlayer, fgkNbins[kPhi], fgkNbins[kEta], fgkNbins[kYrez], 20, 10, Int_t(kNcharge)*AliPID::kSPECIES+1, 15};
2935     const Double_t clMin[kNdim]  = {-0.5, fgkMin[kPhi], fgkMin[kEta], fgkMin[kYrez]/10., 0., 0.1, -AliPID::kSPECIES-0.5, -45},
2936                    clMax[kNdim]  = {AliTRDgeometry::kNlayer-0.5, fgkMax[kPhi], fgkMax[kEta], fgkMax[kYrez]/10., 4., 2.1, AliPID::kSPECIES+0.5, 45};
2937     st = "MC cluster spatial resolution;";
2938     // define minimum info to be saved in non debug mode
2939     Int_t ndim=DebugLevel()>=1?kNdim:4;
2940     for(Int_t idim(0); idim<ndim; idim++){ st += clTitle[idim]; st+=";";}
2941     H = new THnSparseI(hn, st.Data(), ndim, clNbins, clMin, clMax);
2942   } else H->Reset();
2943   fContainer->AddAt(H, kMCcluster);
2944   //++++++++++++++++++++++
2945   // tracklet to TrackRef
2946   snprintf(hn, nhn, "h%s", fgPerformanceName[kMCtracklet]);
2947   if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
2948     Char_t *trTitle[kNdim]; memcpy(trTitle, fgkTitle, kNdim*sizeof(Char_t*));
2949     Int_t trNbins[kNdim]; memcpy(trNbins, fgkNbins, kNdim*sizeof(Int_t));
2950     Double_t trMin[kNdim]; memcpy(trMin, fgkMin, kNdim*sizeof(Double_t));
2951     Double_t trMax[kNdim]; memcpy(trMax, fgkMax, kNdim*sizeof(Double_t));
2952     // set specific fields
2953     trTitle[kBC]=StrDup("layer"); trNbins[kBC] = AliTRDgeometry::kNlayer; trMin[kBC] = -0.5; trMax[kBC] = AliTRDgeometry::kNlayer-0.5;
2954     trMin[kYrez] = -0.54; trMax[kYrez] = -trMin[kYrez];
2955     trMin[kPrez] = -4.5; trMax[kPrez] = -trMin[kPrez];
2956     trMin[kZrez] = -1.5; trMax[kZrez] = -trMin[kZrez];
2957     trNbins[kSpeciesChgRC] = Int_t(kNcharge)*AliPID::kSPECIES+1;trMin[kSpeciesChgRC] = -AliPID::kSPECIES-0.5; trMax[kSpeciesChgRC] = AliPID::kSPECIES+0.5;
2958
2959     st = "MC tracklet spatial resolution;";
2960     // define minimum info to be saved in non debug mode
2961     Int_t ndim=DebugLevel()>=1?kNdim:4;
2962     for(Int_t idim(0); idim<ndim; idim++){ st += trTitle[idim]; st+=";";}
2963     H = new THnSparseI(hn, st.Data(), ndim, trNbins, trMin, trMax);
2964   } else H->Reset();
2965   fContainer->AddAt(H, kMCtracklet);
2966   //++++++++++++++++++++++
2967   // TRDin to TrackRef
2968   snprintf(hn, nhn, "h%s", fgPerformanceName[kMCtrackIn]);
2969   if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
2970     st = "MC r-#phi/z/angular residuals @ TRD entry;";
2971     // set specific fields
2972     Int_t trNbins[kNdim]; memcpy(trNbins, fgkNbins, kNdim*sizeof(Int_t));
2973     Double_t trMin[kNdim]; memcpy(trMin, fgkMin, kNdim*sizeof(Double_t));
2974     Double_t trMax[kNdim]; memcpy(trMax, fgkMax, kNdim*sizeof(Double_t));
2975     trMin[kYrez] = -0.54; trMax[kYrez] = -trMin[kYrez];
2976     trMin[kPrez] = -2.4; trMax[kPrez] = -trMin[kPrez];
2977     trMin[kZrez] = -0.9; trMax[kZrez] = -trMin[kZrez];
2978     trNbins[kSpeciesChgRC] = Int_t(kNcharge)*AliPID::kSPECIES+1;trMin[kSpeciesChgRC] = -AliPID::kSPECIES-0.5; trMax[kSpeciesChgRC] = AliPID::kSPECIES+0.5;
2979     // define minimum info to be saved in non debug mode
2980     Int_t ndim=DebugLevel()>=1?kNdim:7;
2981     for(Int_t idim(0); idim<ndim; idim++){ st += fgkTitle[idim]; st+=";";}
2982     H = new THnSparseI(hn, st.Data(), ndim, trNbins, trMin, trMax);
2983   } else H->Reset();
2984   fContainer->AddAt(H, kMCtrackIn);
2985   //++++++++++++++++++++++
2986   // track to TrackRef
2987   snprintf(hn, nhn, "h%s", fgPerformanceName[kMCtrack]);
2988   if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
2989     Char_t *trTitle[kNdim+1]; memcpy(trTitle, fgkTitle, kNdim*sizeof(Char_t*));
2990     Int_t trNbins[kNdim+1]; memcpy(trNbins, fgkNbins, kNdim*sizeof(Int_t));
2991     Double_t trMin[kNdim+1]; memcpy(trMin, fgkMin, kNdim*sizeof(Double_t));
2992     Double_t trMax[kNdim+1]; memcpy(trMax, fgkMax, kNdim*sizeof(Double_t));
2993     // set specific fields
2994     trTitle[kBC]=StrDup("layer"); trNbins[kBC] = AliTRDgeometry::kNlayer; trMin[kBC] = -0.5; trMax[kBC] = AliTRDgeometry::kNlayer-0.5;
2995     trMin[kYrez] = -0.9; trMax[kYrez] = -trMin[kYrez];
2996     trMin[kPrez] = -1.5; trMax[kPrez] = -trMin[kPrez];
2997     trMin[kZrez] = -0.9; trMax[kZrez] = -trMin[kZrez];
2998     trNbins[kSpeciesChgRC] = Int_t(kNcharge)*AliPID::kSPECIES+1;trMin[kSpeciesChgRC] = -AliPID::kSPECIES-0.5; trMax[kSpeciesChgRC] = AliPID::kSPECIES+0.5;
2999     trTitle[kNdim]=StrDup("#Deltap_{t}/p_{t} [%]"); trNbins[kNdim] = 25; trMin[kNdim] = -4.5; trMax[kNdim] = 20.5;
3000
3001     st = "MC track spatial&p_{t} resolution;";
3002     // define minimum info to be saved in non debug mode
3003     Int_t ndim=DebugLevel()>=1?(kNdim+1):4;
3004     for(Int_t idim(0); idim<ndim; idim++){ st += trTitle[idim]; st+=";";}
3005     H = new THnSparseI(hn, st.Data(), ndim, trNbins, trMin, trMax);
3006   } else H->Reset();
3007   fContainer->AddAt(H, kMCtrack);
3008
3009   return fContainer;
3010 }
3011
3012 //____________________________________________________________________
3013 Bool_t AliTRDresolution::FitTrack(const Int_t np, AliTrackPoint *points, Float_t param[10])
3014 {
3015 //
3016 // Fit track with a staight line using the "np" clusters stored in the array "points".
3017 // The following particularities are stored in the clusters from points:
3018 //   1. pad tilt as cluster charge
3019 //   2. pad row cross or vertex constrain as fake cluster with cluster type 1
3020 // The parameters of the straight line fit are stored in the array "param" in the following order :
3021 //     param[0] - x0 reference radial position
3022 //     param[1] - y0 reference r-phi position @ x0
3023 //     param[2] - z0 reference z position @ x0
3024 //     param[3] - slope dy/dx
3025 //     param[4] - slope dz/dx
3026 //
3027 // Attention :
3028 // Function should be used to refit tracks for B=0T
3029 //
3030
3031   if(np<40){
3032     if(AliLog::GetDebugLevel("PWGPP", "AliTRDresolution")>1) printf("D-AliTRDresolution::FitTrack: Not enough clusters to fit a track [%d].\n", np);
3033     return kFALSE;
3034   }
3035   TLinearFitter yfitter(2, "pol1"), zfitter(2, "pol1");
3036
3037   Double_t x0(0.);
3038   for(Int_t ip(0); ip<np; ip++) x0+=points[ip].GetX();
3039   x0/=Float_t(np);
3040
3041   Double_t x, y, z, dx, tilt(0.);
3042   for(Int_t ip(0); ip<np; ip++){
3043     x = points[ip].GetX(); z = points[ip].GetZ();
3044     dx = x - x0;
3045     zfitter.AddPoint(&dx, z, points[ip].GetClusterType()?1.e-3:1.);
3046   }
3047   if(zfitter.Eval() != 0) return kFALSE;
3048
3049   Double_t z0    = zfitter.GetParameter(0);
3050   Double_t dzdx  = zfitter.GetParameter(1);
3051   for(Int_t ip(0); ip<np; ip++){
3052     if(points[ip].GetClusterType()) continue;
3053     x    = points[ip].GetX();
3054     dx   = x - x0;
3055     y    = points[ip].GetY();
3056     z    = points[ip].GetZ();
3057     tilt = points[ip].GetCharge();
3058     y -= tilt*(-dzdx*dx + z - z0);
3059     Float_t xyz[3] = {x, y, z}; points[ip].SetXYZ(xyz);
3060     yfitter.AddPoint(&dx, y, 1.);
3061   }
3062   if(yfitter.Eval() != 0) return kFALSE;
3063   Double_t y0   = yfitter.GetParameter(0);
3064   Double_t dydx = yfitter.GetParameter(1);
3065
3066   param[0] = x0; param[1] = y0; param[2] = z0; param[3] = dydx; param[4] = dzdx;
3067   if(AliLog::GetDebugLevel("PWGPP", "AliTRDresolution")>3) printf("D-AliTRDresolution::FitTrack: x0[%f] y0[%f] z0[%f] dydx[%f] dzdx[%f].\n", x0, y0, z0, dydx, dzdx);
3068   return kTRUE;
3069 }
3070
3071 //____________________________________________________________________
3072 Bool_t AliTRDresolution::FitTracklet(const Int_t ly, const Int_t np, const AliTrackPoint *points, const Float_t param[10], Float_t par[3])
3073 {
3074 //
3075 // Fit tracklet with a staight line using the coresponding subset of clusters out of the total "np" clusters stored in the array "points".
3076 // See function FitTrack for the data stored in the "clusters" array
3077
3078 // The parameters of the straight line fit are stored in the array "param" in the following order :
3079 //     par[0] - x0 reference radial position
3080 //     par[1] - y0 reference r-phi position @ x0
3081 //     par[2] - slope dy/dx
3082 //
3083 // Attention :
3084 // Function should be used to refit tracks for B=0T
3085 //
3086
3087   TLinearFitter yfitter(2, "pol1");
3088
3089   // grep data for tracklet
3090   Double_t x0(0.), x[60], y[60], dy[60];
3091   Int_t nly(0);
3092   for(Int_t ip(0); ip<np; ip++){
3093     if(points[ip].GetClusterType()) continue;
3094     if(points[ip].GetVolumeID() != ly) continue;
3095     Float_t xt(points[ip].GetX())
3096            ,yt(param[1] + param[3] * (xt - param[0]));
3097     x[nly] = xt;
3098     y[nly] = points[ip].GetY();
3099     dy[nly]= y[nly]-yt;
3100     x0    += xt;
3101     nly++;
3102   }
3103   if(nly<10){
3104     if(AliLog::GetDebugLevel("PWGPP", "AliTRDresolution")>1) printf("D-AliTRDresolution::FitTracklet: Not enough clusters to fit a tracklet [%d].\n", nly);
3105     return kFALSE;
3106   }
3107   // set radial reference for fit
3108   x0 /= Float_t(nly);
3109
3110   // find tracklet core
3111   Double_t mean(0.), sig(1.e3);
3112   AliMathBase::EvaluateUni(nly, dy, mean, sig, 0);
3113
3114   // simple cluster error parameterization
3115   Float_t kSigCut = TMath::Sqrt(5.e-4 + param[3]*param[3]*0.018);
3116
3117   // fit tracklet core
3118   for(Int_t jly(0); jly<nly; jly++){
3119     if(TMath::Abs(dy[jly]-mean)>kSigCut) continue;
3120     Double_t dx(x[jly]-x0);
3121     yfitter.AddPoint(&dx, y[jly], 1.);
3122   }
3123   if(yfitter.Eval() != 0) return kFALSE;
3124   par[0] = x0;
3125   par[1] = yfitter.GetParameter(0);
3126   par[2] = yfitter.GetParameter(1);
3127   return kTRUE;
3128 }
3129
3130 //____________________________________________________________________
3131 Bool_t AliTRDresolution::UseTrack(const Int_t np, const AliTrackPoint *points, Float_t param[10])
3132 {
3133 //
3134 // Global selection mechanism of tracksbased on cluster to fit residuals
3135 // The parameters are the same as used ni function FitTrack().
3136
3137   const Float_t kS(0.6), kM(0.2);
3138   TH1S h("h1", "", 100, -5.*kS, 5.*kS);
3139   Float_t dy, dz, s, m;
3140   for(Int_t ip(0); ip<np; ip++){
3141     if(points[ip].GetClusterType()) continue;
3142     Float_t x0(points[ip].GetX())
3143           ,y0(param[1] + param[3] * (x0 - param[0]))
3144           ,z0(param[2] + param[4] * (x0 - param[0]));
3145     dy=points[ip].GetY() - y0; h.Fill(dy);
3146     dz=points[ip].GetZ() - z0;
3147   }
3148   TF1 fg("fg", "gaus", -5.*kS, 5.*kS);
3149   fg.SetParameter(1, 0.);
3150   fg.SetParameter(2, 2.e-2);
3151   h.Fit(&fg, "QN");
3152   m=fg.GetParameter(1); s=fg.GetParameter(2);
3153   if(s>kS || TMath::Abs(m)>kM) return kFALSE;
3154   return kTRUE;
3155 }
3156
3157 //________________________________________________________
3158 void AliTRDresolution::GetLandauMpvFwhm(TF1 * const f, Float_t &mpv, Float_t &xm, Float_t &xM)
3159 {
3160   //
3161   // Get the most probable value and the full width half mean
3162   // of a Landau distribution
3163   //
3164
3165   const Float_t dx = 1.;
3166   mpv = f->GetParameter(1);
3167   Float_t fx, max = f->Eval(mpv);
3168
3169   xm = mpv - dx;
3170   while((fx = f->Eval(xm))>.5*max){
3171     if(fx>max){
3172       max = fx;
3173       mpv = xm;
3174     }
3175     xm -= dx;
3176   }
3177
3178   xM += 2*(mpv - xm);
3179   while((fx = f->Eval(xM))>.5*max) xM += dx;
3180 }
3181
3182
3183 // #include "TFile.h"
3184 // //________________________________________________________
3185 // Bool_t AliTRDresolution::LoadCorrection(const Char_t *file)
3186 // {
3187 //   if(!file){
3188 //     AliWarning("Use cluster position as in reconstruction.");
3189 //     SetLoadCorrection();
3190 //     return kTRUE;
3191 //   }
3192 //   TDirectory *cwd(gDirectory);
3193 //   TString fileList;
3194 //   FILE *filePtr = fopen(file, "rt");
3195 //   if(!filePtr){
3196 //     AliWarning(Form("Couldn't open correction list \"%s\". Use cluster position as in reconstruction.", file));
3197 //     SetLoadCorrection();
3198 //     return kFALSE;
3199 //   }
3200 //   TH2 *h2 = new TH2F("h2", ";time [time bins];detector;dx [#mum]", 30, -0.5, 29.5, AliTRDgeometry::kNdet, -0.5, AliTRDgeometry::kNdet-0.5);
3201 //   while(fileList.Gets(filePtr)){
3202 //     if(!TFile::Open(fileList.Data())) {
3203 //       AliWarning(Form("Couldn't open \"%s\"", fileList.Data()));
3204 //       continue;
3205 //     } else AliInfo(Form("\"%s\"", fileList.Data()));
3206 //
3207 //     TTree *tSys = (TTree*)gFile->Get("tSys");
3208 //     h2->SetDirectory(gDirectory); h2->Reset("ICE");
3209 //     tSys->Draw("det:t>>h2", "dx", "goff");
3210 //     for(Int_t idet(0); idet<AliTRDgeometry::kNdet; idet++){
3211 //       for(Int_t it(0); it<30; it++) fXcorr[idet][it]+=(1.e-4*h2->GetBinContent(it+1, idet+1));
3212 //     }
3213 //     h2->SetDirectory(cwd);
3214 //     gFile->Close();
3215 //   }
3216 //   cwd->cd();
3217 //
3218 //   if(AliLog::GetDebugLevel("PWGPP", "AliTRDresolution")>=2){
3219 //     for(Int_t il(0); il<184; il++) printf("-"); printf("\n");
3220 //     printf("DET|");for(Int_t it(0); it<30; it++) printf(" tb%02d|", it); printf("\n");
3221 //     for(Int_t il(0); il<184; il++) printf("-"); printf("\n");
3222 //     FILE *fout = fopen("TRD.ClusterCorrection.txt", "at");
3223 //     fprintf(fout, "  static const Double_t dx[AliTRDgeometry::kNdet][30]={\n");
3224 //     for(Int_t idet(0); idet<AliTRDgeometry::kNdet; idet++){
3225 //       printf("%03d|", idet);
3226 //       fprintf(fout, "    {");
3227 //       for(Int_t it(0); it<30; it++){
3228 //         printf("%+5.0f|", 1.e4*fXcorr[idet][it]);
3229 //         fprintf(fout, "%+6.4f%c", fXcorr[idet][it], it==29?' ':',');
3230 //       }
3231 //       printf("\n");
3232 //       fprintf(fout, "}%c\n", idet==AliTRDgeometry::kNdet-1?' ':',');
3233 //     }
3234 //     fprintf(fout, "  };\n");
3235 //   }
3236 //   SetLoadCorrection();
3237 //   return kTRUE;
3238 // }
3239
3240 //________________________________________________________
3241 void AliTRDresolution::SetProcesses(Bool_t det, Bool_t cl, Bool_t trklt, Bool_t trkin)
3242 {
3243 // steer processes
3244   if(det) SETBIT(fSteer, kDetector); else CLRBIT(fSteer, kDetector);
3245   if(cl)  SETBIT(fSteer, kCluster); else CLRBIT(fSteer, kCluster);
3246   if(trklt) SETBIT(fSteer, kTracklet); else CLRBIT(fSteer, kTracklet);
3247   if(trkin) SETBIT(fSteer, kTrackIn); else CLRBIT(fSteer, kTrackIn);
3248 }
3249
3250
3251 //________________________________________________________
3252 void AliTRDresolution::SetDump3D(Bool_t det, Bool_t cl, Bool_t trklt, Bool_t trkin)
3253 {
3254 // steer processes
3255   if(det) SETBIT(fSteer, 4+kDetector); else CLRBIT(fSteer, 4+kDetector);
3256   if(cl)  SETBIT(fSteer, 4+kCluster); else CLRBIT(fSteer, 4+kCluster);
3257   if(trklt) SETBIT(fSteer, 4+kTracklet); else CLRBIT(fSteer, 4+kTracklet);
3258   if(trkin) SETBIT(fSteer, 4+kTrackIn); else CLRBIT(fSteer, 4+kTrackIn);
3259 }
3260