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: AliTRDclusterResolution.cxx */
18 ///////////////////////////////////////////////////////////////////////////////
20 // TRD cluster error parameterization //
22 // This class is designed to produce the reference plots for a detailed study//
23 // and parameterization of TRD cluster errors. The following effects are taken//
25 // - dependence with the total charge of the cluster //
26 // - dependence with the distance from the center pad. This is monitored
27 // for each layer individually since the pad size varies with layer
28 // - dependence with the drift length - here the influence of anisochronity
29 // and diffusion are searched
30 // - dependence with the distance to the anode wire - anisochronity effects
31 // - dependence with track angle (for y resolution)
32 // The correlation between effects is taken into account.
34 // Since magnetic field plays a very important role in the TRD measurement
35 // the ExB correction is forced by the setter function SetExB(Int_t). The
36 // argument is the detector index, if none is specified all will be
39 // Two cases are of big importance.
40 // - comparison with MC
41 // - comparison with Kalman fit. In this case the covariance matrix of the
42 // Kalman fit are needed.
44 // The functionalities implemented in this class are based on the storage
45 // class AliTRDclusterInfo.
50 // The method to disentangle s_y and s_x is based on the relation (see also fig.)
52 // #sigma^{2} = #sigma^{2}_{y} + tg^{2}(#alpha_{L})*#sigma^{2}_{x_{d}} + tg^{2}(#phi-#alpha_{L})*(#sigma^{2}_{x_{d}}+#sigma^{2}_{x_{c}})
56 // #sigma^{2}_{x_{c}} #approx 0
58 // we suppose the chamber is well calibrated for t_{0} and aligned in
61 // Clusters can be radially shifted due to three causes:
62 // - globally shifted - due to residual misalignment/miscalibration(t0)
63 // - locally shifted - due to different local drift velocity from the mean
64 // - randomly shifted - due to neighboring (radial direction) clusters
65 // charge induced by asymmetry of the TRF.
67 // We estimate this effects by the relations:
69 // #mu_{y} = tg(#alpha_{L})*#Delta x_{d}(...) + tg(#phi-#alpha_{L})*(#Delta x_{c}(...) + #Delta x_{d}(...))
73 // #Delta x_{d}(...) = (<v_{d}> + #delta v_{d}(x_{d}, d)) * (t + t^{*}(Q))
75 // and we specified explicitely the variation of drift velocity parallel
76 // with the track (x_{d}) and perpendicular to it due to anisochronity (d).
78 // For estimating the contribution from asymmetry of TRF the following
79 // parameterization is being used
81 // t^{*}(Q) = #delta_{0} * #frac{Q_{t+1} - Q_{t-1}}{Q_{t-1} + Q_{t} + Q_{t+1}}
85 // Clusters can also be r-phi shifted due to:
86 // - wrong PRF or wrong cuts at digits level
87 //The following correction is applied :
89 // <#Delta y> = a + b * sin(c*y_{pw})
94 // Parameterization against total charge
96 // Obtained for B=0T at phi=0. All other effects integrated out.
98 // #sigma^{2}_{y}(Q) = #sigma^{2}_{y}(...) + b(#frac{1}{Q} - #frac{1}{Q_{0}})
100 // For B diff 0T the error of the average ExB correction error has to be subtracted !!
102 // Parameterization Sx
104 // The parameterization of the error in the x direction can be written as
106 // #sigma_{x} = #sigma_{x}^{||} + #sigma_{x}^{#perp}
109 // where the parallel component is given mainly by the TRF width while
110 // the perpendicular component by the anisochronity. The model employed for
111 // the parallel is gaus(0)+expo(3) with the following parameters
112 // 1 C 5.49018e-01 1.23854e+00 3.84540e-04 -8.21084e-06
113 // 2 M 7.82999e-01 6.22531e-01 2.71272e-04 -6.88485e-05
114 // 3 S 2.74451e-01 1.13815e+00 2.90667e-04 1.13493e-05
115 // 4 E1 2.53596e-01 1.08646e+00 9.95591e-05 -2.11625e-05
116 // 5 E2 -2.40078e-02 4.26520e-01 4.67153e-05 -2.35392e-04
118 // and perpendicular to the track is pol2 with the parameters
120 // Par_0 = 0.190676 +/- 0.41785
121 // Par_1 = -3.9269 +/- 7.49862
122 // Par_2 = 14.7851 +/- 27.8012
124 // Parameterization Sy
126 // The parameterization of the error in the y direction along track uses
128 // #sigma_{y}^{||} = #sigma_{y}^{0} -a*exp(1/(x-b))
131 // with following values for the parameters:
132 // 1 sy0 2.60967e-01 2.99652e-03 7.82902e-06 -1.89636e-04
133 // 2 a -7.68941e+00 1.87883e+00 3.84539e-04 9.38268e-07
134 // 3 b -3.41160e-01 7.72850e-02 1.63231e-05 2.51602e-05
136 //==========================================================================
137 // Example how to retrive reference plots from the task
138 // void steerClErrParam(Int_t fig=0)
140 // gSystem->Load("libANALYSIS.so");
141 // gSystem->Load("libTRDqaRec.so");
143 // // initialize DB manager
144 // AliCDBManager *cdb = AliCDBManager::Instance();
145 // cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
147 // // initialize magnetic field.
148 // AliMagFCheb *field=new AliMagFCheb("Maps","Maps", 2, 1., 10., AliMagFCheb::k5kG);
149 // AliTracker::SetFieldMap(field, kTRUE);
151 // AliTRDclusterResolution *res = new AliTRDclusterResolution();
153 // res->Load("TRD.TaskClErrParam.root");
156 // //res->SetSaveAs();
157 // res->SetProcessCharge(kFALSE);
158 // res->SetProcessCenterPad(kFALSE);
159 // //res->SetProcessMean(kFALSE);
160 // res->SetProcessSigma(kFALSE);
161 // if(!res->PostProcess()) return;
163 // res->GetRefFigure(fig);
167 // Alexandru Bercuci <A.Bercuci@gsi.de> //
168 ////////////////////////////////////////////////////////////////////////////
170 #include "AliTRDclusterResolution.h"
171 #include "info/AliTRDclusterInfo.h"
172 #include "AliTRDgeometry.h"
173 #include "AliTRDcalibDB.h"
174 #include "AliTRDCommonParam.h"
175 #include "Cal/AliTRDCalROC.h"
176 #include "Cal/AliTRDCalDet.h"
179 #include "AliTracker.h"
180 #include "AliCDBManager.h"
183 #include "TObjArray.h"
187 #include "TGraphErrors.h"
193 #include "TLinearFitter.h"
198 ClassImp(AliTRDclusterResolution)
200 const Float_t AliTRDclusterResolution::fgkTimeBinLength = 1./ AliTRDCommonParam::Instance()->GetSamplingFrequency();
201 //_______________________________________________________
202 AliTRDclusterResolution::AliTRDclusterResolution(const char *name, const char *title)
203 : AliTRDrecoTask(name, title)
218 memset(fR, 0, 4*sizeof(Float_t));
219 memset(fP, 0, 4*sizeof(Float_t));
221 fAt = new TAxis(kNTB, 0., kNTB*fgkTimeBinLength);
223 // By default register all analysis
224 // The user can switch them off in his steering macro
231 //_______________________________________________________
232 AliTRDclusterResolution::~AliTRDclusterResolution()
234 if(fCanvas) delete fCanvas;
242 //_______________________________________________________
243 void AliTRDclusterResolution::ConnectInputData(Option_t *)
245 fInfo = dynamic_cast<TObjArray *>(GetInputData(0));
248 //_______________________________________________________
249 void AliTRDclusterResolution::CreateOutputObjects()
251 OpenFile(0, "RECREATE");
252 fContainer = Histos();
255 //_______________________________________________________
256 Bool_t AliTRDclusterResolution::GetRefFigure(Int_t ifig)
258 if(!fResults) return kFALSE;
261 TObjArray *arr = 0x0;
262 TH2 *h2 = 0x0;TH1 *h1 = 0x0;
263 TGraphErrors *gm(0x0), *gs(0x0), *gp(0x0);
266 if(!(arr = (TObjArray*)fResults->At(kQRes))) break;
267 if(!(gm = (TGraphErrors*)arr->At(0))) break;
268 if(!(gs = (TGraphErrors*)arr->At(1))) break;
269 if(!(gp = (TGraphErrors*)arr->At(2))) break;
271 gs->GetHistogram()->GetYaxis()->SetRangeUser(-50., 700.);
272 gs->GetHistogram()->SetXTitle("Q [a.u.]");
273 gs->GetHistogram()->SetYTitle("#sigma_{y} / #mu_{y} [#mum] / freq");
278 if(!(arr = (TObjArray*)fResults->At(kCenter))) break;
279 gPad->Divide(2, 1); l = gPad->GetListOfPrimitives();
280 ((TVirtualPad*)l->At(0))->cd();
281 ((TTree*)arr->At(0))->Draw("y:x>>h(23, 0.1, 2.4, 51, -.51, .51)",
282 "m[0]*(ly==0&&abs(m[0])<1.e-1)", "colz");
283 ((TVirtualPad*)l->At(1))->cd();
284 leg= new TLegend(.7, .7, .9, .95);
285 leg->SetBorderSize(0); leg->SetFillColor(0); leg->SetFillStyle(0);
286 leg->SetHeader("TRD Plane");
287 for(Int_t il = 1; il<=AliTRDgeometry::kNlayer; il++){
288 if(!(gm = (TGraphErrors*)arr->At(il))) return kFALSE;
289 gm->Draw(il>1?"pc":"apc"); leg->AddEntry(gm, Form("%d", il-1), "pl");
291 gm->GetHistogram()->SetXTitle("t_{drift} [#mus]");
292 gm->GetHistogram()->SetYTitle("#sigma_{y}(x|cen=0) [#mum]");
293 gm->GetHistogram()->GetYaxis()->SetRangeUser(150., 500.);
298 if(!(arr = (TObjArray*)fResults->At(kSigm))) break;
299 gPad->Divide(2, 1); l = gPad->GetListOfPrimitives();
300 if(!(h2 = (TH2F*)arr->At(0))) return kFALSE;
301 ((TVirtualPad*)l->At(0))->cd();
302 h1 = h2->ProjectionY("hsx_pyy"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24);
303 h1->SetYTitle("<#sigma_{x}> [#mum]");
304 h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc");
306 if(!(h2 = (TH2F*)arr->At(1))) return kFALSE;
307 ((TVirtualPad*)l->At(1))->cd();
308 h1 = h2->ProjectionY("hsy_pyy"); h1->Scale(1.e4/kND); h1->SetMarkerStyle(24);
309 h1->SetYTitle("<#sigma_{y}> [#mum]");
310 h1->GetXaxis()->SetRange(2, kNTB-1); h1->Draw("pc");
313 if(!(arr = (TObjArray*)fResults->At(kMean))) break;
314 gPad->Divide(2, 1); l = gPad->GetListOfPrimitives();
315 ((TVirtualPad*)l->At(0))->cd();
316 if(!(gm = (TGraphErrors*)arr->At(0))) return kFALSE;
318 gm->GetHistogram()->SetXTitle("t_{drift} [#mus]");
319 gm->GetHistogram()->SetYTitle("dx [#mum]");
321 ((TVirtualPad*)l->At(1))->cd();
322 if(!(gm = (TGraphErrors*)arr->At(1))) return kFALSE;
324 gm->GetHistogram()->SetXTitle("t_{drift} [#mus]");
325 gm->GetHistogram()->SetYTitle("dy [#mum]");
331 AliWarning("No container/data found.");
335 //_______________________________________________________
336 TObjArray* AliTRDclusterResolution::Histos()
338 if(fContainer) return fContainer;
339 fContainer = new TObjArray(kNtasks);
340 //fContainer->SetOwner(kTRUE);
343 TObjArray *arr = 0x0;
345 fContainer->AddAt(arr = new TObjArray(2*AliTRDgeometry::kNlayer), kCenter);
346 arr->SetName("Center");
347 for(Int_t il=0; il<AliTRDgeometry::kNlayer; il++){
348 // add resolution plot for each layer
349 if(!(h3=(TH3S*)gROOT->FindObject(Form("hCenResLy%d", il)))){
351 Form("hCenResLy%d", il),
352 Form(" ly [%d]", il),
353 kNTB, fAt->GetBinLowEdge(1), fAt->GetBinUpEdge(kNTB), // x
356 h3->SetXTitle("x [#mus]");
357 h3->SetYTitle("y [pw]");
358 h3->SetZTitle("#Delta y[cm]");
361 // add Pull plot for each layer
362 if(!(h3=(TH3S*)gROOT->FindObject(Form("hCenPullLy%d", il)))){
364 Form("hCenPullLy%d", il),
365 Form(" ly [%d]", il),
366 kNTB, fAt->GetBinLowEdge(1), fAt->GetBinUpEdge(kNTB), // x
369 h3->SetXTitle("x [#mus]");
370 h3->SetYTitle("y [pw]");
371 h3->SetZTitle("#Delta y/#sigma_{y}");
373 arr->AddAt(h3, AliTRDgeometry::kNlayer+il);
376 if(!(h3 = (TH3S*)gROOT->FindObject("Charge"))){
377 h3 = new TH3S("Charge", "dy=f(q)", 50, 2.2, 7.5, 60, -.3, .3, 60, -4., 4.);
378 h3->SetXTitle("log(q) [a.u.]");
379 h3->SetYTitle("#Delta y[cm]");
380 h3->SetZTitle("#Delta y/#sigma_{y}");
382 fContainer->AddAt(h3, kQRes);
384 fContainer->AddAt(arr = new TObjArray(kNTB), kSigm);
385 arr->SetName("Resolution");
386 for(Int_t ix=0; ix<kNTB; ix++){
387 if(!(h3=(TH3S*)gROOT->FindObject(Form("hr_x%02d", ix)))){
389 Form("hr_x%02d", ix),
390 Form(" t_{drift}(%3.1f-%3.1f)[#mus]", fAt->GetBinLowEdge(ix+1), fAt->GetBinUpEdge(ix+1)),
392 35, -.35, .35, // tgp
394 h3->SetXTitle("z [mm]");
395 h3->SetYTitle("tg#phi");
396 h3->SetZTitle("#Delta y[cm]");
401 fContainer->AddAt(arr = new TObjArray(kNTB), kMean);
402 arr->SetName("Systematics");
403 for(Int_t ix=0; ix<kNTB; ix++){
404 if(!(h3=(TH3S*)gROOT->FindObject(Form("hs_x%02d", ix)))){
406 Form("hs_x%02d", ix),
407 Form(" t_{drift}(%3.1f-%3.1f)[#mus]", fAt->GetBinLowEdge(ix+1), fAt->GetBinUpEdge(ix+1)),
409 35, -.35, .35, // tgp-h tgt
411 h3->SetXTitle("z [mm]");
412 h3->SetYTitle("tg(#phi) - h*tg(#theta)");
413 h3->SetZTitle("#Delta y[cm]");
421 //_______________________________________________________
422 void AliTRDclusterResolution::Exec(Option_t *)
424 if(!HasExB()) AliWarning("ExB was not set. Call SetExB() before running the task.");
427 Float_t x, y, z, q, dy, dydx, dzdx, cov[3], covcl[3];
430 // define limits around ExB for which x contribution is negligible
431 const Float_t kDtgPhi = 3.5e-2; //(+- 2 deg)
433 TObjArray *arr0 = (TObjArray*)fContainer->At(kCenter);
434 TObjArray *arr1 = (TObjArray*)fContainer->At(kSigm);
435 TObjArray *arr2 = (TObjArray*)fContainer->At(kMean);
437 const AliTRDclusterInfo *cli = 0x0;
438 TIterator *iter=fInfo->MakeIterator();
439 while((cli=dynamic_cast<AliTRDclusterInfo*>((*iter)()))){
440 cli->GetCluster(det, x, y, z, q, t, covcl);
441 if(fDet>=0 && fDet!=det) continue;
443 dy = cli->GetResolution();
444 cli->GetGlobalPosition(y, z, dydx, dzdx, &cov[0]);
446 // resolution as a function of cluster charge
447 // only for phi equal exB
448 if(TMath::Abs(dydx-fExB) < kDtgPhi){
449 h3 = (TH3S*)fContainer->At(kQRes);
450 h3->Fill(TMath::Log(q), dy, dy/TMath::Sqrt(covcl[0]));
453 // do not use problematic clusters in resolution analysis
454 // TODO define limits as calibration aware (gain) !!
455 if(q<20. || q>250.) continue;
457 x = (t+.5)*fgkTimeBinLength; // conservative approach !!
459 // resolution as a function of y displacement from pad center
460 // only for phi equal exB
461 if(TMath::Abs(dydx-fExB) < kDtgPhi/* &&
462 TMath::Abs(x-0.675)<0.225*/){
463 Int_t ly(AliTRDgeometry::GetLayer(det));
464 h3 = (TH3S*)arr0->At(ly);
465 h3->Fill(x, cli->GetYDisplacement(), dy);
466 h3 = (TH3S*)arr0->At(AliTRDgeometry::kNlayer+ly);
467 h3->Fill(x, cli->GetYDisplacement(), dy/TMath::Sqrt(covcl[0]));
470 Int_t ix = fAt->FindBin(x);
471 if(ix==0 || ix == fAt->GetNbins()+1){
472 AliWarning(Form("Drift time %3.1f outside allowed range", x));
476 // fill histo for resolution (sigma)
477 ((TH3S*)arr1->At(ix-1))->Fill(10.*cli->GetAnisochronity(), dydx, dy);
479 // fill histo for systematic (mean)
480 ((TH3S*)arr2->At(ix-1))->Fill(10.*cli->GetAnisochronity(), dydx-cli->GetTilt()*dzdx, dy);
482 PostData(0, fContainer);
486 //_______________________________________________________
487 Bool_t AliTRDclusterResolution::PostProcess()
489 if(!fContainer) return kFALSE;
490 if(!HasExB()) AliWarning("ExB was not set. Call SetExB() before running the post processing.");
492 TObjArray *arr = 0x0;
495 TGraphErrors *g = 0x0;
496 fResults = new TObjArray(kNtasks);
497 fResults->SetOwner();
498 fResults->AddAt(arr = new TObjArray(3), kQRes);
500 arr->AddAt(g = new TGraphErrors(), 0);
501 g->SetLineColor(kBlue); g->SetMarkerColor(kBlue);
502 g->SetMarkerStyle(7);
503 arr->AddAt(g = new TGraphErrors(), 1);
504 g->SetLineColor(kRed); g->SetMarkerColor(kRed);
505 g->SetMarkerStyle(23);
506 arr->AddAt(g = new TGraphErrors(), 2);
507 g->SetLineColor(kGreen); g->SetMarkerColor(kGreen);
508 g->SetMarkerStyle(7);
510 // pad center dependence
511 fResults->AddAt(arr = new TObjArray(AliTRDgeometry::kNlayer+1), kCenter);
514 t = new TTree("cent", "dy=f(y,x,ly)"), 0);
515 t->Branch("ly", &fLy, "ly/B");
516 t->Branch("x", &fX, "x/F");
517 t->Branch("y", &fY, "y/F");
518 t->Branch("m", &fR[0], "m[2]/F");
519 t->Branch("s", &fR[2], "s[2]/F");
520 t->Branch("pm", &fP[0], "pm[2]/F");
521 t->Branch("ps", &fP[2], "ps[2]/F");
522 for(Int_t il=1; il<=AliTRDgeometry::kNlayer; il++){
523 arr->AddAt(g = new TGraphErrors(), il);
524 g->SetLineColor(il); g->SetLineStyle(il);
525 g->SetMarkerColor(il);g->SetMarkerStyle(4);
529 fResults->AddAt(t = new TTree("sigm", "dy=f(dw,x,dydx)"), kSigm);
530 t->Branch("x", &fX, "x/F");
531 t->Branch("z", &fZ, "z/F");
532 t->Branch("sx", &fR[0], "sx[2]/F");
533 t->Branch("sy", &fR[2], "sy[2]/F");
536 fResults->AddAt(t = new TTree("mean", "dy=f(dw,x,dydx - h dzdx)"), kMean);
537 t->Branch("x", &fX, "x/F");
538 t->Branch("z", &fZ, "z/F");
539 t->Branch("dx", &fR[0], "dx[2]/F");
540 t->Branch("dy", &fR[2], "dy[2]/F");
543 TIterator *iter=fResults->MakeIterator();
544 while((o=((*iter)()))) o->Clear(); // maybe it is wrong but we should never reach this point
547 // precalculated value of tg^2(alpha_L)
548 Double_t exb2 = fExB*fExB;
549 // square of the mean value of sigma drift length.
550 // has to come from previous calibration
551 //Double_t sxd2 = 1.;// [mm^2]
553 printf("ExB[%e] ExB2[%e]\n", fExB, exb2);
555 // process resolution dependency on charge
556 if(HasProcess(kQRes)) ProcessCharge();
558 // process resolution dependency on y displacement
559 if(HasProcess(kCenter)) ProcessCenterPad();
561 // process resolution dependency on drift legth and drift cell width
562 if(HasProcess(kSigm)) ProcessSigma();
564 // process systematic shift on drift legth and drift cell width
565 if(HasProcess(kMean)) ProcessMean();
570 //_______________________________________________________
571 Bool_t AliTRDclusterResolution::SetExB(Int_t det, Int_t col, Int_t row)
574 AliCDBManager *cdb = AliCDBManager::Instance();
575 if(cdb->GetRun() < 0){
576 AliError("OCDB manager not properly initialized");
580 // check magnetic field
581 if(TMath::Abs(AliTracker::GetBz()) < 1.e-10){
582 AliWarning("B=0. Magnetic field may not be initialized. Continue if you know what you are doing !");
585 // set reference detector if any
586 if(det>=0 && det<AliTRDgeometry::kNdet) fDet = det;
589 AliTRDcalibDB *fCalibration = AliTRDcalibDB::Instance();
590 AliTRDCalROC *fCalVdriftROC = fCalibration->GetVdriftROC(det);
591 const AliTRDCalDet *fCalVdriftDet = fCalibration->GetVdriftDet();
593 fVdrift = fCalVdriftDet->GetValue(det) * fCalVdriftROC->GetValue(col, row);
594 fExB = AliTRDCommonParam::Instance()->GetOmegaTau(fVdrift);
599 //_______________________________________________________
600 void AliTRDclusterResolution::SetVisual()
603 fCanvas = new TCanvas("clResCanvas", "Cluster Resolution Visualization", 10, 10, 600, 600);
606 //_______________________________________________________
607 void AliTRDclusterResolution::ProcessCharge()
610 if(!(h2 = (TH2I*)fContainer->At(kQRes))) {
611 AliWarning("Missing dy=f(Q) histo");
614 TF1 f("f", "gaus", -.5, .5);
618 TObjArray *arr = (TObjArray*)fResults->At(kQRes);
619 TGraphErrors *gqm = (TGraphErrors*)arr->At(0);
620 TGraphErrors *gqs = (TGraphErrors*)arr->At(1);
621 TGraphErrors *gqp = (TGraphErrors*)arr->At(2);
622 Double_t q, n = 0., entries;
624 for(Int_t ix=1; ix<=ax->GetNbins(); ix++){
625 q = TMath::Exp(ax->GetBinCenter(ix));
626 if(q<20. || q>250.) continue; // ?!
628 h1 = h2->ProjectionY("py", ix, ix);
629 entries = h1->GetEntries();
630 if(entries < 50) continue;
635 Int_t ip = gqm->GetN();
636 gqm->SetPoint(ip, q, 1.e4*f.GetParameter(1));
637 gqm->SetPointError(ip, 0., 1.e4*f.GetParError(1));
639 // correct sigma for ExB effect
640 gqs->SetPoint(ip, q, 1.e4*f.GetParameter(2)/**f.GetParameter(2)-exb2*sxd2*/);
641 gqs->SetPointError(ip, 0., 1.e4*f.GetParError(2)/**f.GetParameter(2)*/);
645 gqp->SetPoint(ip, q, entries);
646 gqp->SetPointError(ip, 0., 0./*TMath::Sqrt(entries)*/);
649 // normalize probability and get mean sy
650 Double_t sm = 0., sy;
651 for(Int_t ip=gqp->GetN(); ip--;){
652 gqp->GetPoint(ip, q, entries);
654 gqp->SetPoint(ip, q, 1.e3*entries);
655 gqs->GetPoint(ip, q, sy);
659 // error parametrization s(q) = <sy> + b(1/q-1/q0)
660 TF1 fq("fq", "[0] + [1]/x", 20., 250.);
662 //printf("sm=%f [0]=%f [1]=%f\n", 1.e-4*sm, fq.GetParameter(0), fq.GetParameter(1));
663 printf(" const Float_t sq0inv = %f; // [1/q0]\n", (sm-fq.GetParameter(0))/fq.GetParameter(1));
664 printf(" const Float_t sqb = %f; // [cm]\n", 1.e-4*fq.GetParameter(1));
667 //_______________________________________________________
668 void AliTRDclusterResolution::ProcessCenterPad()
670 // Resolution as a function of y displacement from pad center
671 // only for phi equal exB and clusters close to cathode wire plane
672 // for ideal simulations time bins 4,5 and 6.
674 TObjArray *arr = (TObjArray*)fContainer->At(kCenter);
676 AliWarning("Missing dy=f(y | x, ly) container");
679 Float_t s[AliTRDgeometry::kNlayer];
680 TF1 f("f", "gaus", -.5, .5);
681 TF1 fp("fp", "gaus", -3.5, 3.5);
683 TH1D *h1 = 0x0; TH2F *h2 = 0x0; TH3S *h3r=0x0, *h3p=0x0;
684 TObjArray *arrRes = (TObjArray*)fResults->At(kCenter);
685 TTree *t = (TTree*)arrRes->At(0);
686 TGraphErrors *gs = 0x0;
689 printf(" const Float_t lSy[6][24] = {\n {");
690 const Int_t nl = AliTRDgeometry::kNlayer;
691 for(Int_t il=0; il<nl; il++){
692 if(!(h3r = (TH3S*)arr->At(il))) continue;
693 if(!(h3p = (TH3S*)arr->At(nl+il))) continue;
694 gs = (TGraphErrors*)arrRes->At(il+1);
696 for(Int_t ix=1; ix<=h3r->GetXaxis()->GetNbins(); ix++){
697 ax = h3r->GetXaxis(); ax->SetRange(ix, ix);
698 ax = h3p->GetXaxis(); ax->SetRange(ix, ix);
699 fX = ax->GetBinCenter(ix);
700 //printf(" x[%2d]=%4.2f\n", ix, fX);
701 for(Int_t iy=1; iy<=h3r->GetYaxis()->GetNbins(); iy++){
702 ax = h3r->GetYaxis(); ax->SetRange(iy, iy);
703 ax = h3p->GetYaxis(); ax->SetRange(iy, iy);
704 fY = ax->GetBinCenter(iy);
705 //printf(" y[%2d]=%5.2f\n", iy, fY);
706 // finish navigation in the HnSparse
708 h1 = (TH1D*)h3r->Project3D("z");
709 Int_t entries = (Int_t)h1->Integral();
710 if(entries < 50) continue;
714 // Fill sy,my=f(y_w,x,ly)
715 fR[0] = f.GetParameter(1); fR[1] = f.GetParError(1);
716 fR[2] = f.GetParameter(2); fR[3] = f.GetParError(2);
718 h1 = (TH1D*)h3p->Project3D("z");
720 fP[0] = fp.GetParameter(1); fP[1] = fp.GetParError(1);
721 fP[2] = fp.GetParameter(2); fP[3] = fp.GetParError(2);
723 //printf("ly[%d] x[%3.1f] y[%+5.2f] m[%5.3f] s[%5.3f] \n", fLy, fX, fY, fR[0], fR[2]);
729 t->Draw("y:x>>h(24, 0., 2.4, 51, -.51, .51)",
730 Form("s[0]*(ly==%d&&abs(m[0])<1.e-1)", fLy),
732 h2=(TH2F*)gROOT->FindObject("h");
733 f.FixParameter(1, 0.);
734 Int_t n = h2->GetXaxis()->GetNbins(); s[il]=0.;
736 for(Int_t ix=1; ix<=n; ix++){
738 fX = ax->GetBinCenter(ix);
739 h1 = h2->ProjectionY("hCenPy", ix, ix);
740 //if((Int_t)h1->Integral() < 1.e-10) continue;
742 s[il]+=f.GetParameter(2);
743 printf("%6.4f,%s", f.GetParameter(0), ix%6?" ":"\n ");
744 Int_t jx = gs->GetN();
745 gs->SetPoint(jx, fX, 1.e4*f.GetParameter(0));
746 gs->SetPointError(jx, 0., 0./*f.GetParError(0)*/);
751 f.ReleaseParameter(2);
754 if(!fCanvas) continue;
756 fCanvas->Modified(); fCanvas->Update();
757 if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessCenter_ly[%d].gif", fLy));
758 else gSystem->Sleep(100);
761 printf(" const Float_t lPRF[] = {"
762 "%5.3f, %5.3f, %5.3f, %5.3f, %5.3f, %5.3f};\n",
763 s[0], s[1], s[2], s[3], s[4], s[5]);
766 //_______________________________________________________
767 void AliTRDclusterResolution::ProcessSigma()
769 TObjArray *arr = (TObjArray*)fContainer->At(kSigm);
771 AliWarning("Missing dy=f(x_d, d_w) container");
775 // init visualization
776 TGraphErrors *ggs = 0x0;
779 ggs = new TGraphErrors();
781 line->SetLineColor(kRed);line->SetLineWidth(2);
784 // init logistic support
785 TF1 f("f", "gaus", -.5, .5);
786 TLinearFitter gs(1,"pol1");
788 TH1D *h1 = 0x0; TH3S *h3=0x0;
790 Double_t exb2 = fExB*fExB;
792 TTree *t = (TTree*)fResults->At(kSigm);
793 for(Int_t ix=0; ix<kNTB; ix++){
794 if(!(h3=(TH3S*)arr->At(ix))) continue;
795 fX = fAt->GetBinCenter(ix+1);
797 for(Int_t iz=1; iz<=h3->GetXaxis()->GetNbins(); iz++){
799 ax->SetRange(iz, iz);
800 fZ = ax->GetBinCenter(iz);
802 // reset visualization
804 new(ggs) TGraphErrors();
805 ggs->SetMarkerStyle(7);
809 for(Int_t ip=1; ip<=h3->GetYaxis()->GetNbins(); ip++){
811 ax->SetRange(ip, ip);
812 Double_t tgl = ax->GetBinCenter(ip);
813 // finish navigation in the HnSparse
815 //if(TMath::Abs(dydx)>0.18) continue;
816 Double_t tgg = (tgl-fExB)/(1.+tgl*fExB);
817 Double_t tgg2 = tgg*tgg;
819 h1 = (TH1D*)h3->Project3D("z");
820 Int_t entries = (Int_t)h1->Integral();
821 if(entries < 50) continue;
825 Double_t s2 = f.GetParameter(2)*f.GetParameter(2);
826 Double_t s2e = 2.*f.GetParameter(2)*f.GetParError(2);
827 // Fill sy^2 = f(tg^2(phi-a_L))
828 gs.AddPoint(&tgg2, s2, s2e);
831 Int_t jp = ggs->GetN();
832 ggs->SetPoint(jp, tgg2, s2);
833 ggs->SetPointError(jp, 0., s2e);
835 if(gs.Eval()) continue;
837 // s^2_x = s0^2_x - x^2*tg^2(a_L)/12
838 fR[0] = gs.GetParameter(1)/* - x*x*exb2/12.*/;
839 if(fR[0]<0.) continue;
840 fR[0] = TMath::Sqrt(fR[0]);
841 fR[1] = .5*gs.GetParError(1)/fR[0];
843 // s^2_y = s0^2_y + tg^2(a_L) * s^2_x
844 // s0^2_y = f(D_L)*x + s_PRF^2
845 fR[2]= gs.GetParameter(0)/*-exb2*sx*/;
846 if(fR[1] <0.) continue;
847 fR[2] = TMath::Sqrt(fR[2]);
848 fR[3] = gs.GetParError(0)+exb2*exb2*gs.GetParError(1);
851 if(!fCanvas) continue;
852 fCanvas->cd(); fCanvas->SetLogx(); //fCanvas->SetLogy();
854 hFrame=new TH1I("hFrame", "", 100, 0., .3);
855 hFrame->SetMinimum(0.);hFrame->SetMaximum(.005);
856 hFrame->SetXTitle("tg^{2}(#phi-#alpha_{L})");
857 hFrame->SetYTitle("#sigma^{2}y[cm^{2}]");
858 hFrame->SetLineColor(1);hFrame->SetLineWidth(1);
860 } else hFrame->Reset();
861 Double_t xx = 0., dxx=.2/50;
862 for(Int_t ip=0;ip<50;ip++){
863 line->SetPoint(ip, xx, gs.GetParameter(0)+xx*gs.GetParameter(1));
866 ggs->Draw("pl"); line->Draw("l");
867 fCanvas->Modified(); fCanvas->Update();
868 if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessSigma_z[%5.3f]_x[%5.3f].gif", fZ, fX));
869 else gSystem->Sleep(100);
871 printf(" xd=%4.1f[cm] sx=%5.3e[cm] sy=%5.3e[cm]\n", fX, TMath::Sqrt(fR[0]), TMath::Sqrt(fR[1]));
877 //_______________________________________________________
878 void AliTRDclusterResolution::ProcessMean()
880 TObjArray *arr = (TObjArray*)fContainer->At(kMean);
882 AliWarning("Missing dy=f(x_d, d_w) container");
886 // init logistic support
887 TF1 f("f", "gaus", -.5, .5);
888 TF1 line("l", "[0]+[1]*x", -.15, .15);
889 TGraphErrors *gm = new TGraphErrors();
891 TH1D *h1 = 0x0; TH3S *h3 =0x0;
894 TTree *t = (TTree*)fResults->At(kMean);
895 for(Int_t ix=0; ix<kNTB; ix++){
896 if(!(h3=(TH3S*)arr->At(ix))) continue;
897 fX = fAt->GetBinCenter(ix+1);
899 for(Int_t iz=1; iz<=h3->GetXaxis()->GetNbins(); iz++){
901 ax->SetRange(iz, iz);
902 fZ = ax->GetBinCenter(iz);
905 new(gm) TGraphErrors();
906 gm->SetMarkerStyle(7);
908 for(Int_t ip=1; ip<=h3->GetYaxis()->GetNbins(); ip++){
910 ax->SetRange(ip, ip);
911 Double_t tgl = ax->GetBinCenter(ip);
912 // finish navigation in the HnSparse
914 h1 = (TH1D*)h3->Project3D("z");
915 Int_t entries = (Int_t)h1->Integral();
916 if(entries < 50) continue;
920 // Fill <Dy> = f(dydx - h*dzdx)
921 Int_t jp = gm->GetN();
922 gm->SetPoint(jp, tgl, f.GetParameter(1));
923 gm->SetPointError(jp, 0., f.GetParError(1));
925 if(gm->GetN()<4) continue;
927 gm->Fit(&line, "QN");
928 fR[0] = line.GetParameter(1); // dx
929 fR[1] = line.GetParError(1);
930 fR[2] = line.GetParameter(0) + fExB*fR[0]; // xs = dy - tg(a_L)*dx
933 if(!fCanvas) continue;
936 hFrame=new TH1I("hFrame", "", 100, -.3, .3);
937 hFrame->SetMinimum(-.1);hFrame->SetMaximum(.1);
938 hFrame->SetXTitle("tg#phi-htg#theta");
939 hFrame->SetYTitle("#Deltay[cm]");
940 hFrame->SetLineColor(1);hFrame->SetLineWidth(1);
942 } else hFrame->Reset();
943 gm->Draw("pl"); line.Draw("same");
944 fCanvas->Modified(); fCanvas->Update();
945 if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessMean_Z[%5.3f]_X[%5.3f].gif", fZ, fX));
946 else gSystem->Sleep(100);
947 printf(" xd=%4.2f[cm] dx=%5.3e[cm] dy=%5.3e[cm]\n", fX, fR[0], fR[2]);
951 // draw shift results
952 //t->Draw("z:x>>h(24, 0, 2.4, 25, 0, 2.5)", "dx*(abs(dx)<1.e-2)", "lego2fb");
953 //t->Draw("z:x>>h(24, 0, 2.4, 25, 0, 2.5)", "dy*(abs(dx)<1.e-2)", "lego2fb");