]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/qaRec/AliTRDclusterResolution.cxx
updates in the cluster resolution (on going)
[u/mrichter/AliRoot.git] / TRD / qaRec / AliTRDclusterResolution.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercialf purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 /* $Id: AliTRDclusterResolution.cxx */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 //  TRD cluster error parameterization                                        //
21 //                                                                           //
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//
24 // into account :                                                            //
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. 
33 // 
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 
37 // considered.
38 // 
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.
43 // 
44 // The functionalities implemented in this class are based on the storage 
45 // class AliTRDclusterInfo.
46 // 
47 // The Method
48 // ----------
49 // 
50 // The method to disentangle s_y and s_x is based on the relation (see also fig.)
51 // BEGIN_LATEX
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}})
53 // END_LATEX
54 // with
55 // BEGIN_LATEX
56 // #sigma^{2}_{x_{c}} #approx 0 
57 // END_LATEX
58 // we suppose the chamber is well calibrated for t_{0} and aligned in
59 // radial direction. 
60 //
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.
66 //
67 // We estimate this effects by the relations:
68 // BEGIN_LATEX
69 // #mu_{y} = tg(#alpha_{L})*#Delta x_{d}(...) + tg(#phi-#alpha_{L})*(#Delta x_{c}(...) + #Delta x_{d}(...))
70 // END_LATEX
71 // where
72 // BEGIN_LATEX
73 // #Delta x_{d}(...) = (<v_{d}> + #delta v_{d}(x_{d}, d)) * (t + t^{*}(Q))
74 // END_LATEX
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).
77 // 
78 // For estimating the contribution from asymmetry of TRF the following
79 // parameterization is being used
80 // BEGIN_LATEX
81 // t^{*}(Q) = #delta_{0} * #frac{Q_{t+1} - Q_{t-1}}{Q_{t-1} + Q_{t} + Q_{t+1}}
82 // END_LATEX
83 //
84 //
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 :
88 // BEGIN_LATEX
89 // <#Delta y> = a + b * sin(c*y_{pw})
90 // END_LATEX
91
92 // The Models
93 //
94 //   Parameterization against total charge
95 //
96 // Obtained for B=0T at phi=0. All other effects integrated out.
97 // BEGIN_LATEX
98 // #sigma^{2}_{y}(Q) = #sigma^{2}_{y}(...) + b(#frac{1}{Q} - #frac{1}{Q_{0}}) 
99 // END_LATEX
100 // For B diff 0T the error of the average ExB correction error has to be subtracted !! 
101 //
102 //   Parameterization Sx
103 //
104 // The parameterization of the error in the x direction can be written as
105 // BEGIN_LATEX
106 // #sigma_{x} = #sigma_{x}^{||} + #sigma_{x}^{#perp}
107 // END_LATEX
108 //
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
117 //
118 // and perpendicular to the track is pol2 with the parameters
119 //
120 // Par_0 = 0.190676 +/- 0.41785
121 // Par_1 = -3.9269  +/- 7.49862
122 // Par_2 = 14.7851  +/- 27.8012
123 //
124 //   Parameterization Sy
125 //
126 // The parameterization of the error in the y direction along track uses
127 // BEGIN_LATEX
128 // #sigma_{y}^{||} = #sigma_{y}^{0} -a*exp(1/(x-b))
129 // END_LATEX
130 //
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
135 //
136 //==========================================================================
137 // Example how to retrive reference plots from the task
138 // void steerClErrParam(Int_t fig=0)
139 // {
140 //   gSystem->Load("libANALYSIS.so");
141 //   gSystem->Load("libTRDqaRec.so");
142 // 
143 //   // initialize DB manager
144 //   AliCDBManager *cdb = AliCDBManager::Instance();
145 //   cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
146 //   cdb->SetRun(0);
147 //   // initialize magnetic field.
148 //   AliMagFCheb *field=new AliMagFCheb("Maps","Maps", 2, 1., 10., AliMagFCheb::k5kG);
149 //   AliTracker::SetFieldMap(field, kTRUE);
150 // 
151 //   AliTRDclusterResolution *res = new AliTRDclusterResolution();
152 //   res->SetMCdata();
153 //   res->Load("TRD.TaskClErrParam.root");
154 //   res->SetExB();  
155 //   res->SetVisual(); 
156 //   //res->SetSaveAs();
157 //   res->SetProcessCharge(kFALSE);
158 //   res->SetProcessCenterPad(kFALSE);
159 //   //res->SetProcessMean(kFALSE);
160 //   res->SetProcessSigma(kFALSE);
161 //   if(!res->PostProcess()) return;
162 //   new TCanvas;
163 //   res->GetRefFigure(fig);
164 // }
165 //
166 //  Authors:                                                              //
167 //    Alexandru Bercuci <A.Bercuci@gsi.de>                                //
168 ////////////////////////////////////////////////////////////////////////////
169
170 #include "AliTRDclusterResolution.h"
171 #include "AliTRDtrackInfo/AliTRDclusterInfo.h"
172 #include "AliTRDgeometry.h"
173 #include "AliTRDcalibDB.h"
174 #include "AliTRDCommonParam.h"
175 #include "Cal/AliTRDCalROC.h"
176 #include "Cal/AliTRDCalDet.h"
177
178 #include "AliLog.h"
179 #include "AliTracker.h"
180 #include "AliCDBManager.h"
181
182 #include "TROOT.h"
183 #include "TObjArray.h"
184 #include "TAxis.h"
185 #include "TF1.h"
186 #include "TGraphErrors.h"
187 #include "TLine.h"
188 #include "TH2I.h"
189 #include "TMath.h"
190 #include "TLinearFitter.h"
191
192 #include "TCanvas.h"
193 #include "TSystem.h"
194
195
196 ClassImp(AliTRDclusterResolution)
197
198 const Float_t AliTRDclusterResolution::fgkTimeBinLength = 1./ AliTRDCommonParam::Instance()->GetSamplingFrequency();
199 //_______________________________________________________
200 AliTRDclusterResolution::AliTRDclusterResolution(const char *name)
201   : AliTRDrecoTask(name, "Cluster Error Parametrization")
202   ,fCanvas(0x0)
203   ,fInfo(0x0)
204   ,fResults(0x0)
205   ,fAt(0x0)
206   ,fAd(0x0)
207   ,fStatus(0)
208   ,fDet(-1)
209   ,fExB(0.)
210   ,fVdrift(0.)
211 {
212   // time drift axis
213   fAt = new TAxis(kNTB, 0., kNTB*fgkTimeBinLength);
214   // z axis spans the drift cell 2.5 mm
215   fAd = new TAxis(kND, 0., .25);
216
217   // By default register all analysis
218   // The user can switch them off in his steering macro
219   SetProcess(kQRes);
220   SetProcess(kCenter);
221   SetProcess(kMean);
222   SetProcess(kSigm);
223 }
224
225 //_______________________________________________________
226 AliTRDclusterResolution::~AliTRDclusterResolution()
227 {
228   if(fCanvas) delete fCanvas;
229   if(fAd) delete fAd;
230   if(fAt) delete fAt;
231   if(fResults){
232     fResults->Delete();
233     delete fResults;
234   }
235 }
236
237 //_______________________________________________________
238 void AliTRDclusterResolution::ConnectInputData(Option_t *)
239 {
240   fInfo = dynamic_cast<TObjArray *>(GetInputData(0));
241 }
242
243 //_______________________________________________________
244 void AliTRDclusterResolution::CreateOutputObjects()
245 {
246   OpenFile(0, "RECREATE");
247   fContainer = Histos();
248 }
249
250 //_______________________________________________________
251 Bool_t AliTRDclusterResolution::GetRefFigure(Int_t ifig)
252 {
253   if(!fResults) return kFALSE;
254   
255   TList *l = 0x0;
256   TObjArray *arr = 0x0;
257   TH2 *h2 = 0x0;
258   TGraphErrors *gm(0x0), *gs(0x0), *gp(0x0);
259   switch(ifig){
260   case kQRes:
261     if(!(arr = (TObjArray*)fResults->At(kQRes))) break;
262     if(!(gm = (TGraphErrors*)arr->At(0))) break;
263     if(!(gs = (TGraphErrors*)arr->At(1))) break;
264     if(!(gp = (TGraphErrors*)arr->At(2))) break;
265     gs->Draw("apl");
266     gs->GetHistogram()->GetYaxis()->SetRangeUser(-.01, .6);
267     gs->GetHistogram()->SetXTitle("Q [a.u.]");
268     gs->GetHistogram()->SetYTitle("#sigma_{y} / #mu_{y} [mm] / freq");
269     gm->Draw("pl");
270     gp->Draw("pl");
271     return kTRUE;
272   case kCenter:
273     if(!(arr = (TObjArray*)fResults->At(kCenter))) break;
274     gPad->Divide(3, 1); l = gPad->GetListOfPrimitives();
275     for(Int_t ipad = 3; ipad--;){
276       if(!(h2 = (TH2F*)arr->At(ipad))) return kFALSE;
277       ((TVirtualPad*)l->At(ipad))->cd();
278       h2->Draw("lego2fb");
279     }
280     return kTRUE;
281   case kSigm:
282     if(!(arr = (TObjArray*)fResults->At(kSigm))) break;
283     gPad->Divide(2, 1); l = gPad->GetListOfPrimitives();
284     for(Int_t ipad = 2; ipad--;){
285       if(!(h2 = (TH2F*)arr->At(ipad))) return kFALSE;
286       ((TVirtualPad*)l->At(ipad))->cd();
287       h2->Draw("lego2fb");
288     }
289     return kTRUE;
290   case kMean:
291     if(!(arr = (TObjArray*)fResults->At(kMean))) break;
292     gPad->Divide(2, 1);  l = gPad->GetListOfPrimitives();
293     for(Int_t ipad = 2; ipad--;){
294       if(!(h2 = (TH2F*)arr->At(ipad))) return kFALSE;
295       ((TVirtualPad*)l->At(ipad))->cd();
296       h2->Draw("lego2fb");
297     }
298     return kTRUE;
299   default:
300     break;
301   }
302   AliWarning("No container/data found.");
303   return kFALSE;
304 }
305
306 //_______________________________________________________
307 TObjArray* AliTRDclusterResolution::Histos()
308 {
309   if(fContainer) return fContainer;
310   fContainer = new TObjArray(sizeof(AliTRDclusterResolution::EResultContainer));
311   //fContainer->SetOwner(kTRUE);
312
313   TH2I *h2 = 0x0;
314   TObjArray *arr = 0x0;
315
316   fContainer->AddAt(h2 = new TH2I("h_q", "", 50, 2.2, 7.5, 100, -.5, .5), kQRes);
317   h2->SetXTitle("log(q) [a.u.]");
318   h2->SetYTitle("#Delta y[cm]");
319   h2->SetZTitle("entries");
320
321   fContainer->AddAt(arr = new TObjArray(AliTRDgeometry::kNlayer), kCenter);
322   arr->SetName("y(PadWidth)");
323   for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
324     arr->AddAt(h2 = new TH2I(Form("h_y%d", ily), Form("Ly[%d]", ily), 51, -.51, .51, 100, -.5, .5), ily);
325     h2->SetXTitle("y_{w} [w]");
326     h2->SetYTitle("#Delta y[cm]");
327     h2->SetZTitle("entries");
328   }
329
330   fContainer->AddAt(arr = new TObjArray(kN), kSigm);
331   arr->SetName("Resolution");
332   Int_t ih = 0;
333   for(Int_t id=1; id<=fAd->GetNbins(); id++){
334     for(Int_t it=1; it<=fAt->GetNbins(); it++){
335       arr->AddAt(h2 = new TH2I(Form("hr_d%02dt%02d", id, it), Form("d_{wire}(%3.1f-%3.1f)[mm] t_{drift}(%3.1f-%3.1f)[#mus]", 10.*fAd->GetBinLowEdge(id), 10.*fAd->GetBinUpEdge(id), fAt->GetBinLowEdge(it), fAt->GetBinUpEdge(it)), 35, -.35, .35, 100, -.5, .5), ih++);
336       h2->SetXTitle("tg#phi");
337       h2->SetYTitle("#Delta y[cm]");
338       h2->SetZTitle("entries");
339     }
340   }
341
342   fContainer->AddAt(arr = new TObjArray(kN), kMean);
343   arr->SetName("Systematics");
344   ih = 0;
345   for(Int_t id=1; id<=fAd->GetNbins(); id++){
346     for(Int_t it=1; it<=fAt->GetNbins(); it++){
347       arr->AddAt(h2 = new TH2I(Form("hs_d%02dt%02d", id, it), Form("d_{wire}(%3.1f-%3.1f)[mm] t_{drift}(%3.1f-%3.1f)[#mus]", 10.*fAd->GetBinLowEdge(id), 10.*fAd->GetBinUpEdge(id), fAt->GetBinLowEdge(it), fAt->GetBinUpEdge(it)), 35, -.35, .35, 100, -.5, .5), ih++);
348       h2->SetXTitle("tg#phi-h*tg(#theta)");
349       h2->SetYTitle("#Delta y[cm]");
350       h2->SetZTitle("entries");
351     }
352   }
353
354   return fContainer;
355 }
356
357 //_______________________________________________________
358 void AliTRDclusterResolution::Exec(Option_t *)
359 {
360   if(!HasExB()) AliWarning("ExB was not set. Call SetExB() before running the task.");
361
362   Int_t det, t;
363   Float_t x, y, z, q, dy, dydx, dzdx, cov[3], covcl[3];
364   TH2I *h2 = 0x0;
365
366   // define limits around ExB for which x contribution is negligible
367   const Float_t kDtgPhi = 3.5e-2; //(+- 2 deg)
368
369   TObjArray *arr0 = (TObjArray*)fContainer->At(kCenter);
370   TObjArray *arr1 = (TObjArray*)fContainer->At(kSigm);
371   TObjArray *arr2 = (TObjArray*)fContainer->At(kMean);
372
373   const AliTRDclusterInfo *cli = 0x0;
374   TIterator *iter=fInfo->MakeIterator();
375   while((cli=dynamic_cast<AliTRDclusterInfo*>((*iter)()))){
376     cli->GetCluster(det, x, y, z, q, t, covcl);
377     if(fDet>=0 && fDet!=det) continue;
378     
379     dy = cli->GetResolution();
380     cli->GetGlobalPosition(y, z, dydx, dzdx, &cov[0]);
381
382     // resolution as a function of cluster charge
383     // only for phi equal exB 
384     if(TMath::Abs(dydx-fExB) < kDtgPhi){
385       h2 = (TH2I*)fContainer->At(kQRes);
386       h2->Fill(TMath::Log(q), dy);
387     }
388
389     // do not use problematic clusters in resolution analysis
390     // TODO define limits as calibration aware (gain) !!
391     if(q<20. || q>250.) continue;
392
393     // resolution as a function of y displacement from pad center
394     // only for phi equal exB
395     if(TMath::Abs(dydx-fExB) < kDtgPhi){
396       h2 = (TH2I*)arr0->At(AliTRDgeometry::GetLayer(det));
397       h2->Fill(cli->GetYDisplacement(), dy);
398     }
399
400     Int_t it = fAt->FindBin((t+.5)*fgkTimeBinLength);
401     if(it==0 || it == fAt->GetNbins()+1){
402       AliWarning(Form("Drift time %f outside allowed range", t));
403       continue;
404     }
405     Int_t id = fAd->FindBin(cli->GetAnisochronity());
406     if(id==0 || id == fAd->GetNbins()+1){
407       AliWarning(Form("Distance to anode %f outside allowed range", cli->GetAnisochronity()));
408       continue;
409     }
410     // calculate index of cluster position in array
411     Int_t hid = (id-1)*kNTB+it-1;
412
413     // fill histo for resolution (sigma)
414     h2 = (TH2I*)arr1->At(hid);
415     h2->Fill(dydx, dy);
416
417     // fill histo for systematic (mean)
418     h2 = (TH2I*)arr2->At(hid); 
419     h2->Fill(dydx-cli->GetTilt()*dzdx, dy);  
420   }
421   PostData(0, fContainer);
422 }
423
424
425 //_______________________________________________________
426 Bool_t AliTRDclusterResolution::PostProcess()
427 {
428   if(!fContainer) return kFALSE;
429   if(!HasExB()) AliWarning("ExB was not set. Call SetExB() before running the post processing.");
430   
431   TObjArray *arr = 0x0;
432   TH2 *h2 = 0x0; 
433   if(!fResults){
434     TGraphErrors *g = 0x0;
435     fResults = new TObjArray(sizeof(AliTRDclusterResolution::EResultContainer));
436     fResults->SetOwner();
437     fResults->AddAt(arr = new TObjArray(3), kQRes);
438     arr->SetOwner();
439     arr->AddAt(g = new TGraphErrors(), 0);
440     g->SetLineColor(kBlue); g->SetMarkerColor(kBlue);
441     g->SetMarkerStyle(7); 
442     arr->AddAt(g = new TGraphErrors(), 1);
443     g->SetLineColor(kRed); g->SetMarkerColor(kRed);
444     g->SetMarkerStyle(23); 
445     arr->AddAt(g = new TGraphErrors(), 2);
446     g->SetLineColor(kGreen); g->SetMarkerColor(kGreen);
447     g->SetMarkerStyle(7); 
448
449     fResults->AddAt(arr = new TObjArray(3), kCenter);
450     arr->SetOwner();
451
452     if(!(h2 = (TH2F*)gROOT->FindObject("hYM"))){
453       h2 = new TH2F("hYM", "", 
454       AliTRDgeometry::kNlayer, -.5, AliTRDgeometry::kNlayer-.5, 51, -.51, .51);
455     }
456     arr->AddAt(h2, 0);
457     h2->SetXTitle("ly");
458     h2->SetYTitle("y [w]");
459     h2->SetZTitle("#mu_{x} [cm]");
460     arr->AddAt(h2 = (TH2F*)h2->Clone("hYS"), 1);
461     h2->SetZTitle("#sigma_{x} [cm]");
462     arr->AddAt(h2 = (TH2F*)h2->Clone("hYP"), 2);
463     h2->SetZTitle("entries");
464
465     fResults->AddAt(arr = new TObjArray(2), kSigm);
466     arr->SetOwner();
467     if(!(h2 = (TH2F*)gROOT->FindObject("hSX"))){
468       h2 = new TH2F("hSX", "", 
469       fAd->GetNbins(), fAd->GetXmin(), fAd->GetXmax(), 
470       fAt->GetNbins(), fAt->GetXmin(), fAt->GetXmax());
471     }
472     arr->AddAt(h2, 0);
473     h2->SetXTitle("d [cm]");
474     h2->SetYTitle("t_{drift} [#mus]");
475     h2->SetZTitle("#sigma_{x} [cm]");
476     arr->AddAt(h2 = (TH2F*)h2->Clone("hSY"), 1);
477     h2->SetZTitle("#sigma_{y} [cm]");
478
479     fResults->AddAt(arr = new TObjArray(2), kMean);
480     arr->SetOwner();
481     arr->AddAt(h2 = (TH2F*)h2->Clone("hDX"), 0);
482     h2->SetZTitle("dx [cm]");
483     arr->AddAt(h2 = (TH2F*)h2->Clone("hDY"), 1);
484     h2->SetZTitle("dy [cm]");
485   } else {
486     TObject *o = 0x0;
487     TIterator *iter=fResults->MakeIterator();
488     while((o=((*iter)()))) o->Clear(); // maybe it is wrong but we should never reach this point
489   }
490   
491   // precalculated value of tg^2(alpha_L)
492   Double_t exb2 = fExB*fExB;
493   // square of the mean value of sigma drift length.
494   // has to come from previous calibration 
495   //Double_t sxd2 = 1.;// [mm^2]
496
497   printf("ExB[%e] ExB2[%e]\n", fExB, exb2);
498
499   // process resolution dependency on charge
500   if(HasProcess(kQRes)) ProcessCharge();
501   
502   // process resolution dependency on y displacement
503   if(HasProcess(kCenter)) ProcessCenterPad();
504
505   // process resolution dependency on drift legth and drift cell width
506   if(HasProcess(kSigm)) ProcessSigma();
507
508   // process systematic shift on drift legth and drift cell width
509   if(HasProcess(kMean)) ProcessMean();
510
511   return kTRUE;
512 }
513
514 //_______________________________________________________
515 Bool_t AliTRDclusterResolution::SetExB(Int_t det, Int_t col, Int_t row)
516 {
517   // check OCDB
518   AliCDBManager *cdb = AliCDBManager::Instance();
519   if(cdb->GetRun() < 0){
520     AliError("OCDB manager not properly initialized");
521     return kFALSE;
522   }
523
524   // check magnetic field
525   if(TMath::Abs(AliTracker::GetBz()) < 1.e-10){
526     AliWarning("B=0. Magnetic field may not be initialized. Continue if you know what you are doing !");
527   }
528
529   // set reference detector if any
530   if(det>=0 && det<AliTRDgeometry::kNdet) fDet = det;
531   else det = 0;
532
533   AliTRDcalibDB *fCalibration  = AliTRDcalibDB::Instance();
534   AliTRDCalROC  *fCalVdriftROC = fCalibration->GetVdriftROC(det);
535   const AliTRDCalDet  *fCalVdriftDet = fCalibration->GetVdriftDet();
536
537   fVdrift = fCalVdriftDet->GetValue(det) * fCalVdriftROC->GetValue(col, row);
538   fExB   = AliTRDCommonParam::Instance()->GetOmegaTau(fVdrift);
539   SetBit(kExB);
540   return kTRUE;
541 }
542
543 //_______________________________________________________
544 void AliTRDclusterResolution::SetVisual()
545 {
546   if(fCanvas) return;
547   fCanvas = new TCanvas("clResCanvas", "Cluster Resolution Visualization", 10, 10, 600, 600);
548 }
549
550 //_______________________________________________________
551 void AliTRDclusterResolution::ProcessCharge()
552 {
553   TH2I *h2 = 0x0;
554   if((h2 = (TH2I*)fContainer->At(kQRes))) {
555     AliWarning("Missing dy=f(Q) histo");
556     return;
557   }
558   TF1 f("f", "gaus", -.5, .5);
559   TAxis *ax = 0x0;
560   TH1D *h1 = 0x0;
561
562   TObjArray *arr = (TObjArray*)fResults->At(kQRes);
563   TGraphErrors *gqm = (TGraphErrors*)arr->At(0);
564   TGraphErrors *gqs = (TGraphErrors*)arr->At(1);
565   TGraphErrors *gqp = (TGraphErrors*)arr->At(2);
566   Double_t q, n = 0., entries;
567   ax = h2->GetXaxis();
568   for(Int_t ix=1; ix<=ax->GetNbins(); ix++){
569     q = TMath::Exp(ax->GetBinCenter(ix));
570     if(q<20. || q>250.) continue; // ?!
571
572     h1 = h2->ProjectionY("py", ix, ix);
573     entries = h1->GetEntries();
574     if(entries < 50) continue;
575     Adjust(&f, h1);
576     h1->Fit(&f, "Q");
577
578     // Fill sy^2 = f(q)
579     Int_t ip = gqm->GetN();
580     gqm->SetPoint(ip, q, 10.*f.GetParameter(1));
581     gqm->SetPointError(ip, 0., 10.*f.GetParError(1));
582
583     // correct sigma for ExB effect
584     gqs->SetPoint(ip, q, 1.e1*f.GetParameter(2)/**f.GetParameter(2)-exb2*sxd2*/);
585     gqs->SetPointError(ip, 0., 1.e1*f.GetParError(2)/**f.GetParameter(2)*/);
586
587     // save probability
588     n += entries;
589     gqp->SetPoint(ip, q, entries);
590     gqp->SetPointError(ip, 0., 0./*TMath::Sqrt(entries)*/);
591   } 
592
593   // normalize probability and get mean sy
594   Double_t sm = 0., sy;
595   for(Int_t ip=gqp->GetN(); ip--;){
596     gqp->GetPoint(ip, q, entries);
597     entries/=n;
598     gqp->SetPoint(ip, q, entries);
599     gqs->GetPoint(ip, q, sy);
600     sm += entries*sy;
601   }
602
603   // error parametrization s(q) = <sy> + b(1/q-1/q0)
604   TF1 fq("fq", "[0] + [1]/x", 20., 250.);
605   gqs->Fit(&fq);
606   printf("sy(Q) :: sm[%f] b[%f] 1/q0[%f]\n", sm, fq.GetParameter(1), (sm-fq.GetParameter(0))/fq.GetParameter(1));
607 }
608
609 //_______________________________________________________
610 void AliTRDclusterResolution::ProcessCenterPad()
611 {
612   TObjArray *arr = (TObjArray*)fContainer->At(kCenter);
613   if(!arr) {
614     AliWarning("Missing dy=f(y_d) container");
615     return;
616   }
617   TF1 f("f", "gaus", -.5, .5);
618   TAxis *ax = 0x0;
619   TH1D *h1 = 0x0, *h11 = 0x0;
620   TH2I *h2 = 0x0;
621
622   TObjArray *arrg = (TObjArray*)fResults->At(kCenter);
623   TH2F *hym = (TH2F*)arrg->At(0);
624   TH2F *hys = (TH2F*)arrg->At(1);
625   TH2F *hyp = (TH2F*)arrg->At(2);
626   for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
627     if(!(h2 = (TH2I*)arr->At(ily))) continue;
628     ax = h2->GetXaxis();
629     for(Int_t ix=1; ix<=ax->GetNbins(); ix++){
630       Float_t yd = ax->GetBinCenter(ix);
631       h1 = h2->ProjectionY("py", ix, ix);
632       Int_t entries = (Int_t)h1->GetEntries();
633       if(entries < 50) continue;
634       //Adjust(&f, h1);
635       h1->Fit(&f, "QN");
636   
637       // Fill sy = f(y_w)
638       hyp->Fill(ily, yd, entries);
639       hym->Fill(ily, yd, f.GetParameter(1));
640       //hym->SetPointError(ip, 0., f.GetParError(1));
641       hys->Fill(ily, yd, f.GetParameter(2));
642       //hys->SetPointError(ip, 0., f.GetParError(2));
643     } 
644   }
645
646   // POSTPROCESS SPECTRA
647   // Found correction for systematic deviation  
648   TF1 fprf("fprf", "[0]+[1]*sin([2]*x)", -.5, .5);
649   fprf.SetParameter(0, 0.);
650   fprf.SetParameter(1, 1.1E-2);
651   fprf.SetParameter(2, -TMath::PiOver2()/0.25);
652   printf("  const Float_t cy[AliTRDgeometry::kNlayer][3] = {\n");
653   for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
654     h1 = hym->ProjectionY("hym_pyy", ily+1, ily+1);
655     // adjust errors 
656     for(Int_t ib=h1->GetNbinsX(); ib--;) h1->SetBinError(ib, 0.002);
657     h1->Fit(&fprf, "Q");
658     printf("    {%5.3e, %5.3e, %5.3e},\n", fprf.GetParameter(0), fprf.GetParameter(1), fprf.GetParameter(2));
659
660     if(!fCanvas) continue;
661     fCanvas->cd(); 
662     h1->SetMinimum(-0.02);h1->SetMaximum(0.02);h1->Draw("e1"); 
663     h11 = hyp->ProjectionY("hyp_pyy", ily+1, ily+1);
664     h11->Scale(.8/h11->Integral());
665     h11->SetLineColor(kBlue); h11->Draw("csame");
666     fCanvas->Modified(); fCanvas->Update(); 
667     if(IsSaveAs())
668     fCanvas->SaveAs(Form("Figures/ProcessCenterPad_M_Ly%d.gif", ily));
669     else gSystem->Sleep(500);
670   }
671   printf("  };\n");
672
673   // Parameterization for sigma PRF  
674   TF1 fgaus("fgaus", "gaus", -.5, .5);
675   printf("  const Float_t scy[AliTRDgeometry::kNlayer][4] = {\n");
676   for(Int_t ily=0; ily<AliTRDgeometry::kNlayer; ily++){
677     h1 = hys->ProjectionY("hys_pyy", ily+1, ily+1);
678     // adjust errors 
679     for(Int_t ib=h1->GetNbinsX(); ib--;) h1->SetBinError(ib, 0.002);
680
681     h1->Fit(&fgaus, "Q");
682     printf("    {%5.3e, %5.3e, %5.3e, ", fgaus.GetParameter(0), fgaus.GetParameter(1), fgaus.GetParameter(2));
683
684     // calculate mean sigma on the pad center distribution
685     Float_t sy = 0.;
686     h1 = hyp->ProjectionY("hyp_pyy", ily+1, ily+1);
687     for(Int_t ix=1; ix<=h1->GetNbinsX(); ix++){
688       sy += fgaus.Eval(h1->GetBinCenter(ix))*h1->GetBinContent(ix);
689     }
690     sy /= h1->GetEntries();
691     printf("%5.3e},\n", sy);
692
693     if(!fCanvas) continue;
694     fCanvas->cd(); 
695     h1->SetMinimum(0.01);h1->SetMaximum(0.04);h1->Draw("e1"); 
696     h11 = hyp->ProjectionY("hyp_pyy", ily+1, ily+1);
697     h11->Scale(1./h11->Integral());
698     h11->SetLineColor(kBlue); h11->Draw("csame");
699     fCanvas->Modified(); fCanvas->Update(); 
700     if(IsSaveAs())
701     fCanvas->SaveAs(Form("Figures/ProcessCenterPad_S_Ly%d.gif", ily));
702     else gSystem->Sleep(500);
703   }
704   printf("  };\n");
705 }
706
707 //_______________________________________________________
708 void AliTRDclusterResolution::ProcessSigma()
709 {
710   TObjArray *arr = (TObjArray*)fContainer->At(kSigm);
711   if(!arr){
712     AliWarning("Missing dy=f(x_d, d_wire) container");
713     return;
714   }
715   TLinearFitter gs(1,"pol1");
716   TF1 f("f", "gaus", -.5, .5);
717   TAxis *ax = 0x0;
718   TH1D *h1 = 0x0;
719   TH2I *h2 = 0x0;
720   // init visualization
721   TGraphErrors *ggs = 0x0;
722   TLine *line = 0x0;
723   if(fCanvas){
724     ggs = new TGraphErrors();
725     line = new TLine();
726   }
727
728   Double_t d(0.), x(0.), sx, sy;
729   TObjArray *arrr = (TObjArray*)fResults->At(kSigm);
730   TH2F *hsx = (TH2F*)arrr->At(0);
731   TH2F *hsy = (TH2F*)arrr->At(1);
732   for(Int_t id=1; id<=fAd->GetNbins(); id++){
733     d = fAd->GetBinCenter(id); //[mm]
734     printf(" Doing d = %5.3f [mm]\n", d);
735     for(Int_t it=1; it<=fAt->GetNbins(); it++){
736       x = fAt->GetBinCenter(it); //[mm]
737       Int_t idx = (id-1)*kNTB+it-1;
738
739       // retrieve data histogram
740       if(!(h2 = (TH2I*)arr->At(idx))) {
741         AliWarning(Form("Missing histo at index idx[%3d] [id[%2d] it[%2d]] xd[%f] d[%f]\n", idx, id, it, x, d));
742         continue;
743       }
744
745       if(fCanvas){ 
746         new(ggs) TGraphErrors();
747         ggs->SetMarkerStyle(7);
748       }
749       gs.ClearPoints();
750       ax = h2->GetXaxis();
751       for(Int_t ix=1; ix<=ax->GetNbins(); ix++){
752         Float_t dydx = ax->GetBinCenter(ix);
753         Double_t tgg = (dydx-fExB)/(1.+dydx*fExB);
754         Double_t tgg2 = tgg*tgg;
755         h1 = h2->ProjectionY("py", ix, ix);
756         if(h1->GetEntries() < 100) continue;
757         //Adjust(&f, h1);
758         //printf("\tFit ix[%d] on %s entries [%d]\n", ix, h2->GetName(), (Int_t)h1->GetEntries());
759         h1->Fit(&f, "QN");
760         Double_t s2  = f.GetParameter(2)*f.GetParameter(2);
761         Double_t s2e = 2.*f.GetParameter(2)*f.GetParError(2);
762         // Fill sy^2 = f(tg^2(phi-a_L))
763         gs.AddPoint(&tgg2, s2, s2e);
764
765         if(!ggs) continue;
766         Int_t ip = ggs->GetN();
767         ggs->SetPoint(ip, tgg2, s2);
768         ggs->SetPointError(ip, 0., s2e);
769         //printf("%f, %f, %f, \n", tgg2, s2, s2e);
770       }
771       if(gs.Eval()) continue;
772       sx = gs.GetParameter(1); 
773       sy = gs.GetParameter(0);
774       hsx->SetBinContent(id, it, TMath::Sqrt(sx));
775       //hsx->SetBinError(id, it, sig.GetParError(1));
776
777       // s^2_y = s0^2_y + tg^2(a_L) * s^2_x 
778       hsy->SetBinContent(id, it, TMath::Sqrt(sy)/* - exb2*sig.GetParameter(1)*/);
779       //hsy->SetBinError(id, it, sig.GetParError(0)+exb2*exb2*sig.GetParError(1));
780
781       /*if(!fCanvas) */continue;
782       fCanvas->cd();
783       new(line) TLine(0, sy, .025, sy+.025*sx); 
784       line->SetLineColor(kRed);line->SetLineWidth(2);
785       ggs->Draw("apl"); line->Draw("");
786       fCanvas->Modified(); fCanvas->Update();
787       if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessSigma_D%d_T%02d.gif", id, it));
788       else gSystem->Sleep(100);
789
790       printf("    xd=%4.1f[cm] sx=%5.3e[cm] sy=%5.3e[cm]\n", x, sx, sy);
791     }
792   }
793 //   if(ggs) delete ggs; // TODO fix this memory leak !
794 //   if(line) delete line;
795
796   // fit sy parallel to the drift
797   TF1 fsyD("fsy", "[0]+[1]*exp(1./(x+[2]))", 0.5, 3.5);
798   fsyD.SetParameter(0, .025);
799   fsyD.SetParameter(1, -8.e-4);
800   fsyD.SetParameter(2, -.25);
801   h1 = hsy->ProjectionY("hsy_pyy"); h1->Scale(1./hsy->GetNbinsX());
802   for(Int_t ib=1; ib<=h1->GetNbinsX(); ib++) h1->SetBinError(ib, 0.002);
803   h1->Fit(&fsyD, "Q", "", .5, 3.5);
804   printf("  const Float_t sy0 = %5.3e;\n", fsyD.GetParameter(0));
805   printf("  const Float_t sya = %5.3e;\n", fsyD.GetParameter(1));
806   printf("  const Float_t syb = %5.3e;\n", fsyD.GetParameter(2));
807   if(fCanvas){
808     fCanvas->cd();
809     h1->Draw("e1"); fsyD.Draw("same");
810     fCanvas->Modified(); fCanvas->Update();
811     if(IsSaveAs()) fCanvas->SaveAs("Figures/ProcessSigma_SY||.gif");
812     else gSystem->Sleep(1000);
813   }
814   
815
816   // fit sx parallel to the drift
817   TF1 fsxD("fsx", "gaus(0)+expo(3)", 0., 3.5);
818   h1 = hsx->ProjectionY("hsx_pyy"); 
819   h1->Scale(1./hsx->GetNbinsX());
820   for(Int_t ib=1; ib<=h1->GetNbinsX(); ib++) if(h1->GetBinContent(ib)>0.) h1->SetBinError(ib, 0.02);
821   h1->Fit(&f, "QN", "", 0., 1.3);
822   fsxD.SetParameter(0, 0.);
823   fsxD.SetParameter(1, f.GetParameter(1));
824   fsxD.SetParameter(2, f.GetParameter(2));
825   TF1 expo("fexpo", "expo", 0., 3.5);
826   h1->Fit(&expo, "QN");
827   fsxD.SetParameter(3, expo.GetParameter(0));
828   fsxD.SetParameter(4, expo.GetParameter(1));
829   h1->Fit(&fsxD, "Q");
830   printf("  const Float_t sxgc = %5.3e;\n", fsxD.GetParameter(0));
831   printf("  const Float_t sxgm = %5.3e;\n", fsxD.GetParameter(1));
832   printf("  const Float_t sxgs = %5.3e;\n", fsxD.GetParameter(2));
833   printf("  const Float_t sxe0 = %5.3e;\n", fsxD.GetParameter(3));
834   printf("  const Float_t sxe1 = %5.3e;\n", fsxD.GetParameter(4));
835   if(fCanvas){
836     fCanvas->cd();
837     h1->Draw("e1"); fsxD.Draw("same");
838     fCanvas->Modified(); fCanvas->Update();
839     if(IsSaveAs()) fCanvas->SaveAs("Figures/ProcessSigma_SX||.gif");
840     else gSystem->Sleep(1000);
841   }
842   
843   // fit sx perpendicular to the drift
844   Int_t nb = 0;
845   TAxis *ay = hsx->GetYaxis();
846   TH1D *hx = hsx->ProjectionX("hsx_px", 1,1);
847   TH1D *hAn = (TH1D*)hx->Clone("hAn"); hAn->Reset();
848   for(Int_t ib = 11; ib<24; ib++, nb++){
849     hx = hsx->ProjectionX("hsx_px", ib, ib);
850     for(Int_t id=1; id<=hx->GetNbinsX(); id++)
851       hx->SetBinContent(id, hx->GetBinContent(id)-fsxD.Eval(ay->GetBinCenter(ib))); 
852     hAn->Add(hx);
853   }
854   TF1 fsxA("fsxA", "pol2", 0., 0.25);
855   hAn->Scale(1./nb);
856   for(Int_t ib=1; ib<=hAn->GetNbinsX(); ib++) hAn->SetBinError(ib, 0.002);
857   hAn->Fit(&fsxA, "Q");
858   printf("  const Float_t sxd0 = %5.3e;\n", fsxA.GetParameter(0));
859   printf("  const Float_t sxd1 = %5.3e;\n", fsxA.GetParameter(1));
860   printf("  const Float_t sxd2 = %5.3e;\n", fsxA.GetParameter(2));
861   if(fCanvas){
862     fCanvas->cd();
863     hAn->Draw("e1"); fsxA.Draw("same");
864     fCanvas->Modified(); fCanvas->Update();
865     if(IsSaveAs()) fCanvas->SaveAs("Figures/ProcessSigma_SXL.gif");
866     else gSystem->Sleep(100);
867   }
868 }
869
870 //_______________________________________________________
871 void AliTRDclusterResolution::ProcessMean()
872 {
873   TObjArray *arr = (TObjArray*)fContainer->At(kMean);
874   if(!arr){
875     AliWarning("Missing dy=f(x_d, d_wire) container");
876     return;
877   }
878   TGraphErrors *gm = new TGraphErrors();
879   TF1 f("f", "gaus", -.5, .5);
880   TF1 line("l", "[0]+[1]*x", -.15, .15);
881   Double_t d(0.), x(0.), dx, dy;
882   TAxis *ax = 0x0;
883   TH1D *h1 = 0x0;
884   TH2I *h2 = 0x0;
885   TH1 *hFrame=0x0;
886
887   TObjArray *arrr = (TObjArray*)fResults->At(kMean);
888   TH2F *hdx = (TH2F*)arrr->At(0);
889   TH2F *hdy = (TH2F*)arrr->At(1);
890   for(Int_t id=1; id<=fAd->GetNbins(); id++){
891     d = fAd->GetBinCenter(id); //[mm]
892     printf(" Doing d = %5.3f [mm]\n", d);
893     for(Int_t it=1; it<=fAt->GetNbins(); it++){
894       x = fAt->GetBinCenter(it); //[mm]
895       Int_t idx = (id-1)*kNTB+it-1;
896       if(!(h2 = (TH2I*)arr->At(idx))) {
897         AliWarning(Form("Missing histo at index idx[%3d] [id[%2d] it[%2d]] xd[%f] d[%f]\n", idx, id, it, x, d));
898         continue;
899       }
900
901       new(gm) TGraphErrors();
902       gm->SetMarkerStyle(7);
903       ax = h2->GetXaxis();
904       for(Int_t ix=1; ix<=ax->GetNbins(); ix++){
905         Double_t dydx = ax->GetBinCenter(ix);
906         h1 = h2->ProjectionY("py", ix, ix);
907         if(h1->GetEntries() < 200) continue;
908         //Adjust(&f, h1);
909         h1->Fit(&f, "QN");
910
911         // Fill <Dy> = f(dydx - h*dzdx)
912         Int_t ip = gm->GetN();
913         gm->SetPoint(ip, dydx, f.GetParameter(1));
914         gm->SetPointError(ip, 0., f.GetParError(1));
915         ip++;
916       }
917       if(gm->GetN()<4) continue;
918
919       gm->Fit(&line, "QN");
920       dx = line.GetParameter(1);
921       Double_t xs = line.GetParameter(0);
922       dy = xs + fExB*dx; // xs = dy - tg(a_L)*dx
923       hdx->SetBinContent(id, it, dx);
924       hdy->SetBinContent(id, it, dy);
925
926       if(!fCanvas) continue;
927       fCanvas->cd();
928       if(!hFrame){ 
929         hFrame=new TH1I("hFrame", "", 100, -.3, .3);
930         hFrame->SetMinimum(-.1);hFrame->SetMaximum(.1);
931         hFrame->SetXTitle("tg#phi-htg#theta");
932         hFrame->SetYTitle("#Deltay[cm]");
933         hFrame->SetLineColor(1);hFrame->SetLineWidth(1);
934         hFrame->Draw();
935       } else hFrame->Reset();
936       gm->Draw("pl"); line.Draw("same");
937       fCanvas->Modified(); fCanvas->Update();
938       if(IsSaveAs()) fCanvas->SaveAs(Form("Figures/ProcessMean_D%d_T%02d.gif", id, it));
939       else gSystem->Sleep(100);
940       printf("    xd=%4.1f[cm] dx=%5.3e[cm] dy=%5.3e[cm] xs=%5.3e[cm]\n", x, dx, dy, xs);
941     }
942   }
943
944   TH1D *h=hdx->ProjectionY("hdx_py"); h->Scale(1./hdx->GetNbinsX());
945   printf("  const Float_t cx[] = {\n    ");
946   for(Int_t ib=1; ib<=h->GetNbinsX(); ib++){
947     printf("%+6.4e, ", h->GetBinContent(ib));
948     if(ib%6==0) printf("\n    ");
949   }
950   printf("  };\n");
951
952   // delete gm; TODO memory leak ?
953 }