1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-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 **************************************************************************/
16 /* $Id: AliTRDresolution.cxx 27496 2008-07-22 08:35:45Z cblume $ */
18 ////////////////////////////////////////////////////////////////////////////
20 // TRD tracking resolution //
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
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
32 // For stand alone usage please refer to the following example:
34 // gSystem->Load("libANALYSIS.so");
35 // gSystem->Load("libTRDqaRec.so");
36 // AliTRDresolution *res = new AliTRDresolution();
37 // //res->SetMCdata();
38 // //res->SetVerbose();
39 // //res->SetVisual();
41 // if(!res->PostProcess()) return;
42 // res->GetRefFigure(0);
46 // Alexandru Bercuci <A.Bercuci@gsi.de> //
47 // Markus Fasel <M.Fasel@gsi.de> //
49 ////////////////////////////////////////////////////////////////////////////
54 #include <TObjArray.h>
58 #include <THnSparse.h>
64 #include <TGraphErrors.h>
65 #include <TGraphAsymmErrors.h>
66 #include <TLinearFitter.h>
70 #include <TTreeStream.h>
71 #include <TGeoManager.h>
72 #include <TDatabasePDG.h>
76 #include "AliESDtrack.h"
77 #include "AliMathBase.h"
78 #include "AliTrackPointArray.h"
80 #include "AliTRDresolution.h"
81 #include "AliTRDgeometry.h"
82 #include "AliTRDtransform.h"
83 #include "AliTRDpadPlane.h"
84 #include "AliTRDcluster.h"
85 #include "AliTRDseedV1.h"
86 #include "AliTRDtrackV1.h"
87 #include "AliTRDReconstructor.h"
88 #include "AliTRDrecoParam.h"
89 #include "AliTRDpidUtil.h"
90 #include "AliTRDinfoGen.h"
92 #include "info/AliTRDclusterInfo.h"
94 ClassImp(AliTRDresolution)
95 //ClassImp(AliTRDresolution::AliTRDresolutionProjection)
97 Int_t const AliTRDresolution::fgkNbins[kNdim] = {
98 Int_t(kNbunchCross)/*bc*/,
104 Int_t(kNcharge)*AliPID::kSPECIES+1/*chg*species*/,
106 }; //! no of bins/projection
107 Double_t const AliTRDresolution::fgkMin[kNdim] = {
114 -AliPID::kSPECIES-0.5,
116 }; //! low limits for projections
117 Double_t const AliTRDresolution::fgkMax[kNdim] = {
118 Int_t(kNbunchCross)-0.5,
124 AliPID::kSPECIES+0.5,
126 }; //! high limits for projections
127 Char_t const *AliTRDresolution::fgkTitle[kNdim] = {
136 }; //! title of projection
138 Int_t const AliTRDresolution::fgkNproj[kNclasses] = {
142 Char_t const * AliTRDresolution::fgPerformanceName[kNclasses] = {
153 Float_t AliTRDresolution::fgPtBin[kNpt+1];
155 //________________________________________________________
156 AliTRDresolution::AliTRDresolution()
168 // Default constructor
170 SetNameTitle("TRDresolution", "TRD spatial and momentum resolution");
171 MakePtSegmentation();
174 //________________________________________________________
175 AliTRDresolution::AliTRDresolution(char* name, Bool_t xchange)
176 :AliTRDrecoTask(name, "TRD spatial and momentum resolution")
187 // Default constructor
191 MakePtSegmentation();
193 SetUseExchangeContainers();
194 DefineOutput(kClToTrk, TObjArray::Class()); // cluster2track
195 DefineOutput(kClToMC, TObjArray::Class()); // cluster2mc
199 //________________________________________________________
200 AliTRDresolution::~AliTRDresolution()
206 if(fProj){fProj->Delete(); delete fProj;}
207 if(fCl){fCl->Delete(); delete fCl;}
208 if(fMCcl){fMCcl->Delete(); delete fMCcl;}
212 //________________________________________________________
213 void AliTRDresolution::UserCreateOutputObjects()
215 // spatial resolution
217 AliTRDrecoTask::UserCreateOutputObjects();
218 if(UseExchangeContainers()) InitExchangeContainers();
221 //________________________________________________________
222 void AliTRDresolution::InitExchangeContainers()
224 // Init containers for subsequent tasks (AliTRDclusterResolution)
226 fCl = new TObjArray(200); fCl->SetOwner(kTRUE);
227 fMCcl = new TObjArray(); fMCcl->SetOwner(kTRUE);
228 PostData(kClToTrk, fCl);
229 PostData(kClToMC, fMCcl);
232 //________________________________________________________
233 void AliTRDresolution::UserExec(Option_t *opt)
239 if(fCl) fCl->Delete();
240 if(fMCcl) fMCcl->Delete();
241 AliTRDrecoTask::UserExec(opt);
244 //________________________________________________________
245 Bool_t AliTRDresolution::Pulls(Double_t* /*dyz[2]*/, Double_t* /*cov[3]*/, Double_t /*tilt*/) const
247 // Helper function to calculate pulls in the yz plane
248 // using proper tilt rotation
249 // Uses functionality defined by AliTRDseedV1.
253 Double_t t2(tilt*tilt);
254 // exit door until a bug fix is found for AliTRDseedV1::GetCovSqrt
258 cc[0] = cov[0] - 2.*tilt*cov[1] + t2*cov[2];
259 cc[1] = cov[1]*(1.-t2) + tilt*(cov[0] - cov[2]);
260 cc[2] = t2*cov[0] + 2.*tilt*cov[1] + cov[2];
262 Double_t sqr[3]={0., 0., 0.};
263 if(AliTRDseedV1::GetCovSqrt(cc, sqr)) return kFALSE;
264 Double_t invsqr[3]={0., 0., 0.};
265 if(AliTRDseedV1::GetCovInv(sqr, invsqr)<1.e-40) return kFALSE;
266 Double_t tmp(dyz[0]);
267 dyz[0] = invsqr[0]*tmp + invsqr[1]*dyz[1];
268 dyz[1] = invsqr[1]*tmp + invsqr[2]*dyz[1];
273 //________________________________________________________
274 TH1* AliTRDresolution::PlotCluster(const AliTRDtrackV1 *track)
277 // Plot the cluster distributions
280 if(track) fkTrack = track;
282 AliDebug(4, "No Track defined.");
285 if(TMath::Abs(fkESD->GetTOFbc()) > 1){
286 AliDebug(4, Form("Track with BC_index[%d] not used.", fkESD->GetTOFbc()));
289 if(fPt<fPtThreshold){
290 AliDebug(4, Form("Track with pt[%6.4f] under threshold.", fPt));
294 if(!fContainer || !(H = ((THnSparse*)fContainer->At(kCluster)))){
295 AliWarning("No output container defined.");
299 AliTRDgeometry *geo(AliTRDinfoGen::Geometry());
300 Double_t val[kNdim]; //Float_t exb, vd, t0, s2, dl, dt;
301 TObjArray *clInfoArr(NULL);
302 AliTRDseedV1 *fTracklet(NULL);
303 AliTRDcluster *c(NULL), *cc(NULL);
304 for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
305 if(!(fTracklet = fkTrack->GetTracklet(ily))) continue;
306 if(!fTracklet->IsOK()) continue;
307 //fTracklet->GetCalibParam(exb, vd, t0, s2, dl, dt);
311 val[kPt] = TMath::ATan(fTracklet->GetYref(1))*TMath::RadToDeg();
312 Float_t corr = 1./TMath::Sqrt(1.+fTracklet->GetYref(1)*fTracklet->GetYref(1)+fTracklet->GetZref(1)*fTracklet->GetZref(1));
314 Float_t padCorr(fTracklet->GetTilt()*fTracklet->GetPadLength());
315 fTracklet->ResetClusterIter(kTRUE);
316 while((c = fTracklet->NextCluster())){
317 Float_t xc(c->GetX()),
319 Int_t tb(c->GetLocalTimeBin());
320 if(row0<0) row0 = c->GetPadRow();
322 val[kYrez] = c->GetY() + padCorr*(c->GetPadRow() - row0) -fTracklet->GetYat(xc);
323 val[kPrez] = fTracklet->GetX0()-xc;
324 val[kZrez] = 0.; Int_t ic(0);
325 if((cc = fTracklet->GetClusters(tb-1))) {val[kZrez] += cc->GetQ(); ic++;}
326 if((cc = fTracklet->GetClusters(tb-2))) {val[kZrez] += cc->GetQ(); ic++;}
327 if(ic) val[kZrez] /= (ic*q);
328 val[kSpeciesChgRC]= fTracklet->IsRowCross()?0.:(TMath::Max(q*corr, Float_t(3.)));
330 /* // tilt rotation of covariance for clusters
331 Double_t sy2(c->GetSigmaY2()), sz2(c->GetSigmaZ2());
332 cov[0] = (sy2+t2*sz2)*corr;
333 cov[1] = tilt*(sz2 - sy2)*corr;
334 cov[2] = (t2*sy2+sz2)*corr;
335 // sum with track covariance
336 cov[0]+=covR[0]; cov[1]+=covR[1]; cov[2]+=covR[2];
337 Double_t dyz[2]= {dy[1], dz[1]};
338 Pulls(dyz, cov, tilt);*/
340 // Get z-position with respect to anode wire
341 Float_t yt(fTracklet->GetYref(0)-val[kZrez]*fTracklet->GetYref(1)),
342 zt(fTracklet->GetZref(0)-val[kZrez]*fTracklet->GetZref(1));
343 Int_t istk = geo->GetStack(c->GetDetector());
344 AliTRDpadPlane *pp = geo->GetPadPlane(ily, istk);
345 Float_t rowZ = pp->GetRow0();
346 Float_t d = rowZ - zt + pp->GetAnodeWireOffset();
347 d -= ((Int_t)(2 * d)) / 2.0;
348 if (d > 0.25) d = 0.5 - d;
350 AliTRDclusterInfo *clInfo(NULL);
351 clInfo = new AliTRDclusterInfo;
352 clInfo->SetCluster(c);
353 //Float_t covF[] = {cov[0], cov[1], cov[2]};
354 clInfo->SetGlobalPosition(yt, zt, fTracklet->GetYref(1), fTracklet->GetZref(1)/*, covF*/);
355 clInfo->SetResolution(val[kYrez]);
356 clInfo->SetAnisochronity(d);
357 clInfo->SetDriftLength(val[kZrez]);
358 clInfo->SetTilt(fTracklet->GetTilt());
359 if(fCl) fCl->Add(clInfo);
360 //else AliDebug(1, "Cl exchange container missing. Activate by calling \"InitExchangeContainers()\"");
364 clInfoArr=new TObjArray(AliTRDseedV1::kNclusters);
365 clInfoArr->SetOwner(kFALSE);
367 clInfoArr->Add(clInfo);
370 if(DebugLevel()>=2 && clInfoArr){
371 ULong_t status = fkESD->GetStatus();
372 (*DebugStream()) << "cluster"
373 <<"status=" << status
374 <<"clInfo.=" << clInfoArr
379 if(clInfoArr) delete clInfoArr;
381 return NULL;//H->Projection(kEta, kPhi);
385 //________________________________________________________
386 TH1* AliTRDresolution::PlotTracklet(const AliTRDtrackV1 *track)
388 // Plot normalized residuals for tracklets to track.
390 // We start from the result that if X=N(|m|, |Cov|)
392 // (Cov^{-1})^{1/2}X = N((Cov^{-1})^{1/2}*|m|, |1|)
394 // in our case X=(y_trklt - y_trk z_trklt - z_trk) and |Cov| = |Cov_trklt| + |Cov_trk| at the radial
395 // reference position.
396 if(track) fkTrack = track;
398 AliDebug(4, "No Track defined.");
401 if(TMath::Abs(fkESD->GetTOFbc())>1){
402 AliDebug(4, Form("Track with BC_index[%d] not used.", fkESD->GetTOFbc()));
406 if(!fContainer || !(H = (THnSparse*)fContainer->At(kTracklet))){
407 AliWarning("No output container defined.");
411 Double_t val[kNdim+1];
412 AliTRDseedV1 *fTracklet(NULL);
413 for(Int_t il(0); il<AliTRDgeometry::kNlayer; il++){
414 if(!(fTracklet = fkTrack->GetTracklet(il))) continue;
415 if(!fTracklet->IsOK()) continue;
419 val[kSpeciesChgRC]= fSpecies;
420 val[kPt] = GetPtBin(fTracklet->GetMomentum());
421 Double_t dyt(fTracklet->GetYref(0) - fTracklet->GetYfit(0)),
422 dzt(fTracklet->GetZref(0) - fTracklet->GetZfit(0)),
423 dydx(fTracklet->GetYfit(1)),
424 tilt(fTracklet->GetTilt());
425 // correct for tilt rotation
426 val[kYrez] = dyt - dzt*tilt;
427 val[kZrez] = dzt + dyt*tilt;
428 dydx+= tilt*fTracklet->GetZref(1);
429 val[kPrez] = TMath::ATan((fTracklet->GetYref(1) - dydx)/(1.+ fTracklet->GetYref(1)*dydx)) * TMath::RadToDeg();
430 if(fTracklet->IsRowCross()){
431 val[kSpeciesChgRC]= 0.;
432 // val[kPrez] = fkTrack->Charge(); // may be better defined
434 Float_t exb, vd, t0, s2, dl, dt;
435 fTracklet->GetCalibParam(exb, vd, t0, s2, dl, dt);
436 val[kZrez] = TMath::ATan((fTracklet->GetYref(1) - exb)/(1+fTracklet->GetYref(1)*exb));
438 val[kNdim] = fTracklet->GetdQdl();
439 if(DebugLevel()>=1) H->Fill(val);
441 // // compute covariance matrix
442 // fTracklet->GetCovAt(x, cov);
443 // fTracklet->GetCovRef(covR);
444 // cov[0] += covR[0]; cov[1] += covR[1]; cov[2] += covR[2];
445 // Double_t dyz[2]= {dy[1], dz[1]};
446 // Pulls(dyz, cov, tilt);
447 // ((TH3S*)arr->At(1))->Fill(sgm[fSegmentLevel], dyz[0], dyz[1]);
448 // ((TH3S*)arr->At(3))->Fill(tht, dyz[1], rc);
451 Bool_t rc(fTracklet->IsRowCross());
452 UChar_t err(fTracklet->GetErrorMsg());
453 Double_t x(fTracklet->GetX()),
454 pt(fTracklet->GetPt()),
455 yt(fTracklet->GetYref(0)),
456 zt(fTracklet->GetZref(0)),
457 phi(fTracklet->GetYref(1)),
458 tht(fTracklet->GetZref(1));
459 Int_t ncl(fTracklet->GetN()),
460 det(fTracklet->GetDetector());
461 (*DebugStream()) << "tracklet"
472 <<"dy=" << val[kYrez]
473 <<"dz=" << val[kZrez]
474 <<"dphi="<< val[kPrez]
475 <<"dQ ="<< val[kNdim]
481 return NULL;//H->Projection(kEta, kPhi);
485 //________________________________________________________
486 TH1* AliTRDresolution::PlotTrackIn(const AliTRDtrackV1 *track)
488 // Store resolution/pulls of Kalman before updating with the TRD information
489 // at the radial position of the first tracklet. The following points are used
491 // - the (y,z,snp) of the first TRD tracklet
492 // - the (y, z, snp, tgl, pt) of the MC track reference
494 // Additionally the momentum resolution/pulls are calculated for usage in the
496 //printf("AliTRDresolution::PlotTrackIn() :: track[%p]\n", (void*)track);
498 if(track) fkTrack = track;
500 AliDebug(4, "No Track defined.");
505 THnSparseI *H=(THnSparseI*)fContainer->At(kTrackIn);
507 AliError(Form("Missing container @ %d", Int_t(kTrackIn)));
510 // check input track status
511 AliExternalTrackParam *tin(NULL);
512 if(!(tin = fkTrack->GetTrackIn())){
513 AliError("Track did not entered TRD fiducial volume.");
516 // check first tracklet
517 AliTRDseedV1 *fTracklet(fkTrack->GetTracklet(0));
519 AliDebug(3, "No Tracklet in ly[0]. Skip track.");
522 // check radial position
523 Double_t x = tin->GetX();
524 if(TMath::Abs(x-fTracklet->GetX())>1.e-3){
525 AliDebug(1, Form("Tracklet did not match Track. dx[cm]=%+4.1f", x-fTracklet->GetX()));
528 //printf("USE y[%+f] dydx[%+f]\n", fTracklet->GetYfit(0), fTracklet->GetYfit(1));
530 Int_t bc(TMath::Abs(fkESD->GetTOFbc())%2);
531 const Double_t *parR(tin->GetParameter());
532 Double_t dyt(parR[0] - fTracklet->GetYfit(0)), dzt(parR[1] - fTracklet->GetZfit(0)),
533 phit(fTracklet->GetYfit(1)),
534 tilt(fTracklet->GetTilt());
536 // correct for tilt rotation
537 Double_t dy = dyt - dzt*tilt,
539 phit += tilt*parR[3];
540 Double_t dphi = TMath::ASin(parR[2])-TMath::ATan(phit);
546 val[kSpeciesChgRC]= fTracklet->IsRowCross()?0:fSpecies;
547 val[kPt] = GetPtBin(fPt);
550 val[kPrez] = dphi*TMath::RadToDeg();
553 (*DebugStream()) << "trackIn"
554 <<"tracklet.=" << fTracklet
559 if(!HasMCdata()) return NULL; // H->Projection(kEta, kPhi);
560 if(!(H = (THnSparseI*)fContainer->At(kMCtrackIn))) {
561 AliError(Form("Missing container @ %d", Int_t(kMCtrackIn)));
567 Float_t pt0, eta, x0=fTracklet->GetX0(), y0, z0, dydx0, dzdx0;
568 if(!fkMC->GetDirections(x0, y0, z0, dydx0, dzdx0, pt0, eta, s)) return NULL;
569 dyt = y0 - fTracklet->GetYfit(0);
570 dzt = z0 - fTracklet->GetZfit(0);
571 phit= fTracklet->GetYfit(1) + tilt*dzdx0;
572 Float_t phi = TMath::ATan2(y0, x0);
575 dphi= TMath::ASin(dydx0)-TMath::ATan(phit);
577 Int_t pdg = fkMC->GetPDG(),
578 sIdx(AliTRDpidUtil::Pdg2Pid(TMath::Abs(pdg))+1), // species index
580 if(!fDBPDG) fDBPDG=TDatabasePDG::Instance();
581 TParticlePDG *ppdg(fDBPDG->GetParticle(pdg));
582 if(ppdg) sign = ppdg->Charge() > 0. ? 1 : -1;
585 val[kBC] = (bc>=kNbunchCross)?(kNbunchCross-1):bc;
588 val[kSpeciesChgRC]= fTracklet->IsRowCross()?0:sign*(sIdx+1);
589 val[kPt] = GetPtBin(pt0);
592 val[kPrez] = dphi*TMath::RadToDeg();
595 return NULL; //H->Projection(kEta, kPhi);
598 //________________________________________________________
599 TH1* AliTRDresolution::PlotTrackOut(const AliTRDtrackV1 *track)
601 // Store resolution/pulls of Kalman after last update with the TRD information
602 // at the radial position of the first tracklet. The following points are used
604 // - the (y,z,snp) of the first TRD tracklet
605 // - the (y, z, snp, tgl, pt) of the MC track reference
607 // Additionally the momentum resolution/pulls are calculated for usage in the
610 if(track) fkTrack = track;
614 //________________________________________________________
615 TH1* AliTRDresolution::PlotMC(const AliTRDtrackV1 *track)
618 // Plot MC distributions
622 AliDebug(2, "No MC defined. Results will not be available.");
625 if(track) fkTrack = track;
627 AliDebug(4, "No Track defined.");
631 AliWarning("No output container defined.");
634 // retriev track characteristics
635 Int_t pdg = fkMC->GetPDG(),
636 sIdx(AliTRDpidUtil::Pdg2Pid(TMath::Abs(pdg))+1), // species index
639 label(fkMC->GetLabel()),
641 if(!fDBPDG) fDBPDG=TDatabasePDG::Instance();
642 TParticlePDG *ppdg(fDBPDG->GetParticle(pdg));
643 if(ppdg) sign = ppdg->Charge() > 0. ? 1 : -1;
645 TObjArray *arr(NULL);TH1 *h(NULL);
646 AliTRDgeometry *geo(AliTRDinfoGen::Geometry());
647 AliTRDseedV1 *fTracklet(NULL); TObjArray *clInfoArr(NULL);
649 Double_t xAnode, x, y, z, pt, dydx, dzdx, dzdl;
650 Float_t pt0, x0, y0, z0, dx, dy, dz, dydx0, dzdx0;
651 Double_t covR[7]/*, cov[3]*/;
654 // get first detector
656 for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
657 if(!(fTracklet = fkTrack->GetTracklet(ily))) continue;
658 det = fTracklet->GetDetector();
662 TVectorD X(12), Y(12), Z(12), dX(12), dY(12), dZ(12), vPt(12), dPt(12), budget(12), cCOV(12*15);
664 m = fkTrack->GetMass();
665 if(fkMC->PropagateKalman(&X, &Y, &Z, &dX, &dY, &dZ, &vPt, &dPt, &budget, &cCOV, m)){
666 (*DebugStream()) << "MCkalman"
683 for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
684 if(!(fTracklet = fkTrack->GetTracklet(ily)))/* ||
685 !fTracklet->IsOK())*/ continue;
687 sgm[2] = fTracklet->GetDetector();
688 sgm[0] = AliTRDgeometry::GetSector(sgm[2]);
689 sgm[1] = sgm[0] * AliTRDgeometry::kNstack + AliTRDgeometry::GetStack(sgm[2]);
690 Double_t tilt(fTracklet->GetTilt())
693 ,cost(TMath::Sqrt(corr));
694 x0 = fTracklet->GetX0();
695 //radial shift with respect to the MC reference (radial position of the pad plane)
696 x= fTracklet->GetX();
697 Bool_t rc(fTracklet->IsRowCross()); Float_t eta;
698 if(!fkMC->GetDirections(x0, y0, z0, dydx0, dzdx0, pt0, eta, s)) continue;
699 xAnode = fTracklet->GetX0();
701 // MC track position at reference radial position
704 (*DebugStream()) << "MC"
716 Float_t ymc = y0 - dx*dydx0;
717 Float_t zmc = z0 - dx*dzdx0;
718 //p = pt0*TMath::Sqrt(1.+dzdx0*dzdx0); // pt -> p
720 // Kalman position at reference radial position
722 dydx = fTracklet->GetYref(1);
723 dzdx = fTracklet->GetZref(1);
724 dzdl = fTracklet->GetTgl();
725 y = fTracklet->GetYref(0) - dx*dydx;
727 z = fTracklet->GetZref(0) - dx*dzdx;
729 pt = TMath::Abs(fTracklet->GetPt());
730 fTracklet->GetCovRef(covR);
732 arr = (TObjArray*)((TObjArray*)fContainer->At(kMCtrack))->At(ily);
733 // y resolution/pulls
734 if(pt0>fPtThreshold) ((TH3S*)arr->At(0))->Fill(dydx0, dy, sgm[fSegmentLevel]);
735 ((TH3S*)arr->At(1))->Fill(sgm[fSegmentLevel], dy/TMath::Sqrt(covR[0]), dz/TMath::Sqrt(covR[2]));
736 // z resolution/pulls
737 ((TH2S*)arr->At(2))->Fill(dzdx0, dz);
738 ((TH3S*)arr->At(3))->Fill(dzdx0, dz/TMath::Sqrt(covR[2]), 0);
739 // phi resolution/ snp pulls
740 Double_t dtgp = (dydx - dydx0)/(1.- dydx*dydx0);
741 ((TH2I*)arr->At(4))->Fill(dydx0, TMath::ATan(dtgp));
742 Double_t dsnp = dydx/TMath::Sqrt(1.+dydx*dydx) - dydx0/TMath::Sqrt(1.+dydx0*dydx0);
743 ((TH2I*)arr->At(5))->Fill(dydx0, dsnp/TMath::Sqrt(covR[3]));
744 // theta resolution/ tgl pulls
745 Double_t dzdl0 = dzdx0/TMath::Sqrt(1.+dydx0*dydx0),
746 dtgl = (dzdl - dzdl0)/(1.- dzdl*dzdl0);
747 ((TH2I*)arr->At(6))->Fill(dzdl0,
749 ((TH2I*)arr->At(7))->Fill(dzdl0, (dzdl - dzdl0)/TMath::Sqrt(covR[4]));
750 // pt resolution \\ 1/pt pulls \\ p resolution for PID
751 Double_t p0 = TMath::Sqrt(1.+ dzdl0*dzdl0)*pt0,
752 p = TMath::Sqrt(1.+ dzdl*dzdl)*pt;
753 ((TH3S*)((TObjArray*)arr->At(8)))->Fill(pt0, pt/pt0-1., sign*sIdx);
754 ((TH3S*)((TObjArray*)arr->At(9)))->Fill(1./pt0, (1./pt-1./pt0)/TMath::Sqrt(covR[6]), sign*sIdx);
755 ((TH3S*)((TObjArray*)arr->At(10)))->Fill(p0, p/p0-1., sign*sIdx);
757 // Fill Debug stream for Kalman track
759 (*DebugStream()) << "MCtrack"
771 // recalculate tracklet based on the MC info
772 AliTRDseedV1 tt(*fTracklet);
773 tt.SetZref(0, z0 - (x0-xAnode)*dzdx0);
774 tt.SetZref(1, dzdx0);
775 tt.SetReconstructor(AliTRDinfoGen::Reconstructor());
777 x= tt.GetX();y= tt.GetY();z= tt.GetZ();
778 dydx = tt.GetYfit(1);
784 Float_t dphi = (dydx - dydx0);
785 dphi /= (1.- dydx*dydx0);
787 // add tracklet residuals for y and dydx
788 arr = (TObjArray*)fContainer->At(kMCtracklet);
790 if(pt0>fPtThreshold) ((TH3S*)arr->At(0))->Fill(dydx0, dy, sgm[fSegmentLevel]);
791 if(tt.GetS2Y()>0. && tt.GetS2Z()>0.) ((TH3S*)arr->At(1))->Fill(sgm[fSegmentLevel], dy/TMath::Sqrt(tt.GetS2Y()), dz/TMath::Sqrt(tt.GetS2Z()));
792 ((TH3S*)arr->At(2))->Fill(dzdl0, dz, rc);
793 if(tt.GetS2Z()>0.) ((TH3S*)arr->At(3))->Fill(dzdl0, dz/TMath::Sqrt(tt.GetS2Z()), rc);
794 ((TH2I*)arr->At(4))->Fill(dydx0, TMath::ATan(dphi));
796 // Fill Debug stream for tracklet
798 Float_t s2y = tt.GetS2Y();
799 Float_t s2z = tt.GetS2Z();
800 (*DebugStream()) << "MCtracklet"
811 AliTRDpadPlane *pp = geo->GetPadPlane(ily, AliTRDgeometry::GetStack(sgm[2]));
812 Float_t zr0 = pp->GetRow0() + pp->GetAnodeWireOffset();
813 //Double_t exb = AliTRDCommonParam::Instance()->GetOmegaTau(1.5);
815 arr = (TObjArray*)fContainer->At(kMCcluster);
816 AliTRDcluster *c = NULL;
817 tt.ResetClusterIter(kFALSE);
818 while((c = tt.PrevCluster())){
819 Float_t q = TMath::Abs(c->GetQ());
820 x = c->GetX();//+fXcorr[c->GetDetector()][c->GetLocalTimeBin()]; y = c->GetY();z = c->GetZ();
824 dy = cost*(y - ymc - tilt*(z-zmc));
825 dz = cost*(z - zmc + tilt*(y-ymc));
828 if(q>20. && q<250. && pt0>fPtThreshold && c->IsInChamber()){
829 ((TH3S*)arr->At(0))->Fill(dydx0, dy, sgm[fSegmentLevel]);
830 ((TH3S*)arr->At(1))->Fill(sgm[fSegmentLevel], dy/TMath::Sqrt(c->GetSigmaY2()), dz/TMath::Sqrt(c->GetSigmaZ2()));
833 // Fill calibration container
834 Float_t d = zr0 - zmc;
835 d -= ((Int_t)(2 * d)) / 2.0;
836 if (d > 0.25) d = 0.5 - d;
837 AliTRDclusterInfo *clInfo = new AliTRDclusterInfo;
838 clInfo->SetCluster(c);
839 clInfo->SetMC(pdg, label);
840 clInfo->SetGlobalPosition(ymc, zmc, dydx0, dzdx0);
841 clInfo->SetResolution(dy);
842 clInfo->SetAnisochronity(d);
843 clInfo->SetDriftLength(dx);
844 clInfo->SetTilt(tilt);
845 if(fMCcl) fMCcl->Add(clInfo);
846 else AliDebug(1, "MCcl exchange container missing. Activate by calling \"InitExchangeContainers()\"");
849 clInfoArr=new TObjArray(AliTRDseedV1::kNclusters);
850 clInfoArr->SetOwner(kFALSE);
852 clInfoArr->Add(clInfo);
856 if(DebugLevel()>=5 && clInfoArr){
857 (*DebugStream()) << "MCcluster"
858 <<"clInfo.=" << clInfoArr
863 if(clInfoArr) delete clInfoArr;
868 //__________________________________________________________________________
869 Int_t AliTRDresolution::GetPtBin(Float_t pt)
871 // Find pt bin according to local pt segmentation
873 while(ipt<AliTRDresolution::kNpt){
874 if(pt<fgPtBin[ipt+1]) break;
880 //________________________________________________________
881 Float_t AliTRDresolution::GetMeanStat(TH1 *h, Float_t cut, Option_t *opt)
883 // return mean number of entries/bin of histogram "h"
884 // if option "opt" is given the following values are accepted:
885 // "<" : consider only entries less than "cut"
886 // ">" : consider only entries greater than "cut"
888 //Int_t dim(h->GetDimension());
889 Int_t nbx(h->GetNbinsX()), nby(h->GetNbinsY()), nbz(h->GetNbinsZ());
890 Double_t sum(0.); Int_t n(0);
891 for(Int_t ix(1); ix<=nbx; ix++)
892 for(Int_t iy(1); iy<=nby; iy++)
893 for(Int_t iz(1); iz<=nbz; iz++){
894 if(strcmp(opt, "")==0){sum += h->GetBinContent(ix, iy, iz); n++;}
896 if(strcmp(opt, "<")==0) {
897 if(h->GetBinContent(ix, iy, iz)<cut) {sum += h->GetBinContent(ix, iy, iz); n++;}
898 } else if(strcmp(opt, ">")==0){
899 if(h->GetBinContent(ix, iy, iz)>cut) {sum += h->GetBinContent(ix, iy, iz); n++;}
900 } else {sum += h->GetBinContent(ix, iy, iz); n++;}
906 //________________________________________________________
907 Bool_t AliTRDresolution::GetRefFigure(Int_t ifig)
910 // Get the reference figures
914 AliWarning("Please provide a canvas to draw results.");
917 /* Int_t selection[100], n(0), selStart(0); //
918 Int_t ly0(0), dly(5);
919 TList *l(NULL); TVirtualPad *pad(NULL); */
924 AliWarning(Form("Reference plot [%d] missing result", ifig));
929 //________________________________________________________
930 void AliTRDresolution::MakePtSegmentation(Float_t pt0, Float_t dpt)
933 for(Int_t j(0); j<=kNpt; j++){
934 pt0+=(TMath::Exp(j*j*dpt)-1.);
939 //________________________________________________________
940 void AliTRDresolution::MakeSummary()
942 // Build summary plots
945 AliError("Missing results");
948 TVirtualPad *p(NULL); TCanvas *cOut(NULL);
949 TObjArray *arr(NULL); TH2 *h2(NULL);
951 // cluster resolution
953 gStyle->SetPalette(1);
954 const Int_t nClViews(8);
955 const Char_t *vClName[nClViews] = {"HClY", "HClYn", "HClYp", "HClQn", "HClQp", "HClYXTCp", "HClYXTCn", "HClYXPh"};
956 const UChar_t vClOpt[nClViews] = {1, 1, 1, 0, 0, 0, 0, 0};
957 if((arr = (TObjArray*)fProj->At(kCluster))){
958 for(Int_t iview(0); iview<nClViews; iview++){
959 cOut = new TCanvas(Form("TRDsummary%s_Cl%02d", GetName(), iview), "Cluster Resolution", 1024, 768);
960 cOut->Divide(3,2, 1.e-5, 1.e-5);
962 for(Int_t iplot(0); iplot<6; iplot++){
963 p=cOut->cd(iplot+1); p->SetRightMargin(0.1572581);p->SetTopMargin(0.08262712);
964 if(!(h2 = (TH2*)arr->FindObject(Form("%s%d_2D", vClName[iview], iplot)))) continue;
966 if(vClOpt[iview]==0) h2->Draw("colz");
967 else if(vClOpt[iview]==1) DrawSigma(h2, 1.e4, 2.e2, 6.e2, "#sigma(#Deltay) [#mum]");
969 if(nplot) cOut->SaveAs(Form("%s.gif", cOut->GetName()));
974 // tracklet systematic
975 const Int_t nTrkltViews(10);
976 const Char_t *vTrkltName[nTrkltViews] = {"HTrkltY", "HTrkltYn", "HTrkltYp", "HTrkltPhn", "HTrkltPhp", "HTrkltZ", "HTrkltQn", "HTrkltQp", "HTrkltPn", "HTrkltPp"};
977 if((arr = (TObjArray*)fProj->At(kTracklet))){
978 for(Int_t iview(0); iview<nTrkltViews; iview++){
979 cOut = new TCanvas(Form("TRDsummary%s_Trklt%02d", GetName(), iview), "Tracklet Resolution", 1024, 768);
980 cOut->Divide(3,2, 1.e-5, 1.e-5);
982 for(Int_t iplot(0); iplot<6; iplot++){
983 p=cOut->cd(iplot+1); p->SetRightMargin(0.1572581); p->SetTopMargin(0.08262712);
984 if(!(h2 = (TH2*)arr->FindObject(Form("%s%d_2D", vTrkltName[iview], iplot)))) continue;
985 h2->Draw("colz"); nplot++;
987 if(nplot) cOut->SaveAs(Form("%s.gif", cOut->GetName()));
991 // trackIn systematic
992 const Char_t *hname[] = {"HTrkInY", "HTrkInYn", "HTrkInYp", "HTrkInZ", "HTrkInPhn", "HTrkInPhp"};
993 if((arr = (TObjArray*)fProj->At(kTrackIn))){
994 cOut = new TCanvas(Form("TRDsummary%s_TrkIn", GetName()), "Track IN Resolution", 1024, 768);
995 cOut->Divide(3,2, 1.e-5, 1.e-5);
997 for(Int_t iplot(0); iplot<6; iplot++){
998 p=cOut->cd(iplot+1); p->SetRightMargin(0.1572581);p->SetTopMargin(0.08262712);
999 if(!(h2 = (TH2*)arr->FindObject(Form("%s_2D", hname[iplot])))) continue;
1000 h2->Draw("colz"); nplot++;
1002 if(nplot) cOut->SaveAs(Form("%s.gif", cOut->GetName()));
1005 gStyle->SetPalette(1);
1008 //________________________________________________________
1009 void AliTRDresolution::DrawSigma(TH2 *h2, Float_t scale, Float_t m, Float_t M, const Char_t *title)
1011 // Draw error bars scaled with "scale" instead of content values
1012 //use range [m,M] if limits are specified
1015 TH2 *h2e = (TH2F*)h2->Clone(Form("%s_E", h2->GetName()));
1016 h2e->SetContour(10);
1017 if(M>m) h2e->GetZaxis()->SetRangeUser(m, M);
1018 if(title) h2e->GetZaxis()->SetTitle(title);
1020 for(Int_t ix(1); ix<=h2->GetNbinsX(); ix++){
1021 for(Int_t iy(1); iy<=h2->GetNbinsY(); iy++){
1022 if(h2->GetBinContent(ix, iy)<-100.) continue;
1023 Float_t v(scale*h2->GetBinError(ix, iy));
1024 if(M>m && v<m) v=m+TMath::Abs((M-m)*1.e-3);
1025 h2e->SetBinContent(ix, iy, v);
1031 //________________________________________________________
1032 void AliTRDresolution::GetRange(TH2 *h2, Char_t mod, Float_t *range)
1034 // Returns the range of the bulk of data in histogram h2. Removes outliers.
1035 // The "range" vector should be initialized with 2 elements
1036 // Option "mod" can be any of
1037 // - 0 : gaussian like distribution
1038 // - 1 : tailed distribution
1040 Int_t nx(h2->GetNbinsX())
1041 , ny(h2->GetNbinsY())
1043 Double_t *data=new Double_t[n];
1044 for(Int_t ix(1), in(0); ix<=nx; ix++){
1045 for(Int_t iy(1); iy<=ny; iy++)
1046 data[in++] = h2->GetBinContent(ix, iy);
1048 Double_t mean, sigm;
1049 AliMathBase::EvaluateUni(n, data, mean, sigm, Int_t(n*.8));
1051 range[0]=mean-3.*sigm; range[1]=mean+3.*sigm;
1052 if(mod==1) range[0]=TMath::Max(Float_t(1.e-3), range[0]);
1053 AliDebug(2, Form("h[%s] range0[%f %f]", h2->GetName(), range[0], range[1]));
1054 TH1S h1("h1SF0", "", 100, range[0], range[1]);
1059 case 0:// gaussian distribution
1061 TF1 fg("fg", "gaus", mean-3.*sigm, mean+3.*sigm);
1063 mean=fg.GetParameter(1); sigm=fg.GetParameter(2);
1064 range[0] = mean-2.5*sigm;range[1] = mean+2.5*sigm;
1065 AliDebug(2, Form(" rangeG[%f %f]", range[0], range[1]));
1068 case 1:// tailed distribution
1070 Int_t bmax(h1.GetMaximumBin());
1071 Int_t jBinMin(1), jBinMax(100);
1072 for(Int_t ibin(bmax); ibin--;){
1073 if(h1.GetBinContent(ibin)<1.){
1074 jBinMin=ibin; break;
1077 for(Int_t ibin(bmax); ibin++;){
1078 if(h1.GetBinContent(ibin)<1.){
1079 jBinMax=ibin; break;
1082 range[0]=h1.GetBinCenter(jBinMin); range[1]=h1.GetBinCenter(jBinMax);
1083 AliDebug(2, Form(" rangeT[%f %f]", range[0], range[1]));
1092 //________________________________________________________
1093 Bool_t AliTRDresolution::MakeProjectionCluster()
1096 const Int_t kNcontours(9);
1097 const Int_t kNstat(300);
1098 Int_t cidx = kCluster;
1099 if(fProj && fProj->At(cidx)) return kTRUE;
1101 AliError("Missing data container.");
1105 if(!(H = (THnSparse*)fContainer->At(cidx))){
1106 AliError(Form("Missing/Wrong data @ %d.", cidx));
1109 Int_t ndim(H->GetNdimensions());
1110 Int_t coord[kNdim]; memset(coord, 0, sizeof(Int_t) * kNdim); Double_t v = 0.;
1111 TAxis *aa[kNdim], *as(NULL), *apt(NULL); memset(aa, 0, sizeof(TAxis*) * kNdim);
1112 for(Int_t id(0); id<ndim; id++) aa[id] = H->GetAxis(id);
1113 if(ndim > kPt) apt = H->GetAxis(kPt);
1114 if(ndim > kSpeciesChgRC) as = H->GetAxis(kSpeciesChgRC);
1115 // build list of projections
1116 const Int_t nsel(12), npsel(5);
1117 // define rebinning strategy
1118 const Int_t nEtaPhi(4); Int_t rebinEtaPhiX[nEtaPhi] = {1, 2, 5, 1}, rebinEtaPhiY[nEtaPhi] = {2, 1, 1, 5};
1119 AliTRDresolutionProjection hp[fgkNproj[cidx]], *php[nsel][npsel]; memset(php, 0, nsel*npsel*sizeof(AliTRDresolutionProjection*));
1120 Int_t ih(0), isel(-1), np[nsel]; memset(np, 0, nsel*sizeof(Int_t));
1121 for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1122 isel++; // new selection
1123 hp[ih].Build(Form("HClY%d", ily), Form("Clusters :: r-#phi residuals ly%d", ily), kEta, kPhi, kYrez, aa);
1124 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1125 php[isel][np[isel]++] = &hp[ih++];
1126 hp[ih].Build(Form("HClYn%d", ily), Form("Clusters[-]:: r-#phi residuals ly%d", ily), kEta, kPhi, kYrez, aa);
1127 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1128 php[isel][np[isel]++] = &hp[ih++];
1129 hp[ih].Build(Form("HClQn%d", ily), Form("Clusters[-]:: Charge distribution ly%d", ily), kEta, kPhi, kSpeciesChgRC, aa);
1130 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1131 hp[ih].SetShowRange(20., 40.);
1132 php[isel][np[isel]++] = &hp[ih++];
1133 hp[ih].Build(Form("HClYXTCn%d", ily), Form("Clusters[-]:: r-#phi(x,TC) residuals ly%d", ily), kPrez, kZrez, kYrez, aa);
1134 // hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1135 php[isel][np[isel]++] = &hp[ih++];
1136 hp[ih].Build(Form("HClYXPh%d", ily), Form("Clusters :: r-#phi(x,#Phi) residuals ly%d", ily), kPrez, kPt, kYrez, aa);
1137 // hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1138 php[isel][np[isel]++] = &hp[ih++];
1139 isel++; // new selection
1140 php[isel][np[isel]++] = &hp[ih-5]; // relink HClY
1141 hp[ih].Build(Form("HClYp%d", ily), Form("Clusters[+]:: r-#phi residuals ly%d", ily), kEta, kPhi, kYrez, aa);
1142 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1143 php[isel][np[isel]++] = &hp[ih++];
1144 hp[ih].Build(Form("HClQp%d", ily), Form("Clusters[+]:: Charge distribution ly%d", ily), kEta, kPhi, kSpeciesChgRC, aa);
1145 hp[ih].SetShowRange(20., 40.);
1146 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1147 php[isel][np[isel]++] = &hp[ih++];
1148 hp[ih].Build(Form("HClYXTCp%d", ily), Form("Clusters[+]:: r-#phi(x,TC) residuals ly%d", ily), kPrez, kZrez, kYrez, aa);
1149 // hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1150 php[isel][np[isel]++] = &hp[ih++];
1151 php[isel][np[isel]++] = &hp[ih-4]; // relink HClYXPh
1154 Int_t ly(0), ch(0), rcBin(as?as->FindBin(0.):-1), chBin(apt?apt->FindBin(0.):-1);
1155 for (Long64_t ib(0); ib < H->GetNbins(); ib++) {
1156 v = H->GetBinContent(ib, coord); if(v<1.) continue;
1159 if(rcBin>0 && coord[kSpeciesChgRC] == rcBin) continue;
1162 ch = 0; // [-] track
1163 if(chBin>0 && coord[kPt] > chBin) ch = 1; // [+] track
1166 for(Int_t jh(0); jh<np[isel]; jh++) php[isel][jh]->Increment(coord, v);
1170 AliInfo("Building array of projections ...");
1171 fProj = new TObjArray(kNclasses); fProj->SetOwner(kTRUE);
1173 TObjArray *arr(NULL);
1174 fProj->AddAt(arr = new TObjArray(fgkNproj[cidx]), cidx);
1178 if(!hp[ih].fH) continue;
1179 Int_t mid(1), nstat(kNstat);
1180 if(strchr(hp[ih].fH->GetName(), 'Q')){ mid=2; nstat=300;}
1181 if(!(h2 = hp[ih].Projection2D(nstat, kNcontours, mid))) continue;
1188 //________________________________________________________
1189 Bool_t AliTRDresolution::MakeProjectionTracklet()
1192 const Int_t kNcontours(9);
1193 const Int_t kNstat(100);
1194 Int_t cidx = kTracklet;
1195 if(fProj && fProj->At(cidx)) return kTRUE;
1197 AliError("Missing data container.");
1201 if(!(H = (THnSparse*)fContainer->At(cidx))){
1202 AliError(Form("Missing/Wrong data @ %d.", cidx));
1205 Int_t ndim(H->GetNdimensions());
1206 Int_t coord[kNdim+1]; memset(coord, 0, sizeof(Int_t) * (kNdim+1)); Double_t v = 0.;
1207 TAxis *aa[kNdim+1], *as(NULL); memset(aa, 0, sizeof(TAxis*) * (kNdim+1));
1208 for(Int_t id(0); id<ndim; id++) aa[id] = H->GetAxis(id);
1209 if(ndim > kSpeciesChgRC) as = H->GetAxis(kSpeciesChgRC);
1210 // build list of projections
1211 const Int_t nsel(18), npsel(6);
1212 // define rebinning strategy
1213 const Int_t nEtaPhi(4); Int_t rebinEtaPhiX[nEtaPhi] = {1, 2, 5, 1}, rebinEtaPhiY[nEtaPhi] = {2, 1, 1, 5};
1214 AliTRDresolutionProjection hp[fgkNproj[cidx]], *php[nsel][npsel]; memset(php, 0, nsel*npsel*sizeof(AliTRDresolutionProjection*));
1215 Int_t ih(0), isel(-1), np[nsel]; memset(np, 0, nsel*sizeof(Int_t));
1216 for(Int_t ily(0); ily<AliTRDgeometry::kNlayer; ily++){
1217 isel++; // new selection
1218 hp[ih].Build(Form("HTrkltY%d", ily), Form("Tracklets :: r-#phi residuals ly%d", ily), kEta, kPhi, kYrez, aa);
1219 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1220 php[isel][np[isel]++] = &hp[ih++];
1221 hp[ih].Build(Form("HTrkltYn%d", ily), Form("Tracklets[-]:: r-#phi residuals ly%d", ily), kEta, kPhi, kYrez, aa);
1222 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1223 php[isel][np[isel]++] = &hp[ih++];
1224 hp[ih].Build(Form("HTrkltPhn%d", ily), Form("Tracklets[-]:: #Delta#phi residuals ly%d", ily), kEta, kPhi, kPrez, aa);
1225 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1226 php[isel][np[isel]++] = &hp[ih++];
1227 hp[ih].Build(Form("HTrkltPn%d", ily), Form("Tracklets[-]:: Momentum distribution ly%d", ily), kEta, kPhi, kPt, aa);
1228 hp[ih].SetShowRange(6.,12.);
1229 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1230 php[isel][np[isel]++] = &hp[ih++];
1231 hp[ih].Build(Form("HTrkltYPn%d", ily), Form("Tracklets[-]:: r-#phi/p_{t} residuals ly%d", ily), kPt, kPhi, kYrez, aa);
1232 php[isel][np[isel]++] = &hp[ih++];
1233 hp[ih].Build(Form("HTrkltQn%d", ily), Form("Tracklets[-]:: dQdl ly%d", ily), kEta, kPhi, kNdim, aa);
1234 hp[ih].SetShowRange(700.,1100.);
1235 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1236 php[isel][np[isel]++] = &hp[ih++];
1237 isel++; // new selection
1238 php[isel][np[isel]++] = &hp[ih-6]; // relink first histo
1239 hp[ih].Build(Form("HTrkltYp%d", ily), Form("Tracklets[+]:: r-#phi residuals ly%d", ily), kEta, kPhi, kYrez, aa);
1240 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1241 php[isel][np[isel]++] = &hp[ih++];
1242 hp[ih].Build(Form("HTrkltPhp%d", ily), Form("Tracklets[+]:: #Delta#phi residuals ly%d", ily), kEta, kPhi, kPrez, aa);
1243 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1244 php[isel][np[isel]++] = &hp[ih++];
1245 hp[ih].Build(Form("HTrkltPp%d", ily), Form("Tracklets[+]:: Momentum distribution ly%d", ily), kEta, kPhi, kPt, aa);
1246 hp[ih].SetShowRange(6.,12.);
1247 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1248 php[isel][np[isel]++] = &hp[ih++];
1249 hp[ih].Build(Form("HTrkltYPp%d", ily), Form("Tracklets[+]:: r-#phi/p_{t} residuals ly%d", ily), kPt, kPhi, kYrez, aa);
1250 php[isel][np[isel]++] = &hp[ih++];
1251 hp[ih].Build(Form("HTrkltQp%d", ily), Form("Tracklets[+]:: dQdl ly%d", ily), kEta, kPhi, kNdim, aa);
1252 hp[ih].SetShowRange(700.,1100.);
1253 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1254 php[isel][np[isel]++] = &hp[ih++];
1255 isel++; // new selection
1256 hp[ih].Build(Form("HTrkltZ%d", ily), Form("Tracklets[RC]:: z residuals ly%d", ily), kEta, kPhi, kZrez, aa);
1257 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1258 php[isel][np[isel]++] = &hp[ih++];
1261 Int_t ly(0), ch(0), rcBin(as?as->FindBin(0.):-1);
1262 for (Long64_t ib(0); ib < H->GetNbins(); ib++) {
1263 v = H->GetBinContent(ib, coord);
1265 ly = coord[kBC]-1; // layer selection
1267 ch = 0; // [-] track
1268 if(rcBin>0){ // debug mode in which species are also saved
1269 if(coord[kSpeciesChgRC] > rcBin) ch = 1; // [+] track
1270 else if(coord[kSpeciesChgRC] == rcBin) ch = 2; // [RC] track
1273 for(Int_t jh(0); jh<np[isel]; jh++) php[isel][jh]->Increment(coord, v);
1277 AliInfo("Building array of projections ...");
1278 fProj = new TObjArray(kNclasses); fProj->SetOwner(kTRUE);
1280 TObjArray *arr(NULL);
1281 fProj->AddAt(arr = new TObjArray(fgkNproj[cidx]), cidx);
1285 if(!hp[ih].fH) continue;
1286 Int_t mid(0), nstat(kNstat);
1287 if(strchr(hp[ih].fH->GetName(), 'Q')){ mid=2; nstat=300;}
1288 if(!(h2 = hp[ih].Projection2D(nstat, kNcontours, mid))) continue;
1294 //________________________________________________________
1295 Bool_t AliTRDresolution::MakeProjectionTrackIn()
1299 const Int_t kNcontours(9);
1300 const Int_t kNstat(30);
1302 Int_t cidx = kTrackIn;
1303 if(fProj && fProj->At(cidx)) return kTRUE;
1305 AliError("Missing data container.");
1309 if(!(H = (THnSparse*)fContainer->At(cidx))){
1310 AliError(Form("Missing/Wrong data @ %d.", Int_t(cidx)));
1314 Int_t coord[kNdim]; memset(coord, 0, sizeof(Int_t) * kNdim); Double_t v = 0.;
1315 Int_t ndim(H->GetNdimensions());
1316 TAxis *aa[kNdim+1], *as(NULL); memset(aa, 0, sizeof(TAxis*) * (kNdim+1));
1317 for(Int_t id(0); id<ndim; id++) aa[id] = H->GetAxis(id);
1318 if(ndim > kSpeciesChgRC) as = H->GetAxis(kSpeciesChgRC);
1319 // build list of projections
1320 const Int_t nsel(3), npsel(4);
1321 // define rebinning strategy
1322 const Int_t nEtaPhi(4); Int_t rebinEtaPhiX[nEtaPhi] = {1, 2, 5, 1}, rebinEtaPhiY[nEtaPhi] = {2, 1, 1, 5};
1323 const Int_t nPtPhi(2); Int_t rebinPtPhiX[nEtaPhi] = {1, 1}, rebinPtPhiY[nEtaPhi] = {2, 5};
1324 AliTRDresolutionProjection hp[fgkNproj[cidx]], *php[nsel][npsel]; memset(php, 0, nsel*npsel*sizeof(AliTRDresolutionProjection*));
1325 Int_t ih(0), isel(-1), np[nsel]; memset(np, 0, nsel*sizeof(Int_t));
1326 // define list of projections
1327 isel++; // negative tracks
1328 hp[ih].Build("HTrkInY", "TrackIn :: r-#phi residuals", kEta, kPhi, kYrez, aa);
1329 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1330 php[isel][np[isel]++] = &hp[ih++];
1331 hp[ih].Build("HTrkInYn", "TrackIn[-]:: r-#phi residuals", kEta, kPhi, kYrez, aa);
1332 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1333 php[isel][np[isel]++] = &hp[ih++];
1334 hp[ih].Build("HTrkInPhn", "TrackIn[-]:: #Delta#phi residuals", kEta, kPhi, kPrez, aa);
1335 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1336 php[isel][np[isel]++] = &hp[ih++];
1337 hp[ih].Build("HTrkInYPn", "TrackIn[-]:: r-#phi/p_{t} residuals", kPt, kPhi, kYrez, aa);
1338 hp[ih].SetRebinStrategy(nPtPhi, rebinPtPhiX, rebinPtPhiY);
1339 php[isel][np[isel]++] = &hp[ih++];
1340 isel++; // positive tracks
1341 php[isel][np[isel]++] = &hp[ih-4]; // relink first histo
1342 hp[ih].Build("HTrkInYp", "TrackIn[+]:: r-#phi residuals", kEta, kPhi, kYrez, aa);
1343 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1344 php[isel][np[isel]++] = &hp[ih++];
1345 hp[ih].Build("HTrkInPhp", "TrackIn[+]:: #Delta#phi residuals", kEta, kPhi, kPrez, aa);
1346 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1347 php[isel][np[isel]++] = &hp[ih++];
1348 hp[ih].Build("HTrkInYPp", "TrackIn[+]:: r-#phi/p_{t} residuals", kPt, kPhi, kYrez, aa);
1349 hp[ih].SetRebinStrategy(nPtPhi, rebinPtPhiX, rebinPtPhiY);
1350 php[isel][np[isel]++] = &hp[ih++];
1351 isel++; // RC tracks
1352 hp[ih].Build("HTrkInZ", "TrackIn[RC]:: z residuals", kEta, kPhi, kZrez, aa);
1353 hp[ih].SetRebinStrategy(nEtaPhi, rebinEtaPhiX, rebinEtaPhiY);
1354 php[isel][np[isel]++] = &hp[ih++];
1357 Int_t ch(0), rcBin(as?as->FindBin(0.):-1);
1358 for (Long64_t ib(0); ib < H->GetNbins(); ib++) {
1359 v = H->GetBinContent(ib, coord);
1361 if(coord[kBC]>1) continue; // bunch cross cut
1363 ch = 0; // [-] track
1364 if(rcBin>0){ // debug mode in which species are also saved
1365 if(coord[kSpeciesChgRC] > rcBin) ch = 1; // [+] track
1366 else if(coord[kSpeciesChgRC] == rcBin) ch = 2; // [RC] track
1368 for(Int_t jh(0); jh<np[ch]; jh++) php[ch][jh]->Increment(coord, v);
1371 AliInfo("Building array of projections ...");
1372 fProj = new TObjArray(kNclasses); fProj->SetOwner(kTRUE);
1374 TObjArray *arr(NULL);
1375 fProj->AddAt(arr = new TObjArray(fgkNproj[cidx]), cidx);
1379 if(!hp[ih].fH) continue;
1380 if(!(h2 = hp[ih].Projection2D(kNstat, kNcontours/*, mid*/))) continue;
1388 //________________________________________________________
1389 Bool_t AliTRDresolution::PostProcess()
1391 // Fit, Project, Combine, Extract values from the containers filled during execution
1394 AliError("ERROR: list not available");
1400 TF1 fg("fGauss", "gaus", -.5, .5);
1401 // Landau for charge resolution
1402 TF1 fch("fClCh", "landau", 0., 1000.);
1403 // Landau for e+- pt resolution
1404 TF1 fpt("fPt", "landau", -0.1, 0.2);
1406 //PROCESS EXPERIMENTAL DISTRIBUTIONS
1407 // Clusters residuals
1408 if(!MakeProjectionCluster()) return kFALSE;
1410 // Tracklet residual/pulls
1411 if(!MakeProjectionTracklet()) return kFALSE;
1413 // TRDin residual/pulls
1414 if(!MakeProjectionTrackIn()) return kFALSE;
1416 // TRDout residual/pulls
1417 // if(!MakeProjectionTrackOut()) return kFALSE;
1420 if(!HasMCdata()) return kTRUE;
1423 //PROCESS MC RESIDUAL DISTRIBUTIONS
1425 // CLUSTER Y RESOLUTION/PULLS
1426 // if(!MakeProjectionClusterMC()) return kFALSE;
1429 // TRACKLET RESOLUTION/PULLS
1430 // if(!MakeProjectionTrackletMC()) return kFALSE;
1433 // TRACK RESOLUTION/PULLS
1434 /* Process3Darray(kMCtrack, 0, &fg, 1.e4); // y
1435 Process3DlinkedArray(kMCtrack, 1, &fg); // y PULL
1436 Process3Darray(kMCtrack, 2, &fg, 1.e4); // z
1437 Process3Darray(kMCtrack, 3, &fg); // z PULL
1438 Process2Darray(kMCtrack, 4, &fg, 1.e3); // phi
1439 Process2Darray(kMCtrack, 5, &fg); // snp PULL
1440 Process2Darray(kMCtrack, 6, &fg, 1.e3); // theta
1441 Process2Darray(kMCtrack, 7, &fg); // tgl PULL
1442 Process3Darray(kMCtrack, 8, &fg, 1.e2); // pt resolution
1443 Process3Darray(kMCtrack, 9, &fg); // 1/pt pulls
1444 Process3Darray(kMCtrack, 10, &fg, 1.e2); // p resolution*/
1445 // if(!MakeProjectionTrackMC(kMCtrack)) return kFALSE;
1448 // TRACK TRDin RESOLUTION/PULLS
1449 // if(!MakeProjectionTrackMC(kMCtrackIn)) return kFALSE;
1452 // TRACK TRDout RESOLUTION/PULLS
1453 // if(!MakeProjectionTrackMC(kMCtrackOut)) return kFALSE;
1460 //________________________________________________________
1461 void AliTRDresolution::Terminate(Option_t *opt)
1463 AliTRDrecoTask::Terminate(opt);
1464 if(HasPostProcess()) PostProcess();
1467 //________________________________________________________
1468 void AliTRDresolution::AdjustF1(TH1 *h, TF1 *f)
1470 // Helper function to avoid duplication of code
1471 // Make first guesses on the fit parameters
1473 // find the intial parameters of the fit !! (thanks George)
1474 Int_t nbinsy = Int_t(.5*h->GetNbinsX());
1476 for(Int_t jbin=nbinsy-4; jbin<=nbinsy+4; jbin++) sum+=h->GetBinContent(jbin); sum/=9.;
1477 f->SetParLimits(0, 0., 3.*sum);
1478 f->SetParameter(0, .9*sum);
1479 Double_t rms = h->GetRMS();
1480 f->SetParLimits(1, -rms, rms);
1481 f->SetParameter(1, h->GetMean());
1483 f->SetParLimits(2, 0., 2.*rms);
1484 f->SetParameter(2, rms);
1485 if(f->GetNpar() <= 4) return;
1487 f->SetParLimits(3, 0., sum);
1488 f->SetParameter(3, .1*sum);
1490 f->SetParLimits(4, -.3, .3);
1491 f->SetParameter(4, 0.);
1493 f->SetParLimits(5, 0., 1.e2);
1494 f->SetParameter(5, 2.e-1);
1497 //________________________________________________________
1498 TObjArray* AliTRDresolution::BuildMonitorContainerCluster(const char* name, Bool_t expand, Float_t range)
1500 // Build performance histograms for AliTRDcluster.vs TRD track or MC
1501 // - y reziduals/pulls
1503 TObjArray *arr = new TObjArray(2);
1504 arr->SetName(name); arr->SetOwner();
1505 TH1 *h(NULL); char hname[100], htitle[300];
1507 // tracklet resolution/pull in y direction
1508 snprintf(hname, 100, "%s_%s_Y", GetNameId(), name);
1509 snprintf(htitle, 300, "Y res for \"%s\" @ %s;tg(#phi);#Delta y [cm];%s", GetNameId(), name, "Detector");
1510 Float_t rr = range<0.?fDyRange:range;
1511 if(!(h = (TH3S*)gROOT->FindObject(hname))){
1513 if(expand) nybins*=2;
1514 h = new TH3S(hname, htitle,
1515 48, -.48, .48, // phi
1517 nybins, -0.5, nybins-0.5);// segment
1520 snprintf(hname, 100, "%s_%s_YZpull", GetNameId(), name);
1521 snprintf(htitle, 300, "YZ pull for \"%s\" @ %s;%s;#Delta y / #sigma_{y};#Delta z / #sigma_{z}", GetNameId(), name, "Detector");
1522 if(!(h = (TH3S*)gROOT->FindObject(hname))){
1523 h = new TH3S(hname, htitle, 540, -0.5, 540-0.5, 100, -4.5, 4.5, 100, -4.5, 4.5);
1530 //________________________________________________________
1531 TObjArray* AliTRDresolution::BuildMonitorContainerTracklet(const char* name, Bool_t expand)
1533 // Build performance histograms for AliExternalTrackParam.vs TRD tracklet
1534 // - y reziduals/pulls
1535 // - z reziduals/pulls
1537 TObjArray *arr = BuildMonitorContainerCluster(name, expand, 0.05);
1539 TH1 *h(NULL); char hname[100], htitle[300];
1541 // tracklet resolution/pull in z direction
1542 snprintf(hname, 100, "%s_%s_Z", GetNameId(), name);
1543 snprintf(htitle, 300, "Z res for \"%s\" @ %s;tg(#theta);#Delta z [cm]", GetNameId(), name);
1544 if(!(h = (TH2S*)gROOT->FindObject(hname))){
1545 h = new TH2S(hname, htitle, 50, -1., 1., 100, -.05, .05);
1548 snprintf(hname, 100, "%s_%s_Zpull", GetNameId(), name);
1549 snprintf(htitle, 300, "Z pull for \"%s\" @ %s;tg(#theta);#Delta z / #sigma_{z};row cross", GetNameId(), name);
1550 if(!(h = (TH3S*)gROOT->FindObject(hname))){
1551 h = new TH3S(hname, htitle, 50, -1., 1., 100, -5.5, 5.5, 2, -0.5, 1.5);
1552 h->GetZaxis()->SetBinLabel(1, "no RC");
1553 h->GetZaxis()->SetBinLabel(2, "RC");
1557 // tracklet to track phi resolution
1558 snprintf(hname, 100, "%s_%s_PHI", GetNameId(), name);
1559 snprintf(htitle, 300, "#Phi res for \"%s\" @ %s;tg(#phi);#Delta #phi [rad];%s", GetNameId(), name, "Detector");
1561 if(!(h = (TH3S*)gROOT->FindObject(hname))){
1562 h = new TH3S(hname, htitle, 48, -.48, .48, 100, -.5, .5, nsgms, -0.5, nsgms-0.5);
1569 //________________________________________________________
1570 TObjArray* AliTRDresolution::BuildMonitorContainerTrack(const char* name)
1572 // Build performance histograms for AliExternalTrackParam.vs MC
1573 // - y resolution/pulls
1574 // - z resolution/pulls
1575 // - phi resolution, snp pulls
1576 // - theta resolution, tgl pulls
1577 // - pt resolution, 1/pt pulls, p resolution
1579 TObjArray *arr = BuildMonitorContainerTracklet(name);
1581 TH1 *h(NULL); char hname[100], htitle[300];
1585 snprintf(hname, 100, "%s_%s_SNPpull", GetNameId(), name);
1586 snprintf(htitle, 300, "SNP pull for \"%s\" @ %s;tg(#phi);#Delta snp / #sigma_{snp};entries", GetNameId(), name);
1587 if(!(h = (TH2I*)gROOT->FindObject(hname))){
1588 h = new TH2I(hname, htitle, 60, -.3, .3, 100, -4.5, 4.5);
1593 snprintf(hname, 100, "%s_%s_THT", GetNameId(), name);
1594 snprintf(htitle, 300, "#Theta res for \"%s\" @ %s;tg(#theta);#Delta #theta [rad];entries", GetNameId(), name);
1595 if(!(h = (TH2I*)gROOT->FindObject(hname))){
1596 h = new TH2I(hname, htitle, 100, -1., 1., 100, -5e-3, 5e-3);
1600 snprintf(hname, 100, "%s_%s_TGLpull", GetNameId(), name);
1601 snprintf(htitle, 300, "TGL pull for \"%s\" @ %s;tg(#theta);#Delta tgl / #sigma_{tgl};entries", GetNameId(), name);
1602 if(!(h = (TH2I*)gROOT->FindObject(hname))){
1603 h = new TH2I(hname, htitle, 100, -1., 1., 100, -4.5, 4.5);
1607 const Int_t kNdpt(150);
1608 const Int_t kNspc = 2*AliPID::kSPECIES+1;
1609 Float_t lPt=0.1, lDPt=-.1, lSpc=-5.5;
1610 Float_t binsPt[kNpt+1], binsSpc[kNspc+1], binsDPt[kNdpt+1];
1611 for(Int_t i=0;i<kNpt+1; i++,lPt=TMath::Exp(i*.15)-1.) binsPt[i]=lPt;
1612 for(Int_t i=0; i<kNspc+1; i++,lSpc+=1.) binsSpc[i]=lSpc;
1613 for(Int_t i=0; i<kNdpt+1; i++,lDPt+=2.e-3) binsDPt[i]=lDPt;
1616 snprintf(hname, 100, "%s_%s_Pt", GetNameId(), name);
1617 snprintf(htitle, 300, "#splitline{P_{t} res for}{\"%s\" @ %s};p_{t} [GeV/c];#Delta p_{t}/p_{t}^{MC};SPECIES", GetNameId(), name);
1618 if(!(h = (TH3S*)gROOT->FindObject(hname))){
1619 h = new TH3S(hname, htitle,
1620 kNpt, binsPt, kNdpt, binsDPt, kNspc, binsSpc);
1621 //ax = h->GetZaxis();
1622 //for(Int_t ib(1); ib<=ax->GetNbins(); ib++) ax->SetBinLabel(ib, fgParticle[ib-1]);
1626 snprintf(hname, 100, "%s_%s_1Pt", GetNameId(), name);
1627 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);
1628 if(!(h = (TH3S*)gROOT->FindObject(hname))){
1629 h = new TH3S(hname, htitle,
1630 kNpt, 0., 2., 100, -4., 4., kNspc, -5.5, 5.5);
1631 //ax = h->GetZaxis();
1632 //for(Int_t ib(1); ib<=ax->GetNbins(); ib++) ax->SetBinLabel(ib, fgParticle[ib-1]);
1636 snprintf(hname, 100, "%s_%s_P", GetNameId(), name);
1637 snprintf(htitle, 300, "P res for \"%s\" @ %s;p [GeV/c];#Delta p/p^{MC};SPECIES", GetNameId(), name);
1638 if(!(h = (TH3S*)gROOT->FindObject(hname))){
1639 h = new TH3S(hname, htitle,
1640 kNpt, binsPt, kNdpt, binsDPt, kNspc, binsSpc);
1641 //ax = h->GetZaxis();
1642 //for(Int_t ib(1); ib<=ax->GetNbins(); ib++) ax->SetBinLabel(ib, fgParticle[ib-1]);
1650 //________________________________________________________
1651 TObjArray* AliTRDresolution::Histos()
1654 // Define histograms
1657 if(fContainer) return fContainer;
1659 fContainer = new TObjArray(kNclasses); fContainer->SetOwner(kTRUE);
1661 const Int_t nhn(100); Char_t hn[nhn]; TString st;
1663 //++++++++++++++++++++++
1664 // cluster to tracklet residuals/pulls
1665 snprintf(hn, nhn, "h%s", fgPerformanceName[kCluster]);
1666 if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
1667 const Char_t *clTitle[kNdim] = {"layer", fgkTitle[kPhi], fgkTitle[kEta], fgkTitle[kYrez], "#Deltax [cm]", "Q</Q", "Q/angle", "#Phi [deg]"};
1668 const Int_t clNbins[kNdim] = {AliTRDgeometry::kNlayer, fgkNbins[kPhi], fgkNbins[kEta], fgkNbins[kYrez], 33, 10, 30, 15};
1669 const Double_t clMin[kNdim] = {-0.5, fgkMin[kPhi], fgkMin[kEta], fgkMin[kYrez]/10., 0., 0.1, -2., -45},
1670 clMax[kNdim] = {AliTRDgeometry::kNlayer-0.5, fgkMax[kPhi], fgkMax[kEta], fgkMax[kYrez]/10., 3.3, 2.1, 118., 45};
1671 st = "cluster spatial&charge resolution;";
1672 // define minimum info to be saved in non debug mode
1673 Int_t ndim=DebugLevel()>=1?kNdim:4;
1674 for(Int_t idim(0); idim<ndim; idim++){ st += clTitle[idim]; st+=";";}
1675 H = new THnSparseI(hn, st.Data(), ndim, clNbins, clMin, clMax);
1677 fContainer->AddAt(H, kCluster);
1678 //++++++++++++++++++++++
1679 // tracklet to TRD track
1680 snprintf(hn, nhn, "h%s", fgPerformanceName[kTracklet]);
1681 if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
1682 Char_t *trTitle[kNdim+1]; memcpy(trTitle, fgkTitle, kNdim*sizeof(Char_t*));
1683 Int_t trNbins[kNdim+1]; memcpy(trNbins, fgkNbins, kNdim*sizeof(Int_t));
1684 Double_t trMin[kNdim+1]; memcpy(trMin, fgkMin, kNdim*sizeof(Double_t));
1685 Double_t trMax[kNdim+1]; memcpy(trMax, fgkMax, kNdim*sizeof(Double_t));
1686 // set specific fields
1687 trTitle[kBC]=StrDup("layer"); trNbins[kBC] = AliTRDgeometry::kNlayer; trMin[kBC] = -0.5; trMax[kBC] = AliTRDgeometry::kNlayer-0.5;
1688 trTitle[kNdim]=StrDup("dq/dl [a.u.]"); trNbins[kNdim] = 30; trMin[kNdim] = 100.; trMax[kNdim] = 3100;
1690 st = "tracklet spatial&charge resolution;";
1691 // define minimum info to be saved in non debug mode
1692 Int_t ndim=DebugLevel()>=1?(kNdim+1):4;
1693 for(Int_t idim(0); idim<ndim; idim++){ st += trTitle[idim]; st+=";";}
1694 H = new THnSparseI(hn, st.Data(), ndim, trNbins, trMin, trMax);
1696 fContainer->AddAt(H, kTracklet);
1697 //++++++++++++++++++++++
1698 // tracklet to TRDin
1699 snprintf(hn, nhn, "h%s", fgPerformanceName[kTrackIn]);
1700 if(!(H = (THnSparseI*)gROOT->FindObject(hn))){
1701 st = "r-#phi/z/angular residuals @ TRD entry;";
1702 // define minimum info to be saved in non debug mode
1703 Int_t ndim=DebugLevel()>=1?kNdim:7;
1704 for(Int_t idim(0); idim<ndim; idim++){ st += fgkTitle[idim]; st+=";";}
1705 H = new THnSparseI(hn, st.Data(), ndim, fgkNbins, fgkMin, fgkMax);
1707 fContainer->AddAt(H, kTrackIn);
1708 // tracklet to TRDout
1709 // fContainer->AddAt(BuildMonitorContainerTracklet("TrkOUT"), kTrackOut);
1712 // Resolution histos
1713 if(!HasMCdata()) return fContainer;
1715 // cluster resolution
1716 fContainer->AddAt(BuildMonitorContainerCluster("MCcl"), kMCcluster);
1718 // tracklet resolution
1719 fContainer->AddAt(BuildMonitorContainerTracklet("MCtracklet"), kMCtracklet);
1722 TObjArray *arr(NULL);
1723 fContainer->AddAt(arr = new TObjArray(AliTRDgeometry::kNlayer), kMCtrack);
1724 arr->SetName("MCtrk");
1725 for(Int_t il(0); il<AliTRDgeometry::kNlayer; il++) arr->AddAt(BuildMonitorContainerTrack(Form("MCtrk_Ly%d", il)), il);
1727 // TRDin TRACK RESOLUTION
1728 fContainer->AddAt(H, kMCtrackIn);
1730 // TRDout TRACK RESOLUTION
1731 fContainer->AddAt(BuildMonitorContainerTrack("MCtrkOUT"), kMCtrackOut);
1736 //________________________________________________________
1737 Bool_t AliTRDresolution::Process(TH2* const h2, TGraphErrors **g, Int_t stat)
1739 // Robust function to process sigma/mean for 2D plot dy(x)
1740 // For each x bin a gauss fit is performed on the y projection and the range
1741 // with the minimum chi2/ndf is choosen
1744 if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>0) printf("D-AliTRDresolution::Process() : NULL pointer input container.\n");
1747 if(!Int_t(h2->GetEntries())){
1748 if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>0) printf("D-AliTRDresolution::Process() : Empty h[%s - %s].\n", h2->GetName(), h2->GetTitle());
1751 if(!g || !g[0]|| !g[1]) {
1752 if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>0) printf("D-AliTRDresolution::Process() : NULL pointer output container.\n");
1756 TAxis *ax(h2->GetXaxis()), *ay(h2->GetYaxis());
1757 Float_t ymin(ay->GetXmin()), ymax(ay->GetXmax()), dy(ay->GetBinWidth(1)), y0(0.), y1(0.);
1758 TF1 f("f", "gaus", ymin, ymax);
1760 if((n=g[0]->GetN())) for(;n--;) g[0]->RemovePoint(n);
1761 if((n=g[1]->GetN())) for(;n--;) g[1]->RemovePoint(n);
1763 if((h=(TH1D*)gROOT->FindObject("py"))) delete h;
1764 Double_t x(0.), y(0.), ex(0.), ey(0.), sy(0.), esy(0.);
1768 Float_t chi2OverNdf(0.);
1769 for(Int_t ix = 1, np=0; ix<=ax->GetNbins(); ix++){
1770 x = ax->GetBinCenter(ix); ex= ax->GetBinWidth(ix)*0.288; // w/sqrt(12)
1771 ymin = ay->GetXmin(); ymax = ay->GetXmax();
1773 h = h2->ProjectionY("py", ix, ix);
1774 if((n=(Int_t)h->GetEntries())<stat){
1775 if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>1) printf("I-AliTRDresolution::Process() : Low statistics @ x[%f] stat[%d]=%d [%d].\n", x, ix, n, stat);
1778 // looking for a first order mean value
1779 f.SetParameter(1, 0.); f.SetParameter(2, 3.e-2);
1781 chi2OverNdf = f.GetChisquare()/f.GetNDF();
1782 printf("x[%f] range[%f %f] chi2[%f] ndf[%d] chi2/ndf[%f]\n", x, ymin, ymax, f.GetChisquare(),f.GetNDF(),chi2OverNdf);
1783 y = f.GetParameter(1); y0 = y-4*dy; y1 = y+4*dy;
1784 ey = f.GetParError(1);
1785 sy = f.GetParameter(2); esy = f.GetParError(2);
1786 // // looking for the best chi2/ndf value
1787 // while(ymin<y0 && ymax>y1){
1788 // f.SetParameter(1, y);
1789 // f.SetParameter(2, sy);
1790 // h->Fit(&f, "QNW", "", y0, y1);
1791 // printf(" range[%f %f] chi2[%f] ndf[%d] chi2/ndf[%f]\n", y0, y1, f.GetChisquare(),f.GetNDF(),f.GetChisquare()/f.GetNDF());
1792 // if(f.GetChisquare()/f.GetNDF() < Chi2OverNdf){
1793 // chi2OverNdf = f.GetChisquare()/f.GetNDF();
1794 // y = f.GetParameter(1); ey = f.GetParError(1);
1795 // sy = f.GetParameter(2); esy = f.GetParError(2);
1796 // printf(" set y[%f] sy[%f] chi2/ndf[%f]\n", y, sy, chi2OverNdf);
1800 g[0]->SetPoint(np, x, y);
1801 g[0]->SetPointError(np, ex, ey);
1802 g[1]->SetPoint(np, x, sy);
1803 g[1]->SetPointError(np, ex, esy);
1810 //________________________________________________________
1811 Bool_t AliTRDresolution::Process(TH2 * const h2, TF1 *f, Float_t k, TGraphErrors **g)
1814 // Do the processing
1817 Char_t pn[10]; snprintf(pn, 10, "p%03d", fIdxPlot);
1819 if((n=g[0]->GetN())) for(;n--;) g[0]->RemovePoint(n);
1820 if((n=g[1]->GetN())) for(;n--;) g[1]->RemovePoint(n);
1821 if(Int_t(h2->GetEntries())){
1822 AliDebug(4, Form("%s: g[%s %s]", pn, g[0]->GetName(), g[0]->GetTitle()));
1824 AliDebug(2, Form("%s: g[%s %s]: Missing entries.", pn, g[0]->GetName(), g[0]->GetTitle()));
1829 const Int_t kINTEGRAL=1;
1830 for(Int_t ibin = 0; ibin < Int_t(h2->GetNbinsX()/kINTEGRAL); ibin++){
1831 Int_t abin(ibin*kINTEGRAL+1),bbin(abin+kINTEGRAL-1),mbin(abin+Int_t(kINTEGRAL/2));
1832 Double_t x = h2->GetXaxis()->GetBinCenter(mbin);
1833 TH1D *h = h2->ProjectionY(pn, abin, bbin);
1834 if((n=(Int_t)h->GetEntries())<150){
1835 AliDebug(4, Form(" x[%f] range[%d %d] stat[%d] low statistics !", x, abin, bbin, n));
1839 Int_t ip = g[0]->GetN();
1840 AliDebug(4, Form(" x_%d[%f] range[%d %d] stat[%d] M[%f] Sgm[%f]", ip, x, abin, bbin, n, f->GetParameter(1), f->GetParameter(2)));
1841 g[0]->SetPoint(ip, x, k*f->GetParameter(1));
1842 g[0]->SetPointError(ip, 0., k*f->GetParError(1));
1843 g[1]->SetPoint(ip, x, k*f->GetParameter(2));
1844 g[1]->SetPointError(ip, 0., k*f->GetParError(2));
1846 g[0]->SetPoint(ip, x, k*h->GetMean());
1847 g[0]->SetPointError(ip, 0., k*h->GetMeanError());
1848 g[1]->SetPoint(ip, x, k*h->GetRMS());
1849 g[1]->SetPointError(ip, 0., k*h->GetRMSError());*/
1856 //____________________________________________________________________
1857 Bool_t AliTRDresolution::FitTrack(const Int_t np, AliTrackPoint *points, Float_t param[10])
1860 // Fit track with a staight line using the "np" clusters stored in the array "points".
1861 // The following particularities are stored in the clusters from points:
1862 // 1. pad tilt as cluster charge
1863 // 2. pad row cross or vertex constrain as fake cluster with cluster type 1
1864 // The parameters of the straight line fit are stored in the array "param" in the following order :
1865 // param[0] - x0 reference radial position
1866 // param[1] - y0 reference r-phi position @ x0
1867 // param[2] - z0 reference z position @ x0
1868 // param[3] - slope dy/dx
1869 // param[4] - slope dz/dx
1872 // Function should be used to refit tracks for B=0T
1876 if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>1) printf("D-AliTRDresolution::FitTrack: Not enough clusters to fit a track [%d].\n", np);
1879 TLinearFitter yfitter(2, "pol1"), zfitter(2, "pol1");
1882 for(Int_t ip(0); ip<np; ip++) x0+=points[ip].GetX();
1885 Double_t x, y, z, dx, tilt(0.);
1886 for(Int_t ip(0); ip<np; ip++){
1887 x = points[ip].GetX(); z = points[ip].GetZ();
1889 zfitter.AddPoint(&dx, z, points[ip].GetClusterType()?1.e-3:1.);
1891 if(zfitter.Eval() != 0) return kFALSE;
1893 Double_t z0 = zfitter.GetParameter(0);
1894 Double_t dzdx = zfitter.GetParameter(1);
1895 for(Int_t ip(0); ip<np; ip++){
1896 if(points[ip].GetClusterType()) continue;
1897 x = points[ip].GetX();
1899 y = points[ip].GetY();
1900 z = points[ip].GetZ();
1901 tilt = points[ip].GetCharge();
1902 y -= tilt*(-dzdx*dx + z - z0);
1903 Float_t xyz[3] = {x, y, z}; points[ip].SetXYZ(xyz);
1904 yfitter.AddPoint(&dx, y, 1.);
1906 if(yfitter.Eval() != 0) return kFALSE;
1907 Double_t y0 = yfitter.GetParameter(0);
1908 Double_t dydx = yfitter.GetParameter(1);
1910 param[0] = x0; param[1] = y0; param[2] = z0; param[3] = dydx; param[4] = dzdx;
1911 if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>3) printf("D-AliTRDresolution::FitTrack: x0[%f] y0[%f] z0[%f] dydx[%f] dzdx[%f].\n", x0, y0, z0, dydx, dzdx);
1915 //____________________________________________________________________
1916 Bool_t AliTRDresolution::FitTracklet(const Int_t ly, const Int_t np, const AliTrackPoint *points, const Float_t param[10], Float_t par[3])
1919 // Fit tracklet with a staight line using the coresponding subset of clusters out of the total "np" clusters stored in the array "points".
1920 // See function FitTrack for the data stored in the "clusters" array
1922 // The parameters of the straight line fit are stored in the array "param" in the following order :
1923 // par[0] - x0 reference radial position
1924 // par[1] - y0 reference r-phi position @ x0
1925 // par[2] - slope dy/dx
1928 // Function should be used to refit tracks for B=0T
1931 TLinearFitter yfitter(2, "pol1");
1933 // grep data for tracklet
1934 Double_t x0(0.), x[60], y[60], dy[60];
1936 for(Int_t ip(0); ip<np; ip++){
1937 if(points[ip].GetClusterType()) continue;
1938 if(points[ip].GetVolumeID() != ly) continue;
1939 Float_t xt(points[ip].GetX())
1940 ,yt(param[1] + param[3] * (xt - param[0]));
1942 y[nly] = points[ip].GetY();
1948 if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>1) printf("D-AliTRDresolution::FitTracklet: Not enough clusters to fit a tracklet [%d].\n", nly);
1951 // set radial reference for fit
1954 // find tracklet core
1955 Double_t mean(0.), sig(1.e3);
1956 AliMathBase::EvaluateUni(nly, dy, mean, sig, 0);
1958 // simple cluster error parameterization
1959 Float_t kSigCut = TMath::Sqrt(5.e-4 + param[3]*param[3]*0.018);
1961 // fit tracklet core
1962 for(Int_t jly(0); jly<nly; jly++){
1963 if(TMath::Abs(dy[jly]-mean)>kSigCut) continue;
1964 Double_t dx(x[jly]-x0);
1965 yfitter.AddPoint(&dx, y[jly], 1.);
1967 if(yfitter.Eval() != 0) return kFALSE;
1969 par[1] = yfitter.GetParameter(0);
1970 par[2] = yfitter.GetParameter(1);
1974 //____________________________________________________________________
1975 Bool_t AliTRDresolution::UseTrack(const Int_t np, const AliTrackPoint *points, Float_t param[10])
1978 // Global selection mechanism of tracksbased on cluster to fit residuals
1979 // The parameters are the same as used ni function FitTrack().
1981 const Float_t kS(0.6), kM(0.2);
1982 TH1S h("h1", "", 100, -5.*kS, 5.*kS);
1983 Float_t dy, dz, s, m;
1984 for(Int_t ip(0); ip<np; ip++){
1985 if(points[ip].GetClusterType()) continue;
1986 Float_t x0(points[ip].GetX())
1987 ,y0(param[1] + param[3] * (x0 - param[0]))
1988 ,z0(param[2] + param[4] * (x0 - param[0]));
1989 dy=points[ip].GetY() - y0; h.Fill(dy);
1990 dz=points[ip].GetZ() - z0;
1992 TF1 fg("fg", "gaus", -5.*kS, 5.*kS);
1993 fg.SetParameter(1, 0.);
1994 fg.SetParameter(2, 2.e-2);
1996 m=fg.GetParameter(1); s=fg.GetParameter(2);
1997 if(s>kS || TMath::Abs(m)>kM) return kFALSE;
2001 //________________________________________________________
2002 void AliTRDresolution::GetLandauMpvFwhm(TF1 * const f, Float_t &mpv, Float_t &xm, Float_t &xM)
2005 // Get the most probable value and the full width half mean
2006 // of a Landau distribution
2009 const Float_t dx = 1.;
2010 mpv = f->GetParameter(1);
2011 Float_t fx, max = f->Eval(mpv);
2014 while((fx = f->Eval(xm))>.5*max){
2023 while((fx = f->Eval(xM))>.5*max) xM += dx;
2027 // #include "TFile.h"
2028 // //________________________________________________________
2029 // Bool_t AliTRDresolution::LoadCorrection(const Char_t *file)
2032 // AliWarning("Use cluster position as in reconstruction.");
2033 // SetLoadCorrection();
2036 // TDirectory *cwd(gDirectory);
2037 // TString fileList;
2038 // FILE *filePtr = fopen(file, "rt");
2040 // AliWarning(Form("Couldn't open correction list \"%s\". Use cluster position as in reconstruction.", file));
2041 // SetLoadCorrection();
2044 // TH2 *h2 = new TH2F("h2", ";time [time bins];detector;dx [#mum]", 30, -0.5, 29.5, AliTRDgeometry::kNdet, -0.5, AliTRDgeometry::kNdet-0.5);
2045 // while(fileList.Gets(filePtr)){
2046 // if(!TFile::Open(fileList.Data())) {
2047 // AliWarning(Form("Couldn't open \"%s\"", fileList.Data()));
2049 // } else AliInfo(Form("\"%s\"", fileList.Data()));
2051 // TTree *tSys = (TTree*)gFile->Get("tSys");
2052 // h2->SetDirectory(gDirectory); h2->Reset("ICE");
2053 // tSys->Draw("det:t>>h2", "dx", "goff");
2054 // for(Int_t idet(0); idet<AliTRDgeometry::kNdet; idet++){
2055 // for(Int_t it(0); it<30; it++) fXcorr[idet][it]+=(1.e-4*h2->GetBinContent(it+1, idet+1));
2057 // h2->SetDirectory(cwd);
2062 // if(AliLog::GetDebugLevel("PWG1", "AliTRDresolution")>=2){
2063 // for(Int_t il(0); il<184; il++) printf("-"); printf("\n");
2064 // printf("DET|");for(Int_t it(0); it<30; it++) printf(" tb%02d|", it); printf("\n");
2065 // for(Int_t il(0); il<184; il++) printf("-"); printf("\n");
2066 // FILE *fout = fopen("TRD.ClusterCorrection.txt", "at");
2067 // fprintf(fout, " static const Double_t dx[AliTRDgeometry::kNdet][30]={\n");
2068 // for(Int_t idet(0); idet<AliTRDgeometry::kNdet; idet++){
2069 // printf("%03d|", idet);
2070 // fprintf(fout, " {");
2071 // for(Int_t it(0); it<30; it++){
2072 // printf("%+5.0f|", 1.e4*fXcorr[idet][it]);
2073 // fprintf(fout, "%+6.4f%c", fXcorr[idet][it], it==29?' ':',');
2076 // fprintf(fout, "}%c\n", idet==AliTRDgeometry::kNdet-1?' ':',');
2078 // fprintf(fout, " };\n");
2080 // SetLoadCorrection();
2084 //________________________________________________________
2085 AliTRDresolution::AliTRDresolutionProjection::AliTRDresolutionProjection()
2092 memset(fAx, 0, 3*sizeof(Int_t));
2093 memset(fRange, 0, 4*sizeof(Float_t));
2096 //________________________________________________________
2097 AliTRDresolution::AliTRDresolutionProjection::~AliTRDresolutionProjection()
2103 //________________________________________________________
2104 void AliTRDresolution::AliTRDresolutionProjection::Build(const Char_t *n, const Char_t *t, Int_t ix, Int_t iy, Int_t iz, TAxis *aa[])
2106 // check and build (if neccessary) projection determined by axis "ix", "iy" and "iz"
2107 if(!aa[ix] || !aa[iy] || !aa[iz]) return;
2108 TAxis *ax(aa[ix]), *ay(aa[iy]), *az(aa[iz]);
2109 fH = new TH3I(n, Form("%s;%s;%s;%s", t, ax->GetTitle(), ay->GetTitle(), az->GetTitle()),
2110 ax->GetNbins(), ax->GetXmin(), ax->GetXmax(),
2111 ay->GetNbins(), ay->GetXmin(), ay->GetXmax(),
2112 az->GetNbins(), az->GetXmin(), az->GetXmax());
2113 fAx[0] = ix; fAx[1] = iy; fAx[2] = iz;
2114 fRange[0] = az->GetXmin()/3.; fRange[1] = az->GetXmax()/3.;
2117 //________________________________________________________
2118 void AliTRDresolution::AliTRDresolutionProjection::Increment(Int_t bin[], Double_t v)
2120 // increment bin with value "v" pointed by general coord in "bin"
2123 fH->GetBin(bin[fAx[0]],bin[fAx[1]],bin[fAx[2]]), v);
2126 //________________________________________________________
2127 TH2* AliTRDresolution::AliTRDresolutionProjection::Projection2D(const Int_t nstat, const Int_t ncol, const Int_t mid)
2129 // build the 2D projection and adjust binning
2131 const Char_t *title[] = {"Mean", "#mu", "MPV"};
2132 if(!fH) return NULL;
2133 TAxis *ax(fH->GetXaxis()), *ay(fH->GetYaxis()), *az(fH->GetZaxis());
2134 TH2 *h2s = (TH2*)fH->Project3D("yx");
2135 Int_t irebin(0), dxBin(1), dyBin(1);
2136 while(irebin<fNrebin && (AliTRDresolution::GetMeanStat(h2s, .5, ">")<nstat)){
2137 h2s->Rebin2D(fRebinX[irebin], fRebinY[irebin]);
2138 dxBin*=fRebinX[irebin];dyBin*=fRebinY[irebin];
2141 Int_t nx(h2s->GetNbinsX()), ny(h2s->GetNbinsY());
2146 Float_t dz=(fRange[1]-fRange[1])/ncol;
2147 TString titlez(az->GetTitle()); TObjArray *tokenTitle(titlez.Tokenize(" "));
2148 TH2 *h2 = new TH2F(Form("%s_2D", fH->GetName()),
2149 Form("%s;%s;%s;%s(%s) %s", fH->GetTitle(), ax->GetTitle(), ay->GetTitle(), title[mid], (*tokenTitle)[0]->GetName(), tokenTitle->GetEntriesFast()>1?(*tokenTitle)[1]->GetName():""),
2150 nx, ax->GetXmin(), ax->GetXmax(), ny, ay->GetXmin(), ay->GetXmax());
2151 h2->SetContour(ncol);
2152 h2->GetZaxis()->CenterTitle();
2153 h2->GetZaxis()->SetRangeUser(fRange[0], fRange[1]);
2154 //printf("%s[%s] nx[%d] ny[%d]\n", h2->GetName(), h2->GetTitle(), nx, ny);
2155 for(Int_t iy(0); iy<ny; iy++){
2156 for(Int_t ix(0); ix<nx; ix++){
2157 h = fH->ProjectionZ(Form("%s_z", h2->GetName()), ix*dxBin+1, (ix+1)*dxBin+1, iy*dyBin+1, (iy+1)*dyBin+1);
2158 Int_t ne((Int_t)h->Integral());
2160 h2->SetBinContent(ix+1, iy+1, -999);
2161 h2->SetBinError(ix+1, iy+1, 1.);
2163 Float_t v(h->GetMean()), ve(h->GetRMS());
2165 TF1 fg("fg", "gaus", az->GetXmin(), az->GetXmax());
2166 fg.SetParameter(0, Float_t(ne)); fg.SetParameter(1, v); fg.SetParameter(2, ve);
2168 v = fg.GetParameter(1); ve = fg.GetParameter(2);
2169 } else if (mid==2) {
2170 TF1 fl("fl", "landau", az->GetXmin(), az->GetXmax());
2171 fl.SetParameter(0, Float_t(ne)); fl.SetParameter(1, v); fl.SetParameter(2, ve);
2173 v = fl.GetMaximumX(); ve = fl.GetParameter(2);
2174 /* TF1 fgle("gle", "[0]*TMath::Landau(x, [1], [2], 1)*TMath::Exp(-[3]*x/[1])", az->GetXmin(), az->GetXmax());
2175 fgle.SetParameter(0, fl.GetParameter(0));
2176 fgle.SetParameter(1, fl.GetParameter(1));
2177 fgle.SetParameter(2, fl.GetParameter(2));
2178 fgle.SetParameter(3, 1.);fgle.SetParLimits(3, 0., 5.);
2179 h->Fit(&fgle, "WQ");
2180 v = fgle.GetMaximumX(); ve = fgle.GetParameter(2);*/
2182 if(v<fRange[0]) h2->SetBinContent(ix+1, iy+1, fRange[0]+0.1*dz);
2183 else h2->SetBinContent(ix+1, iy+1, v);
2184 h2->SetBinError(ix+1, iy+1, ve);
2192 void AliTRDresolution::AliTRDresolutionProjection::SetRebinStrategy(Int_t n, Int_t rebx[], Int_t reby[])
2194 // define rebinning strategy for this projection
2196 fRebinX = new Int_t[n]; memcpy(fRebinX, rebx, n*sizeof(Int_t));
2197 fRebinY = new Int_t[n]; memcpy(fRebinY, reby, n*sizeof(Int_t));