]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDtrackletOflHelper.cxx
initialize x,y,z such to avoid unconditional jump (bug #81839)
[u/mrichter/AliRoot.git] / TRD / AliTRDtrackletOflHelper.cxx
1 #include "TObjArray.h"
2 #include "TMath.h"
3
4 #include "AliLog.h"
5 #include "AliMathBase.h"
6
7 #include "AliTRDseedV1.h"
8 #include "AliTRDcluster.h"
9 #include "AliTRDpadPlane.h"
10 #include "AliTRDtrackletOflHelper.h"
11
12 ClassImp(AliTRDtrackletOflHelper)
13 //___________________________________________________________________
14 AliTRDtrackletOflHelper::AliTRDtrackletOflHelper() 
15   :TObject()
16   ,fRow(-1)
17   ,fClusters(NULL)
18   ,fPadPlane(NULL)
19 {
20 // Default constructor
21   fCol[0]=144; fCol[1]=0;
22   fTBrange[0]=1; fTBrange[1]=21;
23 }
24
25 //___________________________________________________________________
26 AliTRDtrackletOflHelper::AliTRDtrackletOflHelper(const AliTRDtrackletOflHelper &ref) 
27   :TObject(ref)
28   ,fRow(-1)
29   ,fClusters(NULL)
30   ,fPadPlane(ref.fPadPlane)
31 {
32 // Copy constructor
33   fRow = ref.fRow; fCol[0]=ref.fCol[0]; fCol[1]=ref.fCol[1];
34   fTBrange[0] = ref.fTBrange[0];fTBrange[1] = ref.fTBrange[1];
35   Int_t n(0);
36   if(ref.fClusters){
37     if((n = ref.fClusters->GetEntriesFast())) {
38       fClusters = new TObjArray(n);
39       for(Int_t ic(n); ic--;) fClusters->AddAt(ref.fClusters->At(ic), ic);
40     }
41   }
42 }
43
44 //___________________________________________________________________
45 AliTRDtrackletOflHelper& AliTRDtrackletOflHelper::operator=(const AliTRDtrackletOflHelper &rhs)
46 {
47   if(this != &rhs){
48     TObject::operator=(rhs);
49     fPadPlane  = rhs.fPadPlane;
50     fRow       = rhs.fRow;
51     fCol[0]    = rhs.fCol[0];
52     fCol[1]    = rhs.fCol[1];
53     fTBrange[0]= rhs.fTBrange[0];
54     fTBrange[1]= rhs.fTBrange[1];
55     if(rhs.fClusters){ 
56       Int_t n(rhs.fClusters->GetEntriesFast());
57       if(!fClusters) fClusters = new TObjArray(n);
58       if(fClusters->GetEntriesFast() != n){ 
59         fClusters->Clear();
60         fClusters->Expand(n);
61       }
62       for(Int_t ic(n); ic--;)  fClusters->AddAt(rhs.fClusters->At(ic), ic);
63     } else {
64       if(fClusters) delete fClusters;
65     }
66   }
67   return *this;
68 }
69
70 //___________________________________________________________________
71 AliTRDtrackletOflHelper::~AliTRDtrackletOflHelper()
72 {
73 // Clean helper  
74   if(fClusters) fClusters->Clear();
75   delete fClusters;
76 }
77
78 //___________________________________________________________________
79 Int_t AliTRDtrackletOflHelper::Expand(TObjArray *cls, Int_t *mark, Int_t groupId)
80 {
81 // Allocate new clusters for this helper.  If a subset of clusters is to be allocated 
82 // this can be specified via the identifier "groupId" which have to be compared 
83 // with individual elements in the array "mark".
84 // 
85 // Return total no. of clusters in helper
86
87   if(!fPadPlane || !fClusters ){
88     AliError("Helper not initialized."); 
89     return 0;
90   }
91   Int_t ncl(fClusters->GetEntriesFast());
92   Int_t mcl(cls->GetEntriesFast());
93   fClusters->Expand(mcl + ncl);
94   fCol[0]=144; fCol[1]=0;
95   AliTRDcluster *c(NULL);
96   for(Int_t icl(0), jcl(ncl); icl<mcl; icl++){
97     if(!(c=(AliTRDcluster*)cls->At(icl))) continue;
98     if(mark && mark[icl]!=groupId) continue;
99     fClusters->AddAt(c, jcl++);
100     Int_t col(c->GetPadCol());
101     Short_t *sig(c->GetSignals());
102     for(Int_t icol(0), jcol(col-3); icol<7; icol++, jcol++){
103       if(sig[icol]==0) continue;
104       if(jcol<fCol[0]) fCol[0]=jcol;
105       if(jcol>fCol[1]) fCol[1]=jcol;
106     }
107   }
108
109   AliDebug(1, Form("Segment[%d] Clusters[%2d] pad[%3d %3d].", groupId, fClusters->GetEntriesFast(), fCol[0], fCol[1]));
110   return fClusters->GetEntriesFast();
111 }
112
113
114 //___________________________________________________________________
115 Int_t AliTRDtrackletOflHelper::Init(AliTRDpadPlane *p, TObjArray *cls, Int_t *mark, Int_t groupId)
116 {
117 // Allocate clusters for this helper.  If a subset of clusters is to be allocated 
118 // this can be specified via the identifier "groupId" which have to be compared 
119 // with individual elements in the array "mark".
120 // 
121 // Return no. of clusters allocated
122
123   if(!p){
124     AliError("PadPlane not initialized."); return 0;
125   }
126   if(!cls){
127     AliError("Cluster array not initialized."); return 0;
128   }
129   Int_t ncl(cls->GetEntriesFast());
130   if(ncl<2){ 
131     AliDebug(1, Form("Segment[%d] failed n[%d].", groupId, ncl)); return 0;
132   }
133   Int_t mcl(ncl);
134   if(mark){
135     mcl = 0;
136     for(Int_t icl(ncl); icl--;) 
137       if(cls->At(icl) && mark[icl]==groupId) mcl++;
138   }  
139   if(mcl<2){ 
140     AliDebug(1, Form("Segment[%d] failed n[%d] in group.", groupId, mcl)); return 0;
141   }
142   if(!fClusters) fClusters = new TObjArray(mcl);
143   else{ 
144     fClusters->Clear();
145     fClusters->Expand(mcl);
146   }
147   fCol[0]=144; fCol[1]=0; fRow=-1;
148   AliTRDcluster *c(NULL);
149   for(Int_t icl(0), jcl(0); icl<ncl; icl++){
150     if(!(c=(AliTRDcluster*)cls->At(icl))) continue;
151     if(mark && mark[icl]!=groupId) continue;
152     fClusters->AddAt(c, jcl++);
153     if(fRow<0) fRow = c->GetPadRow();
154     Int_t col(c->GetPadCol());
155     Short_t *sig(c->GetSignals());
156     for(Int_t icol(0), jcol(col-3); icol<7; icol++, jcol++){
157       if(sig[icol]==0) continue;
158       if(jcol<fCol[0]) fCol[0]=jcol;
159       if(jcol>fCol[1]) fCol[1]=jcol;
160     }
161   }
162   fPadPlane = p;
163   
164   AliDebug(1, Form("Segment[%d] Clusters[%2d] pad[%3d %3d].", groupId, fClusters->GetEntriesFast(), fCol[0], fCol[1]));
165   return fClusters->GetEntriesFast();
166 }
167
168 //___________________________________________________________________
169 Int_t AliTRDtrackletOflHelper::ClassifyTopology()
170 {
171 // Classify topology and return classification code
172 // 0 - normal tracklet
173 // 1 - delta ray candidate
174 // 2 - secondary candidate
175 // 3 - "elephant" candidate
176 // 4 - unknown topology
177
178   if(!fClusters){ 
179     AliError("Helper not initialized. Missing clusters.");
180     return kUnknown;
181   }
182   Int_t ncl(fClusters->GetEntries());
183   if(!ncl){ 
184     AliError("Helper not initialized. No cluster allocated.");
185     return kUnknown;
186   }
187   const Int_t kRange(22); // DEFINE based on vd 
188   
189   // compute local occupancy
190   Int_t localOccupancy[AliTRDseedV1::kNtb]; memset(localOccupancy, 0, AliTRDseedV1::kNtb*sizeof(Int_t));
191   AliTRDcluster *c(NULL);
192   Double_t sy[kNcls]; Int_t mcl(0);
193   for(Int_t icl(ncl), time; icl--;){
194     c = (AliTRDcluster*)fClusters->At(icl);
195     time = c->GetPadTime();
196     if(time==0 || time>=kRange){
197       sy[icl] = -1; // mark clusters outsde drift volume
198       continue;
199     }
200     // protect against wrong error param.
201     if(c->GetSigmaY2() < 1.e-5) sy[icl] = 0.02;
202     else sy[icl] = TMath::Min(TMath::Sqrt(c->GetSigmaY2()), 0.04);
203     localOccupancy[time]++;
204     mcl++;
205   }
206   if(!mcl){
207     AliWarning("No clusters in the active area.");
208     return kUnknown;
209   } 
210   //compute number of 0 bins and high occupancy
211   Int_t goodOccupancy(0), highOccupancy(0), lowOccupancy(0);
212   for(Int_t itb(1); itb<kRange; itb++){
213     switch(localOccupancy[itb]){ 
214       case 0: lowOccupancy++; break;
215       case 1: goodOccupancy++; break;
216       default: highOccupancy++; break;
217     }
218   }
219   AliDebug(2, Form("H[%2d | %5.2f%%] L[%2d | %5.2f%%] N[%2d | %5.2f%% | %5.2f%%]",
220           highOccupancy, 100.*highOccupancy/kRange, 
221           lowOccupancy, 100.*lowOccupancy/kRange, 
222           goodOccupancy, 100.*goodOccupancy/kRange, 100.*goodOccupancy/mcl));
223   
224   // filter
225   Double_t dy[kNcls];
226   if(goodOccupancy==mcl) return kNormal;
227   else if(Double_t(goodOccupancy)/kRange > 0.9){
228     if(highOccupancy == 0 ) {
229       if(!FitPSR(dy)) return kUnknown;
230       Int_t nin(0);
231       for(Int_t idy(ncl); idy--;){
232         if(sy[idy]<0.) continue;
233         if(dy[idy] > 3*sy[idy]) continue;
234         nin ++;
235       }
236       if(Double_t(nin)/mcl > 0.8) return kNormal;
237       else return kUnknown;
238     } else return kDeltaRay;
239   } else return kUnknown;
240 }
241
242
243 //___________________________________________________________________
244 void AliTRDtrackletOflHelper::FindSolidCls(Bool_t *mark, Int_t *q)
245 {
246 //  Find clusters produced by large fluctuations of energy deposits
247 //  Largest charge and well separation from neighbors
248
249   Int_t ntb(AliTRDseedV1::kNtb);
250   Int_t idx[ntb+1];
251   TMath::Sort(ntb, q, idx, kTRUE);
252   Int_t qmax = Int_t(0.3*q[idx[0]]);
253   mark[0] = kFALSE;
254   for(Int_t icl(ntb-5); icl<ntb; icl++) mark[icl] = kFALSE;
255   for(Int_t icl(0); icl<ntb; icl++){
256     Int_t jcl(idx[icl]);
257     if(!mark[jcl]) continue;
258     if(q[jcl-1]>q[jcl] || q[jcl+1]>q[jcl]){
259       mark[jcl] = kFALSE;
260       continue;
261     }
262     if(q[jcl] < qmax){
263       mark[jcl] = kFALSE;
264       continue;
265     }
266     for(Int_t kcl=TMath::Max(0, jcl-2); kcl<jcl+3; kcl++){
267       if(kcl==jcl) continue;
268       mark[kcl] = kFALSE;
269     }
270   }
271 }
272
273 //___________________________________________________________________
274 Bool_t AliTRDtrackletOflHelper::FitPSR(Double_t dy[200], Bool_t useSolid)
275 {
276 // Fit tracklet in Pad System of Reference [PSR] to avoid uncertainty related to 
277 // Lorentz angle correction
278
279   Bool_t mark[200]; memset(mark, 0, 200*sizeof(Bool_t));
280   Int_t q[200]; memset(q, 0, 200*sizeof(Int_t));
281   Int_t ncl(fClusters->GetEntries());
282   AliTRDcluster *c(NULL);
283   for(Int_t icl(ncl); icl--;){
284     c = (AliTRDcluster*)fClusters->At(icl);
285     if(c->GetPadRow() != fRow) continue;
286     Int_t time(c->GetPadTime());
287     mark[time] = kTRUE; q[time] = Int_t(c->GetQ());
288   }
289   if(useSolid) FindSolidCls(mark, q);
290   
291   Double_t 
292     x[AliTRDseedV1::kNtb], y[AliTRDseedV1::kNtb], sy[AliTRDseedV1::kNtb], 
293     xf[AliTRDseedV1::kNtb], yf[AliTRDseedV1::kNtb], syf[AliTRDseedV1::kNtb], 
294     par[3];
295   Int_t jcl(0), kcl(0);
296   for(Int_t icl(0); icl<ncl; icl++){
297     c = (AliTRDcluster*)fClusters->At(icl);
298     if(c->GetPadRow() != fRow) continue;
299     Int_t col(c->GetPadCol());
300     Int_t time(c->GetPadTime());
301     Double_t center(c->GetCenter());
302     Double_t cw(fPadPlane->GetColSize(col));
303     //Double_t corr = AliTRDcluster::GetYcorr(AliTRDgeometry::GetLayer(det), center);
304     y[jcl] = fPadPlane->GetColPos(col) + (.5 + center)*cw /*+ corr*/;
305     x[jcl] = c->GetX();
306     sy[jcl]= TMath::Sqrt(c->GetSigmaY2());
307     if(mark[time]){
308       yf[kcl] = y[jcl];
309       xf[kcl] = x[jcl];
310       syf[kcl]= useSolid ? 0.5/time:sy[jcl];
311       kcl++;
312     } 
313     jcl++;
314   }
315   Fit(kcl, xf, yf, syf, par);
316
317   for(Int_t icl(0); icl<jcl; icl++){
318     Double_t dx(x[icl] - par[2]);
319     dy[icl] = y[icl] - (par[0] + par[1]*dx);
320   }
321   return kTRUE;
322 }
323
324 //___________________________________________________________________
325 Bool_t AliTRDtrackletOflHelper::Fit(Int_t n, Double_t *x, Double_t *y, Double_t *sy, Double_t *par, Double_t sCut,  Double_t *cov)
326 {
327 // Iterative robust tracklet fit 
328   if(n<3) return kFALSE;
329   //compute <x>
330   if(Int_t(par[2])==21122012){ 
331     par[2] = 0.; 
332   } else {
333     par[2] = 0.; for(Int_t ic(n); ic--;) par[2] += x[ic]; par[2] /= n;
334   }
335   AliTRDtrackerV1::AliTRDLeastSquare &f=Fitter();
336   for(Int_t iter(0); iter<3; iter++){
337     f.Reset();
338     Int_t jp(0);
339     for(Int_t ip(0); ip<n; ip++){
340       Double_t dx(x[ip]-par[2]);
341       Double_t dy(y[ip] - (par[0] + par[1]*dx));
342       if(iter && TMath::Abs(dy)>sCut*sy[ip]) continue;
343       f.AddPoint(&dx, y[ip], sy[ip]);
344       jp++;
345     }
346     if(jp<3) continue;
347     if(!f.Eval()) continue;
348     par[0]=f.GetFunctionParameter(0);
349     par[1]=f.GetFunctionParameter(1);
350     if(cov) f.GetCovarianceMatrix(cov);
351     AliDebugGeneral("AliTRDtrackletOflHelper::Fit()", 2, Form("Iter[%d] Ncl[%2d/%2d] par[%f %f %f]", iter, jp, n, par[0], par[1], par[2]));
352   }
353   return kTRUE;
354 }
355
356 //___________________________________________________________________
357 Bool_t AliTRDtrackletOflHelper::Fit(Double_t *par, Double_t sCut) const
358 {
359 // Wrapper for clusters attach to this for static Fit function  
360 //
361   Int_t n(fClusters->GetEntriesFast()), jc(0), dr(0);
362   Double_t corr = TMath::Tan(TMath::DegToRad()*fPadPlane->GetTiltingAngle())*
363                   fPadPlane->GetLengthIPad();
364   Double_t x[kNcls], y[kNcls], sy[kNcls];
365   AliTRDcluster *c(NULL);
366   for(Int_t ic(0); ic<n; ic++){
367     c = (AliTRDcluster*)fClusters->At(ic);
368     if(!c->IsInChamber()) continue;
369     dr = c->GetPadRow() - fRow;
370     x[jc] = c->GetX();
371     y[jc] = c->GetY()+corr*dr;
372     sy[jc]= c->GetSigmaY2()>0?(TMath::Min(TMath::Sqrt(c->GetSigmaY2()), 0.08)):0.08;
373     jc++;
374   }
375   return Fit(jc, x, y, sy, par, sCut);
376 }
377
378 //___________________________________________________________________
379 void AliTRDtrackletOflHelper::GetColSignals(Int_t col, Int_t adc[32], Bool_t mainRow) const
380 {
381   memset(adc, 0, 32*sizeof(Int_t));
382   if(col<fCol[0] || col>fCol[1]) return;
383   
384   AliTRDcluster *cc(NULL);
385   for(Int_t ic(fClusters->GetEntriesFast()); ic--;){
386     cc = (AliTRDcluster*)fClusters->At(ic);
387     if((mainRow && cc->GetPadRow()!=fRow) ||
388        (!mainRow && cc->GetPadRow()==fRow)) continue;
389     Short_t *sig = cc->GetSignals();
390     Int_t padcol(cc->GetPadCol());
391     Int_t time(cc->GetPadTime());
392     for(Int_t icol(0), jcol(padcol-3); icol<7; icol++, jcol++){
393       if(jcol!=col) continue;
394       adc[time]+=sig[icol];
395     }
396   }
397 }
398
399 //___________________________________________________________________
400 Int_t AliTRDtrackletOflHelper::GetRMS(Double_t &r, Double_t &m, Double_t &s, Double_t &xm) const
401 {
402 // Calculate Rotation[r], Mean y[m] (at mean radial position [xm]) and Sigma[s] (of a gaussian distribution in the tracklet [SR])
403 // for clusters attach to this helper. The Rotation and Mean are calculated without tilt correction option.
404 // It returns the number of clusters in 1 sigma cut.
405   
406   Int_t n(fClusters->GetEntriesFast());
407   if(n==2){
408     return n;
409   }
410   
411   Double_t par[3] = {0., 0., 0.};
412   Fit(par);
413   xm= par[2];
414   r = par[1];
415
416   Double_t corr = TMath::Tan(TMath::DegToRad()*fPadPlane->GetTiltingAngle())*
417                   fPadPlane->GetLengthIPad();
418   Double_t y[kNcls];
419   AliTRDcluster *c(NULL);
420   for(Int_t ic(n); ic--;){
421     c = (AliTRDcluster*)fClusters->At(ic);
422     Double_t x(c->GetX() - xm);
423     Int_t dr(c->GetPadRow() - fRow);
424     y[ic] = c->GetY()+corr*dr - (par[0] + par[1]*x);
425   }
426   Double_t m1(0.);
427   AliMathBase::EvaluateUni(n, y, m1, s, 0);
428   m = par[0] + m1;
429   Int_t n0(0);
430   for(Int_t ic(n); ic--;){
431     c = (AliTRDcluster*)fClusters->At(ic);
432     Double_t sy = c->GetSigmaY2()>0?(TMath::Min(TMath::Sqrt(c->GetSigmaY2()), 0.08)):0.08;
433     if(TMath::Abs(y[ic]-m1) <= sy) n0++;
434   }
435   return n0;
436 }
437
438 //___________________________________________________________________
439 Double_t AliTRDtrackletOflHelper::GetSyMean() const
440 {
441 // Calculate mean uncertainty of clusters
442
443   Double_t sym(0.);
444   Int_t n(fClusters->GetEntriesFast());
445   AliTRDcluster *c(NULL);
446   for(Int_t ic(n); ic--;){
447     c = (AliTRDcluster*)fClusters->At(ic);
448     sym += c->GetSigmaY2()>0?(TMath::Min(TMath::Sqrt(c->GetSigmaY2()), 0.08)):0.08;
449   }
450   return sym/=n;
451 }
452
453 //___________________________________________________________________
454 Int_t AliTRDtrackletOflHelper::Segmentation(Int_t n, Double_t *x, Double_t *y, Int_t *Index)
455 {
456 // Segmentation of clusters in the tracklet roads
457 //
458 // The user supply the coordinates of the clusters (x,y) and their number "n". Also
459 // The array "Index" has to be allocated by the user with a size equal or larger than "n".
460 // On return the function returns the number of segments found and the array "Index" i-th element 
461 // is filled with the index of the tracklet segment to which the i-th cluster was assigned too.
462 // 
463 // Observation
464 // The parameter which controls the segmentation is set inside the function "kGapSize" and it is used 
465 // for both "x" and "y" segmentations. An improvement can be a parametrization as function of angle of 
466 // incidence.
467 //
468 // author:
469 // Alex Bercuci <a.bercuci@gsi.de>
470
471   if(!n || !x || !y || !Index){
472     AliErrorGeneral("AliTRDtrackletOflHelper::Segmentation()", "One of the input arrays non initialized.");
473     return 0;
474   }
475   const Int_t kBuffer = 200;
476   if(n>kBuffer){
477     AliWarningGeneral("AliTRDtrackletOflHelper::Segmentation()", Form("Input array size %d exceed buffer %d. Truncate.", n, kBuffer));
478     n = kBuffer;
479   }
480   const Double_t kGapSize(0.2); // cm
481   Int_t ng(0),
482         nc(0);
483   Double_t xx[kBuffer], dy;
484   Int_t idx[kBuffer+1], jdx[kBuffer], kdx[kBuffer];
485   TMath::Sort(n, y, idx);
486   for(Int_t iy(0); iy<n; iy++){
487     dy = iy>0?(TMath::Abs(y[idx[iy-1]]-y[idx[iy]])):0.;
488     if(dy>kGapSize){
489       TMath::Sort(nc, xx, jdx);
490       for(Int_t ic(0), jc0, jc1; ic<nc; ic++){
491         jc0 = ic>0?kdx[jdx[ic-1]]:0;
492         jc1 = kdx[jdx[ic]];
493         dy = TMath::Abs(y[jc0] - y[jc1]);
494         if(ic && dy>kGapSize) ng++;
495         Index[jc1] = ng;
496         AliDebugGeneral("AliTRDtrackletOflHelper::Segmentation()", 4, Form("  y[%2d]=%+f x[%+f] %2d -> %2d -> %2d ng[%2d]", jc1, y[jc1], x[jc1], ic, jdx[ic], jc1, ng));
497       }
498       ng++;
499       nc=0;
500     }
501     xx[nc] = x[idx[iy]];
502     kdx[nc]= idx[iy];
503     AliDebugGeneral("AliTRDtrackletOflHelper::Segmentation()", 4, Form("y[%2d]=%+f -> %2d", idx[iy], y[idx[iy]], nc));
504     nc++;
505   }
506   if(nc){
507     TMath::Sort(nc, xx, jdx);
508     for(Int_t ic(0), jc0, jc1; ic<nc; ic++){
509       jc0 = ic>0?kdx[jdx[ic-1]]:0;
510       jc1 = kdx[jdx[ic]];
511       dy = TMath::Abs(y[jc0] - y[jc1]);
512       if(ic && dy>kGapSize) ng++;
513       Index[jc1] = ng;
514       AliDebugGeneral("AliTRDtrackletOflHelper::Segmentation()", 4, Form("  y[%2d]=%+f x[%+f|%+f] %2d -> %2d -> %2d ng[%2d]\n", jc1, y[jc1], xx[jdx[ic]], x[jc1], ic, jdx[ic], jc1, ng));
515     }
516     ng++;
517   }
518   return ng;
519 }
520
521 //___________________________________________________________________
522 void AliTRDtrackletOflHelper::SetTbRange(Float_t t0, Float_t vd)
523 {
524 // Set first time bin and total number of time bins corresponding to clusters 
525 // in chamber based on the calibrated info "t0" and drift velocity "vd"
526
527   // TO CHECK
528   fTBrange[0] = Int_t(t0*0.1);
529   fTBrange[1] = Int_t(vd*0.1);
530 }
531
532 #include "TH2.h"
533 #include "TGraph.h"
534 #include "TGraphErrors.h"
535 #include "TCanvas.h"
536 #include "TLegend.h"
537 #include "TGaxis.h"
538 //___________________________________________________________________
539 void AliTRDtrackletOflHelper::View(TVirtualPad *vpad)
540 {
541 // Visualization support. Draw this tracklet segment  
542
543
544   Int_t row(-1), det(-1);
545   Int_t n(fClusters->GetEntriesFast());
546   AliInfo(Form("Processing Clusters[%2d] Class[%d].", n ,ClassifyTopology()));
547   
548   // prepare drawing objects
549   Int_t ncols(fPadPlane->GetNcols());
550   Double_t cw(fPadPlane->GetColSize(1));
551   TH2 *h2 = new TH2I("h2pm", ";y_{Local} [cm]; pad time;Charge", ncols, fPadPlane->GetColPos(1)-cw, fPadPlane->GetColPos(ncols-1)+cw, 31, -30.5, 0.5);
552   h2->SetMarkerColor(kWhite);h2->SetMarkerSize(2.);
553   h2->SetFillColor(9);
554   
555   TGraph *gcls = new TGraph(n);
556   gcls->SetMarkerColor(kBlack);gcls->SetMarkerStyle(20);
557   TGraph *gclsLC = new TGraph(n);
558   gclsLC->SetMarkerColor(kBlack);gclsLC->SetMarkerStyle(28);
559   TGraph *gclsSC = new TGraph(n);
560   gclsSC->SetMarkerColor(kBlack);gclsSC->SetMarkerStyle(4);gclsSC->SetMarkerSize(1.5);
561   TGraph *gFP = new TGraph(n);
562   gFP->SetMarkerColor(kBlack);gFP->SetLineWidth(2);
563   
564   // fill signal data
565   Bool_t map[200]; memset(map, 0, 200*sizeof(Bool_t));
566   Int_t qa[200]; memset(qa, 0, 200*sizeof(Int_t));
567   AliTRDcluster *cc(NULL); Int_t tm = 30; Double_t ym=0.;
568   for(Int_t ic(n); ic--;){
569     cc = (AliTRDcluster*)fClusters->At(ic);
570     if(cc->GetPadRow() != fRow) continue; //TODO extend for 2 pad rows
571     Short_t *sig = cc->GetSignals();
572     Int_t col(cc->GetPadCol());
573     det = cc->GetDetector();
574     row = cc->GetPadRow();
575     Int_t time(cc->GetPadTime());
576     map[time] = kTRUE; qa[time] = (Int_t)cc->GetQ();
577     for(Int_t ipad(0), jpad(col-2); ipad<7; ipad++, jpad++){
578       Int_t q = (Int_t)h2->GetBinContent(jpad, 31-time);
579       h2->SetBinContent(jpad, 31-time, q+sig[ipad]);
580     }
581     Double_t y0 = fPadPlane->GetColPos(col) + (.5 + cc->GetCenter())*cw;
582     //h2->GetXaxis()->GetBinCenter(pad)+cc->GetCenter();
583     gcls->SetPoint(ic, y0, -time);
584     if(time <= tm) {ym = cc->GetY() - y0; tm = time;}
585   }
586
587   // draw special clusters (solid and Lorentz corrected and fit) 
588   FindSolidCls(map, qa);
589   Double_t ddy[200]; FitPSR(ddy, kTRUE);
590   Double_t dt, dy;
591   for(Int_t ic(0), jc(0); ic<n; ic++){
592     cc = (AliTRDcluster*)fClusters->At(ic);
593     if(cc->GetPadRow() != fRow) continue; //TODO extend for 2 pad rows
594     gcls->GetPoint(ic, dy, dt);
595     gclsLC->SetPoint(ic, cc->GetY()-ym, dt);
596     gFP->SetPoint(ic, dy-ddy[ic], dt);
597     if(map[cc->GetPadTime()]) gclsSC->SetPoint(jc++, dy, dt);
598   }
599   
600   
601   // prepare frame histo
602   h2->SetName(Form("h2s%03d%02d", det, row));
603   Int_t binSrt(fCol[0]+1), binSop(fCol[1]+1);
604   TH1 *h1(NULL);
605   
606   // show everything
607   if(!vpad){ 
608     vpad = new TCanvas(Form("c%03d%02d", det, row), Form("D %03d [%02d_%d_%d] R[%02d]", det, AliTRDgeometry::GetSector(det), AliTRDgeometry::GetStack(det), AliTRDgeometry::GetLayer(det), row), 700, 500);
609   }
610   TVirtualPad *pp(NULL);
611   vpad->Divide(2,1,2.e-5,2.e-5);
612   pp = vpad->cd(1); pp->SetRightMargin(0.0001);pp->SetTopMargin(0.1);pp->SetBorderMode(0); pp->SetFillColor(kWhite);
613   h1 = h2->ProjectionY(); h1->GetYaxis()->SetTitle("Total Charge");
614   h1->SetTitle(Form("D%03d[%02d_%d_%d] R[%02d]", 
615     det,AliTRDgeometry::GetSector(det), AliTRDgeometry::GetStack(det), AliTRDgeometry::GetLayer(det), row));
616   TAxis *ax(h1->GetXaxis()); for(Int_t ib(0), jb(1); ib<ax->GetNbins(); ib++, jb++) ax->SetBinLabel(jb, Form("%d", -Int_t(ax->GetBinCenter(jb))));
617   h1->Draw("hbar3");
618
619   pp = vpad->cd(2);
620   pp->SetRightMargin(0.15);pp->SetLeftMargin(0.0001);pp->SetTopMargin(0.1);
621   pp->SetBorderMode(0); pp->SetFillColor(kWhite);
622   ax=h2->GetXaxis();
623   ax->SetRange(TMath::Max(1, binSrt-1), TMath::Min(ncols, binSop+1));
624   h2->Draw("coltextz");
625   gPad->Update();
626   TGaxis *axis = new TGaxis(gPad->GetUxmin(),
627                     gPad->GetUymax(),
628                     gPad->GetUxmax(),
629                     gPad->GetUymax(),
630                     TMath::Max(0, binSrt-2)-0.5, TMath::Min(ncols-1, binSop)+0.5, 510,"-L");
631
632   axis->SetNdivisions(103+binSop-binSrt);
633   axis->SetTitle("pad col");
634   axis->Draw();
635
636   TLegend *leg = new TLegend(0.01, 0.1, 0.84, 0.21);
637   leg->SetBorderSize(1); leg->SetFillColor(kYellow-9);leg->SetTextSize(0.04);
638   gcls->Draw("p");  leg->AddEntry(gcls, "Cls. in Pad [SR]", "p");
639   gclsLC->Draw("p"); leg->AddEntry(gclsLC, "Lorentz Corr. Cls.", "p");
640   gclsSC->Draw("p"); leg->AddEntry(gclsSC, "Solid Cls.", "p");
641   gFP->Draw("l"); leg->AddEntry(gFP, "Fit in Pad [SR]", "l");
642   leg->Draw();
643 }
644
645 //___________________________________________________________________
646 AliTRDtrackerV1::AliTRDLeastSquare& AliTRDtrackletOflHelper::Fitter()
647 {
648   static AliTRDtrackerV1::AliTRDLeastSquare f;
649   return f;
650 }