dc9d463f3c96242c06a23c2f4f6b4bcb0d343c68
[u/mrichter/AliRoot.git] / ITS / AliITSClusterFinderV2SSD.cxx
1 /**************************************************************************
2  * Copyright(c) 2007-2009, 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-commercial 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$ */
17
18 ////////////////////////////////////////////////////////////////////////////
19 //            Implementation of the ITS clusterer V2 class                //
20 //                                                                        //
21 //          Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch            //
22 //          Last revision: 13-05-09 Enrico Fragiacomo                     //
23 //                                  enrico.fragiacomo@ts.infn.it          //
24 //                                                                        //
25 ///////////////////////////////////////////////////////////////////////////
26
27 #include <Riostream.h>
28 #include "AliLog.h"
29
30 #include "AliITSClusterFinderV2SSD.h"
31 #include "AliITSRecPoint.h"
32 #include "AliITSgeomTGeo.h"
33 #include "AliITSDetTypeRec.h"
34 #include "AliRawReader.h"
35 #include "AliITSRawStreamSSD.h"
36 #include <TClonesArray.h>
37 #include "AliITSdigitSSD.h"
38 #include "AliITSReconstructor.h"
39 #include "AliITSCalibrationSSD.h"
40 #include "AliITSsegmentationSSD.h"
41
42 Short_t *AliITSClusterFinderV2SSD::fgPairs = 0x0;
43 Int_t    AliITSClusterFinderV2SSD::fgPairsSize = 0;
44 const Float_t  AliITSClusterFinderV2SSD::fgkThreshold = 5.;
45
46 const Float_t AliITSClusterFinderV2SSD::fgkCosmic2008StripShifts[16][9] = 
47   {{-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35},  // DDL 512
48    {-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35,-0.35},  // DDL 513
49    {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 514
50    {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 515
51    { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00},  // DDL 516
52    { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00},  // DDL 517
53    {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 518
54    {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 519
55    {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.25,-0.15},  // DDL 520
56    {-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15,-0.15},  // DDL 521
57    {-0.10,-0.10,-0.10,-0.40,-0.40,-0.40,-0.10,-0.10,-0.45},  // DDL 522
58    {-0.10,-0.10,-0.10,-0.35,-0.35,-0.35,-0.10,-0.35,-0.50},  // DDL 523
59    { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00},  // DDL 524
60    { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00},  // DDL 525
61    { 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35},  // DDL 526
62    { 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45}}; // DDL 527
63
64 ClassImp(AliITSClusterFinderV2SSD)
65
66
67 AliITSClusterFinderV2SSD::AliITSClusterFinderV2SSD(AliITSDetTypeRec* dettyp):AliITSClusterFinder(dettyp),
68                                                                              fLastSSD1(AliITSgeomTGeo::GetModuleIndex(6,1,1)-1)
69 {
70 //Default constructor
71
72 }
73  
74 //______________________________________________________________________
75 AliITSClusterFinderV2SSD::AliITSClusterFinderV2SSD(const AliITSClusterFinderV2SSD &cf) : AliITSClusterFinder(cf),                                               fLastSSD1(cf.fLastSSD1)
76 {
77   // Copy constructor
78 }
79
80 //______________________________________________________________________
81 AliITSClusterFinderV2SSD& AliITSClusterFinderV2SSD::operator=(const AliITSClusterFinderV2SSD&  cf ){
82   // Assignment operator
83
84   this->~AliITSClusterFinderV2SSD();
85   new(this) AliITSClusterFinderV2SSD(cf);
86   return *this;
87 }
88
89
90 void AliITSClusterFinderV2SSD::FindRawClusters(Int_t mod){
91
92   //Find clusters V2
93   SetModule(mod);
94   FindClustersSSD(fDigits);
95
96 }
97
98 void AliITSClusterFinderV2SSD::FindClustersSSD(TClonesArray *alldigits) {
99   //------------------------------------------------------------
100   // Actual SSD cluster finder
101   //------------------------------------------------------------
102   Int_t smaxall=alldigits->GetEntriesFast();
103   if (smaxall==0) return;
104
105
106   //---------------------------------------
107   // load recoparam and calibration
108   // 
109   static AliITSRecoParam *repa = NULL;  
110   if(!repa){
111     repa = (AliITSRecoParam*) AliITSReconstructor::GetRecoParam();
112     if(!repa){
113       repa = AliITSRecoParam::GetHighFluxParam();
114       AliWarning("Using default AliITSRecoParam class");
115     }
116   }
117
118   AliITSCalibrationSSD* cal = (AliITSCalibrationSSD*)GetResp(fModule);
119   Float_t gain=0;
120   Float_t noise=0;
121   //---------------------------------------
122
123
124   //------------------------------------
125   // fill the digits array with zero-suppression condition
126   // Signal is converted in KeV
127   //
128   TObjArray digits;
129   for (Int_t i=0;i<smaxall; i++){
130     AliITSdigitSSD *d=(AliITSdigitSSD*)alldigits->UncheckedAt(i);
131
132     if(d->IsSideP()) noise = cal->GetNoiseP(d->GetStripNumber());  
133     else noise = cal->GetNoiseN(d->GetStripNumber());
134     if (d->GetSignal()<3.*noise) continue;
135
136     if(d->IsSideP()) gain = cal->GetGainP(d->GetStripNumber());  
137     else gain = cal->GetGainN(d->GetStripNumber());
138
139     Float_t q=gain*d->GetSignal(); //
140     q=cal->ADCToKeV(q); // converts the charge in KeV from ADC units
141     d->SetSignal(Int_t(q));
142
143     digits.AddLast(d);
144   }
145   Int_t smax = digits.GetEntriesFast();
146   if (smax==0) return;
147   //------------------------------------
148
149   
150   const Int_t kMax=1000;
151   Int_t np=0, nn=0; 
152   Ali1Dcluster pos[kMax], neg[kMax];
153   Float_t y=0., q=0., qmax=0.; 
154   Int_t lab[4]={-2,-2,-2,-2};  
155   Bool_t flag5 = 0;
156   
157   /*
158   cout<<"-----------------------------"<<endl;
159   cout<<"this is module "<<fModule;
160   cout<<endl;
161   cout<<endl;
162   */
163
164   //--------------------------------------------------------
165   // start 1D-clustering from the first digit in the digits array
166   //
167   AliITSdigitSSD *d=(AliITSdigitSSD*)digits.UncheckedAt(0);
168   q += d->GetSignal();
169   y += d->GetCoord2()*d->GetSignal();
170   qmax=d->GetSignal();
171   lab[0]=d->GetTrack(0); lab[1]=d->GetTrack(1); lab[2]=d->GetTrack(2);
172   
173   if(d->IsSideP()) {
174     noise = cal->GetNoiseP(d->GetStripNumber());  
175     gain = cal->GetGainP(d->GetStripNumber());
176   }
177   else {
178     noise = cal->GetNoiseN(d->GetStripNumber());
179     gain = cal->GetGainN(d->GetStripNumber());
180   }  
181   noise*=gain;
182   noise=cal->ADCToKeV(noise); // converts noise in KeV from ADC units
183
184   if(qmax>fgkThreshold*noise) flag5=1; // seed for the cluster
185
186   /*
187   cout<<d->GetSignal()<<" "<<noise<<" "<<flag5<<" "<<
188     d->GetCoord1()<<" "<<d->GetCoord2()<<endl;
189   */
190
191   Int_t curr=d->GetCoord2();
192   Int_t flag=d->GetCoord1();
193
194   // Note: the first side which will be processed is supposed to be the 
195   // P-side which is neg
196   Int_t *n=&nn;
197   Ali1Dcluster *c=neg;
198   if(flag) {n=&np; c=pos;} // in case we have only Nstrips (P was bad!)
199
200   Int_t nd=1;
201   Int_t milab[10];
202   for (Int_t ilab=0;ilab<10;ilab++){
203     milab[ilab]=-2;
204   }
205   milab[0]=d->GetTrack(0); milab[1]=d->GetTrack(1); milab[2]=d->GetTrack(2);
206
207
208   //----------------------------------------------------------
209   // search for neighboring digits
210   //
211   for (Int_t s=1; s<smax; s++) {
212       d=(AliITSdigitSSD*)digits.UncheckedAt(s);      
213       Int_t strip=d->GetCoord2();
214
215       // if digits is not a neighbour or side did not change 
216       // and at least one of the previous digits met the seed condition
217       // then creates a new 1D cluster
218       if ( ( ((strip-curr) > 1) || (flag!=d->GetCoord1()) ) ) {
219
220         if(flag5) {
221           //cout<<"here1"<<endl;
222          c[*n].SetY(y/q);
223          c[*n].SetQ(q);
224          c[*n].SetNd(nd);
225          CheckLabels2(milab);
226          c[*n].SetLabels(milab);
227
228          if(repa->GetUseUnfoldingInClusterFinderSSD()==kTRUE) {
229            // Note: fUseUnfoldingInClusterFinderSSD=kFALSE by default in RecoParam
230
231            //Split suspiciously big cluster
232            if (nd>4&&nd<25) {
233              c[*n].SetY(y/q-0.25*nd);
234              c[*n].SetQ(0.5*q);
235              (*n)++;
236              if (*n==kMax) {
237                Error("FindClustersSSD","Too many 1D clusters !");
238                return;
239              }
240              c[*n].SetY(y/q+0.25*nd);
241              c[*n].SetQ(0.5*q);
242              c[*n].SetNd(nd);
243              c[*n].SetLabels(milab);
244            }     
245            
246          } // unfolding is on
247
248          (*n)++;
249          if (*n==kMax) {
250           Error("FindClustersSSD","Too many 1D clusters !");
251           return;
252          }
253
254         } // flag5 set
255
256          // reset everything
257          y=q=qmax=0.;
258          nd=0;
259          flag5=0;
260          lab[0]=lab[1]=lab[2]=-2;
261          for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
262
263          // if side changed from P to N, switch to pos 1D clusters
264          // (if for some reason the side changed from N to P then do the opposite)
265          if (flag!=d->GetCoord1()) 
266            { if(!flag) {n=&np; c=pos;} else {n=&nn; c=neg;} }
267
268       } // end create new 1D cluster from previous neighboring digits
269
270       // continues adding digits to the previous cluster 
271       // or start a new one 
272       flag=d->GetCoord1();
273       q += d->GetSignal();
274       y += d->GetCoord2()*d->GetSignal();
275       nd++;
276
277       if(d->IsSideP()) {
278         noise = cal->GetNoiseP(d->GetStripNumber());  
279         gain = cal->GetGainP(d->GetStripNumber());
280       }
281       else {
282         noise = cal->GetNoiseN(d->GetStripNumber());
283         gain = cal->GetGainN(d->GetStripNumber());
284       }
285       noise*=gain;
286       noise=cal->ADCToKeV(noise); // converts the charge in KeV from ADC units
287
288       if(d->GetSignal()>fgkThreshold*noise) flag5=1;
289
290       /*
291   cout<<d->GetSignal()<<" "<<noise<<" "<<flag5<<" "<<
292     d->GetCoord1()<<" "<<d->GetCoord2()<<endl;
293       */
294
295       if (d->GetSignal()>qmax) {
296          qmax=d->GetSignal();
297          lab[0]=d->GetTrack(0); lab[1]=d->GetTrack(1); lab[2]=d->GetTrack(2);
298       }
299       for (Int_t ilab=0;ilab<10;ilab++) {
300         if (d->GetTrack(ilab)>=0) AddLabel(milab, (d->GetTrack(ilab))); 
301       }
302       curr=strip;
303
304
305   } // loop over digits, no more digits in the digits array
306
307
308   // add the last 1D cluster 
309   if(flag5) {
310
311     //  cout<<"here2"<<endl;
312
313     c[*n].SetY(y/q);
314     c[*n].SetQ(q);
315     c[*n].SetNd(nd);
316     c[*n].SetLabels(lab);
317     
318     if(repa->GetUseUnfoldingInClusterFinderSSD()==kTRUE) {
319       
320       //Split suspiciously big cluster
321       if (nd>4 && nd<25) {
322         c[*n].SetY(y/q-0.25*nd);
323         c[*n].SetQ(0.5*q);
324         (*n)++;
325         if (*n==kMax) {
326           Error("FindClustersSSD","Too many 1D clusters !");
327           return;
328         }
329         c[*n].SetY(y/q+0.25*nd);
330         c[*n].SetQ(0.5*q);
331         c[*n].SetNd(nd);
332         c[*n].SetLabels(lab);
333       }
334     } // unfolding is on
335     
336     (*n)++;
337     if (*n==kMax) {
338       Error("FindClustersSSD","Too many 1D clusters !");
339       return;
340     }
341
342   } // if flag5 last 1D cluster added
343
344
345   //------------------------------------------------------
346   // call FindClustersSSD to pair neg and pos 1D clusters 
347   // and create recpoints from the crosses
348   // Note1: neg are Pside and pos are Nside!!
349   // Note2: if there are no Pside digits nn=0 (bad strips!!) (same for Nside)
350   //
351   //  cout<<nn<<" Pside and "<<np<<" Nside clusters"<<endl;
352   FindClustersSSD(neg, nn, pos, np);
353   //
354   //-----------------------------------------------------
355
356 }
357
358
359 void AliITSClusterFinderV2SSD::RawdataToClusters(AliRawReader* rawReader,TClonesArray** clusters){
360
361     //------------------------------------------------------------
362   // This function creates ITS clusters from raw data
363   //------------------------------------------------------------
364   rawReader->Reset();
365   AliITSRawStreamSSD inputSSD(rawReader);
366   FindClustersSSD(&inputSSD,clusters);
367   
368 }
369
370 void AliITSClusterFinderV2SSD::FindClustersSSD(AliITSRawStreamSSD* input, 
371                                         TClonesArray** clusters) 
372 {
373   //------------------------------------------------------------
374   // Actual SSD cluster finder for raw data
375   //------------------------------------------------------------
376
377   static AliITSRecoParam *repa = NULL;
378   if(!repa){
379     repa = (AliITSRecoParam*) AliITSReconstructor::GetRecoParam();
380     if(!repa){
381       repa = AliITSRecoParam::GetHighFluxParam();
382       AliWarning("Using default AliITSRecoParam class");
383     }
384   }
385
386   Int_t nClustersSSD = 0;
387   const Int_t kMax = 1000;
388   Ali1Dcluster clusters1D[2][kMax];
389   Int_t nClusters[2] = {0, 0};
390   Int_t lab[3]={-2,-2,-2};
391   Float_t q = 0.;
392   Float_t y = 0.;
393   Int_t nDigits = 0;
394   Float_t gain=0;
395   Float_t noise=0.;
396   //  Float_t pedestal=0.;
397   Float_t oldnoise=0.;
398   AliITSCalibrationSSD* cal=NULL;
399
400   Int_t matrix[12][1536];
401   Int_t iddl=-1;
402   Int_t iad=-1;
403   Int_t oddl = -1;
404   Int_t oad = -1;
405   Int_t oadc = -1;
406   Int_t ostrip = -1;
407   Int_t osignal = 65535;
408   Int_t n=0;
409   Bool_t next=0;
410
411   // read raw data input stream
412   while (kTRUE) {
413     
414     // reset signal matrix
415     for(Int_t i=0; i<12; i++) { for(Int_t j=0; j<1536; j++) { matrix[i][j] = 65535;} }
416     
417     if((osignal!=65535)&&(ostrip>0)&&(ostrip<1536)) { 
418       n++;
419       matrix[oadc][ostrip] = osignal; // recover data from previous occurence of input->Next() 
420     }
421     
422     // buffer data for ddl=iddl and ad=iad
423     while(kTRUE) {
424         
425       next = input->Next();
426       if((!next)&&(input->flag)) continue;
427       Int_t ddl=input->GetDDL(); 
428       Int_t ad=input->GetAD();
429       Int_t adc = input->GetADC(); adc = (adc<6)? adc : adc - 2;
430       Int_t strip = input->GetStrip();
431       if(input->GetSideFlag()) strip=1535-strip;
432       Int_t signal = input->GetSignal();
433
434       if((ddl==iddl)&&(ad==iad)&&(strip>0)&&(strip<1536)) {n++; matrix[adc][strip] = signal;}
435       else {if ((strip<1536) && (strip>0)) {oddl=iddl; oad=iad; oadc = adc; ostrip = strip; osignal=signal; iddl=ddl; iad=ad; break;}}
436       
437       if(!next)  {oddl=iddl; oad=iad; oadc = adc; ostrip = strip; osignal=signal; iddl=ddl; iad=ad; break;}
438       //break;
439     }
440     
441     // No SSD data
442     if(!next && oddl<0) break;
443     
444     if(n==0) continue; // first occurence
445     n=0; //osignal=0;
446
447     Float_t dStrip = 0;
448     if (repa->GetUseCosmicRunShiftsSSD()) {  // Special condition for 2007/2008 cosmic data
449       dStrip = fgkCosmic2008StripShifts[oddl][oad-1];
450     }
451     if (TMath::Abs(dStrip) > 1.5)
452       AliError(Form("Indexing error ? oddl = %d, dStrip %f\n",oddl,dStrip));
453     // fill 1Dclusters
454     for(Int_t iadc=0; iadc<12; iadc++) {  // loop over ADC index for ddl=oddl and ad=oad
455       
456       Int_t iimod = (oad - 1)  * 12 + iadc;
457       Int_t iModule = AliITSRawStreamSSD::GetModuleNumber(oddl,iimod);
458       if(iModule==-1) continue;
459       cal = (AliITSCalibrationSSD*)GetResp(iModule);
460
461       Bool_t first = 0;
462       Bool_t flag5 = 0;
463       
464       /*
465       for(Int_t istrip=0; istrip<768; istrip++) { // P-side
466         Int_t signal = matrix[iadc][istrip];
467         pedestal = cal->GetPedestalP(istrip);
468         matrix[iadc][istrip]=signal-(Int_t)pedestal;
469       } 
470       */
471
472       /*
473       Float_t cmode=0;
474       for(Int_t l=0; l<6; l++) {
475         cmode=0;
476         for(Int_t n=20; n<108; n++) cmode+=matrix[iadc][l*128+n];
477         cmode/=88.;
478         for(Int_t n=0; n<128; n++) matrix[iadc][l*128+n]-=(Int_t)cmode;
479         
480       }
481       */
482
483       Int_t istrip=0;
484       for(istrip=0; istrip<768; istrip++) { // P-side
485         
486         Int_t signal = TMath::Abs(matrix[iadc][istrip]);
487         
488         oldnoise = noise;
489         noise = cal->GetNoiseP(istrip); if(noise<1.) signal = 65535;
490         if(signal<3*noise) signal = 65535; // in case ZS was not done in hw do it now
491
492         //        if(cal->IsPChannelBad(istrip)) signal=0;
493
494         if (signal!=65535) {
495           gain = cal->GetGainP(istrip);
496           signal = (Int_t) ( signal * gain ); // signal is corrected for gain
497           if(signal>fgkThreshold*noise) flag5=1;
498           signal = (Int_t) cal->ADCToKeV( signal ); // signal is  converted in KeV 
499           
500           q += signal;    // add digit to current cluster
501           y += istrip * signal;   
502           nDigits++;
503           first=1;
504         }
505         
506         else if(first) {
507           
508           if ( (nDigits>0) && flag5 ) {
509             
510             Ali1Dcluster& cluster = clusters1D[0][nClusters[0]++];
511
512             if(q!=0) cluster.SetY(y/q + dStrip);
513             else cluster.SetY(istrip + dStrip -1);
514
515             cluster.SetQ(q);
516             cluster.SetNd(nDigits);
517             cluster.SetLabels(lab);
518             
519             if(repa->GetUseUnfoldingInClusterFinderSSD()==kTRUE) {
520               
521               //Split suspiciously big cluster
522               if (nDigits > 4&&nDigits < 25) {
523                 if(q!=0) cluster.SetY(y/q + dStrip - 0.25*nDigits);
524                 else cluster.SetY(istrip-1 + dStrip - 0.25*nDigits);
525                 cluster.SetQ(0.5*q);
526                 if (nClusters[0] == kMax) {
527                   Error("FindClustersSSD", "Too many 1D clusters !");
528                   return;
529                 }
530                 Ali1Dcluster& cluster2 = clusters1D[0][nClusters[0]++];
531                 if(q!=0) cluster2.SetY(y/q + dStrip + 0.25*nDigits);
532                 else cluster2.SetY(istrip-1 + dStrip + 0.25*nDigits);
533                 cluster2.SetQ(0.5*q);
534                 cluster2.SetNd(nDigits);
535                 cluster2.SetLabels(lab);
536               }
537             } // unfolding is on            
538           }
539           
540           y = q = 0.;
541           nDigits = 0;
542           first=0;
543           flag5=0;
544         }
545         
546       } // loop over strip on P-side
547       
548       // if last strip does have signal
549       if(first) {
550         
551          if ( (nDigits>0) && flag5 ) {
552           
553           Ali1Dcluster& cluster = clusters1D[0][nClusters[0]++];
554
555           if(q!=0) cluster.SetY(y/q + dStrip);
556           else cluster.SetY(istrip - 1 + dStrip);
557
558           cluster.SetQ(q);
559           cluster.SetNd(nDigits);
560           cluster.SetLabels(lab);
561           
562           if(repa->GetUseUnfoldingInClusterFinderSSD()==kTRUE) {
563             
564             //Split suspiciously big cluster
565             if (nDigits > 4&&nDigits < 25) {
566               if(q!=0) cluster.SetY(y/q + dStrip - 0.25*nDigits);
567               else cluster.SetY(istrip-1 + dStrip - 0.25*nDigits);
568               cluster.SetQ(0.5*q);
569               if (nClusters[0] == kMax) {
570                 Error("FindClustersSSD", "Too many 1D clusters !");
571                 return;
572               }
573               Ali1Dcluster& cluster2 = clusters1D[0][nClusters[0]++];
574               if(q!=0) cluster2.SetY(y/q + dStrip + 0.25*nDigits);
575               else cluster2.SetY(istrip-1 + dStrip + 0.25*nDigits);
576               cluster2.SetQ(0.5*q);
577               cluster2.SetNd(nDigits);
578               cluster2.SetLabels(lab);
579             }
580           } // unfolding is on    
581           
582         }
583         y = q = 0.;
584         nDigits = 0;
585         first=0;
586         flag5=0;
587       }
588       
589       /*
590       for(Int_t istrip=768; istrip<1536; istrip++) { // P-side
591         Int_t signal = matrix[iadc][istrip];
592         pedestal = cal->GetPedestalN(1535-istrip);
593         matrix[iadc][istrip]=signal-(Int_t)pedestal;
594       } 
595       */
596
597       /*
598       for(Int_t l=6; l<12; l++) {
599         Float_t cmode=0;
600         for(Int_t n=20; n<108; n++) cmode+=matrix[iadc][l*128+n];
601         cmode/=88.;
602         for(Int_t n=0; n<128; n++) matrix[iadc][l*128+n]-=(Int_t)cmode;
603       }
604       */
605
606       oldnoise = 0.;
607       noise = 0.;
608       Int_t strip=0;
609       for(Int_t iistrip=768; iistrip<1536; iistrip++) { // N-side
610         
611         Int_t signal = TMath::Abs(matrix[iadc][iistrip]);
612         strip = 1535-iistrip;
613
614         oldnoise = noise;
615         noise = cal->GetNoiseN(strip); if(noise<1.) signal=65535;
616
617         //        if(cal->IsNChannelBad(strip)) signal=0;
618
619         if(signal<3*noise) signal = 65535; // in case ZS was not done in hw do it now
620
621         if (signal!=65535) {
622           gain = cal->GetGainN(strip);
623           signal = (Int_t) ( signal * gain); // signal is corrected for gain
624           if(signal>fgkThreshold*noise) flag5=1;
625           signal = (Int_t) cal->ADCToKeV( signal ); // signal is  converted in KeV 
626           
627           // add digit to current cluster
628           q += signal;
629           y += strip * signal;
630           nDigits++;
631           first=1;
632         }
633
634         else if(first) {
635           
636           if ( (nDigits>0) && flag5 ) {
637             
638             Ali1Dcluster& cluster = clusters1D[1][nClusters[1]++];
639
640             if(q!=0) cluster.SetY(y/q - dStrip);
641             else cluster.SetY(strip+1 - dStrip);
642
643             cluster.SetQ(q);
644             cluster.SetNd(nDigits);
645             cluster.SetLabels(lab);
646             
647             if(repa->GetUseUnfoldingInClusterFinderSSD()==kTRUE) {
648
649               //Split suspiciously big cluster
650               if (nDigits > 4&&nDigits < 25) {
651                 cluster.SetY(y/q - dStrip - 0.25*nDigits);
652                 cluster.SetQ(0.5*q);
653                 if (nClusters[1] == kMax) {
654                   Error("FindClustersSSD", "Too many 1D clusters !");
655                   return;
656                 }
657                 Ali1Dcluster& cluster2 = clusters1D[1][nClusters[1]++];
658                 cluster2.SetY(y/q - dStrip + 0.25*nDigits);
659                 cluster2.SetQ(0.5*q);
660                 cluster2.SetNd(nDigits);
661                 cluster2.SetLabels(lab);
662               }       
663             } // unfolding is on
664           } 
665
666           y = q = 0.;
667           nDigits = 0;
668           first=0;        
669         flag5=0;
670         }
671         
672       } // loop over strips on N-side
673
674       if(first) {
675         
676           if ( (nDigits>0) && flag5 ) {
677           
678           Ali1Dcluster& cluster = clusters1D[1][nClusters[1]++];
679           
680           if(q!=0) cluster.SetY(y/q - dStrip);
681           else cluster.SetY(strip - dStrip + 1);
682
683           cluster.SetQ(q);
684           cluster.SetNd(nDigits);
685           cluster.SetLabels(lab);
686           
687           if(repa->GetUseUnfoldingInClusterFinderSSD()==kTRUE) {
688             
689             //Split suspiciously big cluster
690             if (nDigits > 4&&nDigits < 25) {
691               if(q!=0) cluster.SetY(y/q - dStrip - 0.25*nDigits);
692               else cluster.SetY(strip+1 - dStrip - 0.25*nDigits);
693               cluster.SetQ(0.5*q);
694               if (nClusters[1] == kMax) {
695                 Error("FindClustersSSD", "Too many 1D clusters !");
696                 return;
697               }
698               Ali1Dcluster& cluster2 = clusters1D[1][nClusters[1]++];
699               if(q!=0) cluster2.SetY(y/q - dStrip + 0.25*nDigits);
700               else cluster2.SetY(strip+1 - dStrip + 0.25*nDigits);
701               cluster2.SetQ(0.5*q);
702               cluster2.SetNd(nDigits);
703               cluster2.SetLabels(lab);
704             }
705           } // unfolding is on      
706         }
707
708         y = q = 0.;
709         nDigits = 0;
710         first=0;          
711         flag5=0;
712       }
713       
714       // create recpoints
715       if((nClusters[0])&&(nClusters[1])) {
716         
717         clusters[iModule] = new TClonesArray("AliITSRecPoint");
718         fModule = iModule;
719         FindClustersSSD(&clusters1D[0][0], nClusters[0], 
720                         &clusters1D[1][0], nClusters[1], clusters[iModule]);
721         Int_t nClustersn = clusters[iModule]->GetEntriesFast();
722         nClustersSSD += nClustersn;
723       }
724
725       nClusters[0] = nClusters[1] = 0;
726       y = q = 0.;
727       nDigits = 0;
728
729     } // loop over adc
730
731     if(!next) break;
732   }
733   
734   Info("FindClustersSSD", "found clusters in ITS SSD: %d", nClustersSSD);
735 }
736
737 void AliITSClusterFinderV2SSD::
738 FindClustersSSD(Ali1Dcluster* neg, Int_t nn, 
739                 Ali1Dcluster* pos, Int_t np,
740                 TClonesArray *clusters) {
741   //------------------------------------------------------------
742   // Actual SSD cluster finder
743   //------------------------------------------------------------
744
745   const TGeoHMatrix *mT2L=AliITSgeomTGeo::GetTracking2LocalMatrix(fModule);
746
747   //---------------------------------------
748   // load recoparam
749   // 
750   static AliITSRecoParam *repa = NULL;  
751   if(!repa){
752     repa = (AliITSRecoParam*) AliITSReconstructor::GetRecoParam();
753     if(!repa){
754       repa = AliITSRecoParam::GetHighFluxParam();
755       AliWarning("Using default AliITSRecoParam class");
756     }
757   }
758
759   TClonesArray &cl=*clusters;
760   
761   AliITSsegmentationSSD *seg = dynamic_cast<AliITSsegmentationSSD*>(fDetTypeRec->GetSegmentationModel(2));
762   if (fModule>fLastSSD1) 
763     seg->SetLayer(6);
764   else 
765     seg->SetLayer(5);
766
767   Float_t hwSSD = seg->Dx()*1e-4/2;
768   Float_t hlSSD = seg->Dz()*1e-4/2;
769
770   Int_t idet=fNdet[fModule];
771   Int_t ncl=0;
772
773   //
774   Int_t *cnegative = new Int_t[np];  
775   Int_t *cused1 = new Int_t[np];
776   Int_t *negativepair = new Int_t[10*np];
777   Int_t *cpositive = new Int_t[nn];  
778   Int_t *cused2 = new Int_t[nn];  
779   Int_t *positivepair = new Int_t[10*nn];  
780   for (Int_t i=0;i<np;i++) {cnegative[i]=0; cused1[i]=0;}
781   for (Int_t i=0;i<nn;i++) {cpositive[i]=0; cused2[i]=0;}
782   for (Int_t i=0;i<10*np;i++) {negativepair[i]=0;}
783   for (Int_t i=0;i<10*nn;i++) {positivepair[i]=0;}
784
785   if ((np*nn) > fgPairsSize) {
786
787     if (fgPairs) delete [] fgPairs;
788     fgPairsSize = 4*np*nn;
789     fgPairs = new Short_t[fgPairsSize];
790   }
791   memset(fgPairs,0,sizeof(Short_t)*np*nn);
792
793   //
794   // find available pairs
795   //
796   for (Int_t i=0; i<np; i++) {
797     Float_t yp=pos[i].GetY(); 
798     if ( (pos[i].GetQ()>0) && (pos[i].GetQ()<3) ) continue;
799     for (Int_t j=0; j<nn; j++) {
800       if ( (neg[j].GetQ()>0) && (neg[j].GetQ()<3) ) continue;
801       Float_t yn=neg[j].GetY();
802
803       Float_t xt, zt;
804       seg->GetPadCxz(yn, yp, xt, zt);
805       //cout<<yn<<" "<<yp<<" "<<xt<<" "<<zt<<endl;
806       
807       if (TMath::Abs(xt)<hwSSD)
808       if (TMath::Abs(zt)<hlSSD) {
809         Int_t in = i*10+cnegative[i];
810         Int_t ip = j*10+cpositive[j];
811         if ((in < 10*np) && (ip < 10*nn)) {
812           negativepair[in] =j;  //index
813           positivepair[ip] =i;
814           cnegative[i]++;  //counters
815           cpositive[j]++;       
816           fgPairs[i*nn+j]=100;
817         }
818         else
819           AliError(Form("Index out of range: ip=%d, in=%d",ip,in));
820       }
821     }
822   }
823
824   /* //
825   // try to recover points out of but close to the module boundaries 
826   //
827   for (Int_t i=0; i<np; i++) {
828     Float_t yp=pos[i].GetY(); 
829     if ( (pos[i].GetQ()>0) && (pos[i].GetQ()<3) ) continue;
830     for (Int_t j=0; j<nn; j++) {
831       if ( (neg[j].GetQ()>0) && (neg[j].GetQ()<3) ) continue;
832       // if both 1Dclusters have an other cross continue
833       if (cpositive[j]&&cnegative[i]) continue;
834       Float_t yn=neg[j].GetY();
835       
836       Float_t xt, zt;
837       seg->GetPadCxz(yn, yp, xt, zt);
838       
839       if (TMath::Abs(xt)<hwSSD+0.1)
840       if (TMath::Abs(zt)<hlSSD+0.15) {
841         // tag 1Dcluster (eventually will produce low quality recpoint)
842         if (cnegative[i]==0) pos[i].SetNd(100);  // not available pair
843         if (cpositive[j]==0) neg[j].SetNd(100);  // not available pair
844         Int_t in = i*10+cnegative[i];
845         Int_t ip = j*10+cpositive[j];
846         if ((in < 10*np) && (ip < 10*nn)) {
847           negativepair[in] =j;  //index
848           positivepair[ip] =i;
849           cnegative[i]++;  //counters
850           cpositive[j]++;       
851           fgPairs[i*nn+j]=100;
852         }
853         else
854           AliError(Form("Index out of range: ip=%d, in=%d",ip,in));
855       }
856     }
857   }
858   */
859
860   //
861   Float_t lp[6];
862   Int_t milab[10];
863   Double_t ratio;
864   
865
866   if(repa->GetUseChargeMatchingInClusterFinderSSD()==kTRUE) {
867
868
869     //
870     // sign gold tracks
871     //
872     for (Int_t ip=0;ip<np;ip++){
873       Float_t xbest=1000,zbest=1000,qbest=0;
874       //
875       // select gold clusters
876       if ( (cnegative[ip]==1) && cpositive[negativepair[10*ip]]==1){ 
877         Float_t yp=pos[ip].GetY(); 
878         Int_t j = negativepair[10*ip];      
879
880         if( (pos[ip].GetQ()==0) && (neg[j].GetQ() ==0) ) { 
881           // both bad, hence continue;    
882           // mark both as used (to avoid recover at the end)
883           cused1[ip]++; 
884           cused2[j]++;
885           continue;
886         }
887
888         ratio = (pos[ip].GetQ()-neg[j].GetQ())/(pos[ip].GetQ()+neg[j].GetQ());
889         //cout<<"ratio="<<ratio<<endl;
890
891         // charge matching (note that if posQ or negQ is 0 -> ratio=1 and the following condition is met
892         if (TMath::Abs(ratio)>0.2) continue; // note: 0.2=3xsigma_ratio calculated in cosmics tests
893
894         //
895         Float_t yn=neg[j].GetY();
896         
897         Float_t xt, zt;
898         seg->GetPadCxz(yn, yp, xt, zt);
899         
900         xbest=xt; zbest=zt; 
901
902         
903         qbest=0.5*(pos[ip].GetQ()+neg[j].GetQ());
904         if( (pos[ip].GetQ()==0)||(neg[j].GetQ()==0)) qbest*=2; // in case of bad strips on one side keep all charge from the other one
905         
906         {
907           Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
908           mT2L->MasterToLocal(loc,trk);
909           lp[0]=trk[1];
910           lp[1]=trk[2];
911         }
912         lp[4]=qbest;        //Q
913         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
914         for (Int_t ilab=0;ilab<3;ilab++){
915           milab[ilab] = pos[ip].GetLabel(ilab);
916           milab[ilab+3] = neg[j].GetLabel(ilab);
917         }
918         //
919         CheckLabels2(milab);
920         milab[3]=(((ip<<10) + j)<<10) + idet; // pos|neg|det
921         Int_t info[3] = {pos[ip].GetNd(),neg[j].GetNd(),fNlayer[fModule]};
922
923         lp[2]=0.0022*0.0022;  //SigmaY2
924         lp[3]=0.110*0.110;  //SigmaZ2
925         // out-of-diagonal element of covariance matrix
926         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
927         else if ( (info[0]>1) && (info[1]>1) ) { 
928           lp[2]=0.0016*0.0016;  //SigmaY2
929           lp[3]=0.08*0.08;  //SigmaZ2
930           lp[5]=-0.00006;
931         }
932         else {
933           lp[3]=0.093*0.093;
934           if (info[0]==1) { lp[5]=-0.00014;}
935           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
936         }
937
938         AliITSRecPoint * cl2;
939         
940         if(clusters){  // Note clusters != 0 when method is called for rawdata
941           
942           
943           cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);
944           
945           cl2->SetChargeRatio(ratio);           
946           cl2->SetType(1);
947           fgPairs[ip*nn+j]=1;
948
949           if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
950             cl2->SetType(2);
951             fgPairs[ip*nn+j]=2;
952           }
953
954           if(pos[ip].GetQ()==0) cl2->SetType(3);
955           if(neg[j].GetQ()==0) cl2->SetType(4);
956
957           cused1[ip]++;
958           cused2[j]++;
959           
960         }
961         else{ // Note clusters == 0 when method is called for digits
962           
963           cl2 = new AliITSRecPoint(milab,lp,info);      
964           
965           cl2->SetChargeRatio(ratio);           
966           cl2->SetType(1);
967           fgPairs[ip*nn+j]=1;
968
969           if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
970             cl2->SetType(2);
971             fgPairs[ip*nn+j]=2;
972           }
973
974           if(pos[ip].GetQ()==0) cl2->SetType(3);
975           if(neg[j].GetQ()==0) cl2->SetType(4);
976
977           cused1[ip]++;
978           cused2[j]++;
979
980           fDetTypeRec->AddRecPoint(*cl2);
981         }
982         ncl++;
983       }
984     }
985     
986     for (Int_t ip=0;ip<np;ip++){
987       Float_t xbest=1000,zbest=1000,qbest=0;
988       //
989       //
990       // select "silber" cluster
991       if ( cnegative[ip]==1 && cpositive[negativepair[10*ip]]==2){
992         Int_t in  = negativepair[10*ip];
993         Int_t ip2 = positivepair[10*in];
994         if (ip2==ip) ip2 =  positivepair[10*in+1];
995         Float_t pcharge = pos[ip].GetQ()+pos[ip2].GetQ();
996         
997
998
999         ratio = (pcharge-neg[in].GetQ())/(pcharge+neg[in].GetQ());
1000         if ( (TMath::Abs(ratio)<0.2) && (pcharge!=0) ) {
1001           //if ( (TMath::Abs(pcharge-neg[in].GetQ())<30) && (pcharge!=0) ) { // 
1002           
1003           //
1004           // add first pair
1005           if ( (fgPairs[ip*nn+in]==100)&&(pos[ip].GetQ() ) ) {  //
1006             
1007             Float_t yp=pos[ip].GetY(); 
1008             Float_t yn=neg[in].GetY();
1009             
1010             Float_t xt, zt;
1011             seg->GetPadCxz(yn, yp, xt, zt);
1012             
1013             xbest=xt; zbest=zt; 
1014
1015             qbest =pos[ip].GetQ();
1016             Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
1017             mT2L->MasterToLocal(loc,trk);
1018             lp[0]=trk[1];
1019             lp[1]=trk[2];
1020             
1021             lp[4]=qbest;        //Q
1022             for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1023             for (Int_t ilab=0;ilab<3;ilab++){
1024               milab[ilab] = pos[ip].GetLabel(ilab);
1025               milab[ilab+3] = neg[in].GetLabel(ilab);
1026             }
1027             //
1028             CheckLabels2(milab);
1029             ratio = (pos[ip].GetQ()-neg[in].GetQ())/(pos[ip].GetQ()+neg[in].GetQ());
1030             milab[3]=(((ip<<10) + in)<<10) + idet; // pos|neg|det
1031             Int_t info[3] = {pos[ip].GetNd(),neg[in].GetNd(),fNlayer[fModule]};
1032             
1033         lp[2]=0.0022*0.0022;  //SigmaY2
1034         lp[3]=0.110*0.110;  //SigmaZ2
1035         // out-of-diagonal element of covariance matrix
1036         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
1037         else if ( (info[0]>1) && (info[1]>1) ) { 
1038           lp[2]=0.0016*0.0016;  //SigmaY2
1039           lp[3]=0.08*0.08;  //SigmaZ2
1040           lp[5]=-0.00006;
1041         }
1042         else {
1043           lp[3]=0.093*0.093;
1044           if (info[0]==1) { lp[5]=-0.00014;}
1045           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
1046         }
1047
1048             AliITSRecPoint * cl2;
1049             if(clusters){
1050               
1051               cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);
1052               cl2->SetChargeRatio(ratio);       
1053               cl2->SetType(5);
1054               fgPairs[ip*nn+in] = 5;
1055               if ((pos[ip].GetNd()+neg[in].GetNd())>6){ //multi cluster
1056                 cl2->SetType(6);
1057                 fgPairs[ip*nn+in] = 6;
1058               }     
1059             }
1060             else{
1061               cl2 = new AliITSRecPoint(milab,lp,info);
1062               cl2->SetChargeRatio(ratio);       
1063               cl2->SetType(5);
1064               fgPairs[ip*nn+in] = 5;
1065               if ((pos[ip].GetNd()+neg[in].GetNd())>6){ //multi cluster
1066                 cl2->SetType(6);
1067                 fgPairs[ip*nn+in] = 6;
1068               }
1069               
1070               fDetTypeRec->AddRecPoint(*cl2);
1071             }
1072             ncl++;
1073           }
1074           
1075           
1076           //
1077           // add second pair
1078           
1079           //    if (!(cused1[ip2] || cused2[in])){  //
1080           if ( (fgPairs[ip2*nn+in]==100) && (pos[ip2].GetQ()) ) {
1081             
1082             Float_t yp=pos[ip2].GetY();
1083             Float_t yn=neg[in].GetY();
1084             
1085             Float_t xt, zt;
1086             seg->GetPadCxz(yn, yp, xt, zt);
1087             
1088             xbest=xt; zbest=zt; 
1089
1090             qbest =pos[ip2].GetQ();
1091             
1092             Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
1093             mT2L->MasterToLocal(loc,trk);
1094             lp[0]=trk[1];
1095             lp[1]=trk[2];
1096             
1097             lp[4]=qbest;        //Q
1098             for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1099             for (Int_t ilab=0;ilab<3;ilab++){
1100               milab[ilab] = pos[ip2].GetLabel(ilab);
1101               milab[ilab+3] = neg[in].GetLabel(ilab);
1102             }
1103             //
1104             CheckLabels2(milab);
1105             ratio = (pos[ip2].GetQ()-neg[in].GetQ())/(pos[ip2].GetQ()+neg[in].GetQ());
1106             milab[3]=(((ip2<<10) + in)<<10) + idet; // pos|neg|det
1107             Int_t info[3] = {pos[ip2].GetNd(),neg[in].GetNd(),fNlayer[fModule]};
1108             
1109         lp[2]=0.0022*0.0022;  //SigmaY2
1110         lp[3]=0.110*0.110;  //SigmaZ2
1111         // out-of-diagonal element of covariance matrix
1112         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
1113         else if ( (info[0]>1) && (info[1]>1) ) { 
1114           lp[2]=0.0016*0.0016;  //SigmaY2
1115           lp[3]=0.08*0.08;  //SigmaZ2
1116           lp[5]=-0.00006;
1117         }
1118         else {
1119           lp[3]=0.093*0.093;
1120           if (info[0]==1) { lp[5]=-0.00014;}
1121           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
1122         }
1123
1124             AliITSRecPoint * cl2;
1125             if(clusters){
1126               cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);
1127               
1128               cl2->SetChargeRatio(ratio);       
1129               cl2->SetType(5);
1130               fgPairs[ip2*nn+in] =5;
1131               if ((pos[ip2].GetNd()+neg[in].GetNd())>6){ //multi cluster
1132                 cl2->SetType(6);
1133                 fgPairs[ip2*nn+in] =6;
1134               }
1135             }
1136             else{
1137               cl2 = new AliITSRecPoint(milab,lp,info);
1138               cl2->SetChargeRatio(ratio);       
1139               cl2->SetType(5);
1140               fgPairs[ip2*nn+in] =5;
1141               if ((pos[ip2].GetNd()+neg[in].GetNd())>6){ //multi cluster
1142                 cl2->SetType(6);
1143                 fgPairs[ip2*nn+in] =6;
1144               }
1145               
1146               fDetTypeRec->AddRecPoint(*cl2);
1147             }
1148             ncl++;
1149           }
1150           
1151           cused1[ip]++;
1152           cused1[ip2]++;
1153           cused2[in]++;
1154
1155         } // charge matching condition
1156
1157       } // 2 Pside cross 1 Nside
1158     } // loop over Pside clusters
1159     
1160     
1161       
1162       //  
1163     for (Int_t jn=0;jn<nn;jn++){
1164       if (cused2[jn]) continue;
1165       Float_t xbest=1000,zbest=1000,qbest=0;
1166       // select "silber" cluster
1167       if ( cpositive[jn]==1 && cnegative[positivepair[10*jn]]==2){
1168         Int_t ip  = positivepair[10*jn];
1169         Int_t jn2 = negativepair[10*ip];
1170         if (jn2==jn) jn2 =  negativepair[10*ip+1];
1171         Float_t pcharge = neg[jn].GetQ()+neg[jn2].GetQ();
1172         //
1173         
1174
1175         ratio = (pcharge-pos[ip].GetQ())/(pcharge+pos[ip].GetQ());
1176         if ( (TMath::Abs(ratio)<0.2) && (pcharge!=0) ) {
1177
1178           /*
1179         if ( (TMath::Abs(pcharge-pos[ip].GetQ())<30) &&  // charge matching 
1180              (pcharge!=0) ) { // reject combinations of bad strips
1181           */
1182
1183
1184           //
1185           // add first pair
1186           //    if (!(cused1[ip]||cused2[jn])){
1187           if ( (fgPairs[ip*nn+jn]==100) && (neg[jn].GetQ()) ) {  //
1188             
1189             Float_t yn=neg[jn].GetY(); 
1190             Float_t yp=pos[ip].GetY();
1191
1192             Float_t xt, zt;
1193             seg->GetPadCxz(yn, yp, xt, zt);
1194             
1195             xbest=xt; zbest=zt; 
1196
1197             qbest =neg[jn].GetQ();
1198
1199             {
1200               Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
1201               mT2L->MasterToLocal(loc,trk);
1202               lp[0]=trk[1];
1203               lp[1]=trk[2];
1204           }
1205           
1206           lp[4]=qbest;        //Q
1207           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1208           for (Int_t ilab=0;ilab<3;ilab++){
1209             milab[ilab] = pos[ip].GetLabel(ilab);
1210             milab[ilab+3] = neg[jn].GetLabel(ilab);
1211           }
1212           //
1213           CheckLabels2(milab);
1214           ratio = (pos[ip].GetQ()-neg[jn].GetQ())/(pos[ip].GetQ()+neg[jn].GetQ());
1215           milab[3]=(((ip<<10) + jn)<<10) + idet; // pos|neg|det
1216           Int_t info[3] = {pos[ip].GetNd(),neg[jn].GetNd(),fNlayer[fModule]};
1217
1218         lp[2]=0.0022*0.0022;  //SigmaY2
1219         lp[3]=0.110*0.110;  //SigmaZ2
1220         // out-of-diagonal element of covariance matrix
1221         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
1222         else if ( (info[0]>1) && (info[1]>1) ) { 
1223           lp[2]=0.0016*0.0016;  //SigmaY2
1224           lp[3]=0.08*0.08;  //SigmaZ2
1225           lp[5]=-0.00006;
1226         }
1227         else {
1228           lp[3]=0.093*0.093;
1229           if (info[0]==1) { lp[5]=-0.00014;}
1230           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
1231         }
1232
1233           AliITSRecPoint * cl2;
1234           if(clusters){
1235             cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);
1236
1237             cl2->SetChargeRatio(ratio);         
1238             cl2->SetType(7);
1239             fgPairs[ip*nn+jn] =7;
1240             if ((pos[ip].GetNd()+neg[jn].GetNd())>6){ //multi cluster
1241               cl2->SetType(8);
1242               fgPairs[ip*nn+jn]=8;
1243             }
1244
1245           }
1246           else{
1247             cl2 = new AliITSRecPoint(milab,lp,info);
1248             cl2->SetChargeRatio(ratio);         
1249             cl2->SetType(7);
1250             fgPairs[ip*nn+jn] =7;
1251             if ((pos[ip].GetNd()+neg[jn].GetNd())>6){ //multi cluster
1252               cl2->SetType(8);
1253               fgPairs[ip*nn+jn]=8;
1254             }
1255
1256             fDetTypeRec->AddRecPoint(*cl2);
1257           }
1258           ncl++;
1259         }
1260         //
1261         // add second pair
1262         //      if (!(cused1[ip]||cused2[jn2])){
1263         if ( (fgPairs[ip*nn+jn2]==100)&&(neg[jn2].GetQ() ) ) {  //
1264
1265           Float_t yn=neg[jn2].GetY(); 
1266           Double_t yp=pos[ip].GetY(); 
1267
1268           Float_t xt, zt;
1269           seg->GetPadCxz(yn, yp, xt, zt);
1270           
1271           xbest=xt; zbest=zt; 
1272
1273           qbest =neg[jn2].GetQ();
1274
1275           {
1276           Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
1277           mT2L->MasterToLocal(loc,trk);
1278           lp[0]=trk[1];
1279           lp[1]=trk[2];
1280           }
1281
1282           lp[4]=qbest;        //Q
1283           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1284           for (Int_t ilab=0;ilab<3;ilab++){
1285             milab[ilab] = pos[ip].GetLabel(ilab);
1286             milab[ilab+3] = neg[jn2].GetLabel(ilab);
1287           }
1288           //
1289           CheckLabels2(milab);
1290           ratio = (pos[ip].GetQ()-neg[jn2].GetQ())/(pos[ip].GetQ()+neg[jn2].GetQ());
1291           milab[3]=(((ip<<10) + jn2)<<10) + idet; // pos|neg|det
1292           Int_t info[3] = {pos[ip].GetNd(),neg[jn2].GetNd(),fNlayer[fModule]};
1293
1294         lp[2]=0.0022*0.0022;  //SigmaY2
1295         lp[3]=0.110*0.110;  //SigmaZ2
1296         // out-of-diagonal element of covariance matrix
1297         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
1298         else if ( (info[0]>1) && (info[1]>1) ) { 
1299           lp[2]=0.0016*0.0016;  //SigmaY2
1300           lp[3]=0.08*0.08;  //SigmaZ2
1301           lp[5]=-0.00006;
1302         }
1303         else {
1304           lp[3]=0.093*0.093;
1305           if (info[0]==1) { lp[5]=-0.00014;}
1306           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
1307         }
1308
1309           AliITSRecPoint * cl2;
1310           if(clusters){
1311             cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);
1312
1313
1314             cl2->SetChargeRatio(ratio);         
1315             fgPairs[ip*nn+jn2]=7;
1316             cl2->SetType(7);
1317             if ((pos[ip].GetNd()+neg[jn2].GetNd())>6){ //multi cluster
1318               cl2->SetType(8);
1319               fgPairs[ip*nn+jn2]=8;
1320             }
1321             
1322           }
1323           else{
1324             cl2 = new AliITSRecPoint(milab,lp,info);
1325             cl2->SetChargeRatio(ratio);         
1326             fgPairs[ip*nn+jn2]=7;
1327             cl2->SetType(7);
1328             if ((pos[ip].GetNd()+neg[jn2].GetNd())>6){ //multi cluster
1329               cl2->SetType(8);
1330               fgPairs[ip*nn+jn2]=8;
1331             }
1332
1333             fDetTypeRec->AddRecPoint(*cl2);
1334           }
1335
1336           ncl++;
1337         }
1338         cused1[ip]++;
1339         cused2[jn]++;
1340         cused2[jn2]++;
1341
1342         } // charge matching condition
1343
1344       } // 2 Nside cross 1 Pside
1345     } // loop over Pside clusters
1346
1347   
1348     
1349     for (Int_t ip=0;ip<np;ip++){
1350
1351       if(cused1[ip]) continue;
1352
1353
1354       Float_t xbest=1000,zbest=1000,qbest=0;
1355       //
1356       // 2x2 clusters
1357       //
1358       if ( (cnegative[ip]==2) && cpositive[negativepair[10*ip]]==2){ 
1359         Float_t minchargediff =4.;
1360         Float_t minchargeratio =0.2;
1361
1362         Int_t j=-1;
1363         for (Int_t di=0;di<cnegative[ip];di++){
1364           Int_t   jc = negativepair[ip*10+di];
1365           Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
1366           ratio = (pos[ip].GetQ()-neg[jc].GetQ())/(pos[ip].GetQ()+neg[jc].GetQ()); 
1367           //if (TMath::Abs(chargedif)<minchargediff){
1368           if (TMath::Abs(ratio)<0.2){
1369             j =jc;
1370             minchargediff = TMath::Abs(chargedif);
1371             minchargeratio = TMath::Abs(ratio);
1372           }
1373         }
1374         if (j<0) continue;  // not proper cluster      
1375         
1376
1377         Int_t count =0;
1378         for (Int_t di=0;di<cnegative[ip];di++){
1379           Int_t   jc = negativepair[ip*10+di];
1380           Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
1381           if (TMath::Abs(chargedif)<minchargediff+3.) count++;
1382         }
1383         if (count>1) continue;  // more than one "proper" cluster for positive
1384         //
1385         
1386         count =0;
1387         for (Int_t dj=0;dj<cpositive[j];dj++){
1388           Int_t   ic  = positivepair[j*10+dj];
1389           Float_t chargedif = pos[ic].GetQ()-neg[j].GetQ();
1390           if (TMath::Abs(chargedif)<minchargediff+3.) count++;
1391         }
1392         if (count>1) continue;  // more than one "proper" cluster for negative
1393         
1394         Int_t jp = 0;
1395         
1396         count =0;
1397         for (Int_t dj=0;dj<cnegative[jp];dj++){
1398           Int_t   ic = positivepair[jp*10+dj];
1399           Float_t chargedif = pos[ic].GetQ()-neg[jp].GetQ();
1400           if (TMath::Abs(chargedif)<minchargediff+4.) count++;
1401         }
1402         if (count>1) continue;   
1403         if (fgPairs[ip*nn+j]<100) continue;
1404         //
1405         
1406
1407
1408         //almost gold clusters
1409         Float_t yp=pos[ip].GetY(); 
1410         Float_t yn=neg[j].GetY();      
1411         Float_t xt, zt;
1412         seg->GetPadCxz(yn, yp, xt, zt); 
1413         xbest=xt; zbest=zt; 
1414         qbest=0.5*(pos[ip].GetQ()+neg[j].GetQ());
1415         {
1416           Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
1417           mT2L->MasterToLocal(loc,trk);
1418           lp[0]=trk[1];
1419           lp[1]=trk[2];
1420         }
1421         lp[4]=qbest;        //Q
1422         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1423         for (Int_t ilab=0;ilab<3;ilab++){
1424           milab[ilab] = pos[ip].GetLabel(ilab);
1425           milab[ilab+3] = neg[j].GetLabel(ilab);
1426         }
1427         //
1428         CheckLabels2(milab);
1429         if ((neg[j].GetQ()==0)&&(pos[ip].GetQ()==0)) continue; // reject crosses of bad strips!!
1430         ratio = (pos[ip].GetQ()-neg[j].GetQ())/(pos[ip].GetQ()+neg[j].GetQ());
1431         milab[3]=(((ip<<10) + j)<<10) + idet; // pos|neg|det
1432         Int_t info[3] = {pos[ip].GetNd(),neg[j].GetNd(),fNlayer[fModule]};
1433
1434         lp[2]=0.0022*0.0022;  //SigmaY2
1435         lp[3]=0.110*0.110;  //SigmaZ2
1436         // out-of-diagonal element of covariance matrix
1437         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
1438         else if ( (info[0]>1) && (info[1]>1) ) { 
1439           lp[2]=0.0016*0.0016;  //SigmaY2
1440           lp[3]=0.08*0.08;  //SigmaZ2
1441           lp[5]=-0.00006;
1442         }
1443         else {
1444           lp[3]=0.093*0.093;
1445           if (info[0]==1) { lp[5]=-0.00014;}
1446           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
1447         }
1448
1449         AliITSRecPoint * cl2;
1450         if(clusters){
1451           cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);
1452                   
1453           cl2->SetChargeRatio(ratio);           
1454           cl2->SetType(10);
1455           fgPairs[ip*nn+j]=10;
1456           if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
1457             cl2->SetType(11);
1458             fgPairs[ip*nn+j]=11;
1459           }
1460           cused1[ip]++;
1461           cused2[j]++;      
1462         }
1463         else{
1464           cl2 = new AliITSRecPoint(milab,lp,info);
1465           cl2->SetChargeRatio(ratio);           
1466           cl2->SetType(10);
1467           fgPairs[ip*nn+j]=10;
1468           if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
1469             cl2->SetType(11);
1470             fgPairs[ip*nn+j]=11;
1471           }
1472           cused1[ip]++;
1473           cused2[j]++;      
1474           
1475           fDetTypeRec->AddRecPoint(*cl2);
1476         }      
1477         ncl++;
1478         
1479       } // 2X2
1480     } // loop over Pside 1Dclusters
1481
1482
1483
1484     for (Int_t ip=0;ip<np;ip++){
1485
1486       if(cused1[ip]) continue;
1487
1488
1489       Float_t xbest=1000,zbest=1000,qbest=0;
1490       //
1491       // manyxmany clusters
1492       //
1493       if ( (cnegative[ip]<5) && cpositive[negativepair[10*ip]]<5){ 
1494         Float_t minchargediff =4.;
1495         Int_t j=-1;
1496         for (Int_t di=0;di<cnegative[ip];di++){
1497           Int_t   jc = negativepair[ip*10+di];
1498           Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
1499           if (TMath::Abs(chargedif)<minchargediff){
1500             j =jc;
1501             minchargediff = TMath::Abs(chargedif);
1502           }
1503         }
1504         if (j<0) continue;  // not proper cluster      
1505         
1506         Int_t count =0;
1507         for (Int_t di=0;di<cnegative[ip];di++){
1508           Int_t   jc = negativepair[ip*10+di];
1509           Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
1510           if (TMath::Abs(chargedif)<minchargediff+3.) count++;
1511         }
1512         if (count>1) continue;  // more than one "proper" cluster for positive
1513         //
1514         
1515         count =0;
1516         for (Int_t dj=0;dj<cpositive[j];dj++){
1517           Int_t   ic  = positivepair[j*10+dj];
1518           Float_t chargedif = pos[ic].GetQ()-neg[j].GetQ();
1519           if (TMath::Abs(chargedif)<minchargediff+3.) count++;
1520         }
1521         if (count>1) continue;  // more than one "proper" cluster for negative
1522         
1523         Int_t jp = 0;
1524         
1525         count =0;
1526         for (Int_t dj=0;dj<cnegative[jp];dj++){
1527           Int_t   ic = positivepair[jp*10+dj];
1528           Float_t chargedif = pos[ic].GetQ()-neg[jp].GetQ();
1529           if (TMath::Abs(chargedif)<minchargediff+4.) count++;
1530         }
1531         if (count>1) continue;   
1532         if (fgPairs[ip*nn+j]<100) continue;
1533         //
1534         
1535         //almost gold clusters
1536         Float_t yp=pos[ip].GetY(); 
1537         Float_t yn=neg[j].GetY();
1538       
1539
1540         Float_t xt, zt;
1541         seg->GetPadCxz(yn, yp, xt, zt);
1542         
1543         xbest=xt; zbest=zt; 
1544
1545         qbest=0.5*(pos[ip].GetQ()+neg[j].GetQ());
1546
1547         {
1548           Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
1549           mT2L->MasterToLocal(loc,trk);
1550           lp[0]=trk[1];
1551           lp[1]=trk[2];
1552         }
1553         lp[4]=qbest;        //Q
1554         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1555         for (Int_t ilab=0;ilab<3;ilab++){
1556           milab[ilab] = pos[ip].GetLabel(ilab);
1557           milab[ilab+3] = neg[j].GetLabel(ilab);
1558         }
1559         //
1560         CheckLabels2(milab);
1561         if ((neg[j].GetQ()==0)&&(pos[ip].GetQ()==0)) continue; // reject crosses of bad strips!!
1562         ratio = (pos[ip].GetQ()-neg[j].GetQ())/(pos[ip].GetQ()+neg[j].GetQ());
1563         milab[3]=(((ip<<10) + j)<<10) + idet; // pos|neg|det
1564         Int_t info[3] = {pos[ip].GetNd(),neg[j].GetNd(),fNlayer[fModule]};
1565
1566         lp[2]=0.0022*0.0022;  //SigmaY2
1567         lp[3]=0.110*0.110;  //SigmaZ2
1568         // out-of-diagonal element of covariance matrix
1569         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
1570         else if ( (info[0]>1) && (info[1]>1) ) { 
1571           lp[2]=0.0016*0.0016;  //SigmaY2
1572           lp[3]=0.08*0.08;  //SigmaZ2
1573           lp[5]=-0.00006;
1574         }
1575         else {
1576           lp[3]=0.093*0.093;
1577           if (info[0]==1) { lp[5]=-0.00014;}
1578           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
1579         }
1580
1581         AliITSRecPoint * cl2;
1582         if(clusters){
1583           cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);
1584                   
1585           cl2->SetChargeRatio(ratio);           
1586           cl2->SetType(12);
1587           fgPairs[ip*nn+j]=12;
1588           if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
1589             cl2->SetType(13);
1590             fgPairs[ip*nn+j]=13;
1591           }
1592           cused1[ip]++;
1593           cused2[j]++;      
1594         }
1595         else{
1596           cl2 = new AliITSRecPoint(milab,lp,info);
1597           cl2->SetChargeRatio(ratio);           
1598           cl2->SetType(12);
1599           fgPairs[ip*nn+j]=12;
1600           if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
1601             cl2->SetType(13);
1602             fgPairs[ip*nn+j]=13;
1603           }
1604           cused1[ip]++;
1605           cused2[j]++;      
1606           
1607           fDetTypeRec->AddRecPoint(*cl2);
1608         }      
1609         ncl++;
1610         
1611       } // manyXmany
1612     } // loop over Pside 1Dclusters
1613     
1614   } // use charge matching
1615   
1616   
1617   // recover all the other crosses
1618   //  
1619   for (Int_t i=0; i<np; i++) {
1620     Float_t xbest=1000,zbest=1000,qbest=0;
1621     Float_t yp=pos[i].GetY(); 
1622     if ((pos[i].GetQ()>0)&&(pos[i].GetQ()<3)) continue;
1623     for (Int_t j=0; j<nn; j++) {
1624     //    for (Int_t di = 0;di<cpositive[i];di++){
1625     //  Int_t j = negativepair[10*i+di];
1626       if ((neg[j].GetQ()>0)&&(neg[j].GetQ()<3)) continue;
1627
1628       if ((neg[j].GetQ()==0)&&(pos[i].GetQ()==0)) continue; // reject crosses of bad strips!!
1629
1630       if (cused2[j]||cused1[i]) continue;      
1631       if (fgPairs[i*nn+j]>0 &&fgPairs[i*nn+j]<100) continue;
1632       ratio = (pos[i].GetQ()-neg[j].GetQ())/(pos[i].GetQ()+neg[j].GetQ());      
1633       Float_t yn=neg[j].GetY();
1634       
1635       Float_t xt, zt;
1636       seg->GetPadCxz(yn, yp, xt, zt);
1637       
1638       if (TMath::Abs(xt)<hwSSD)
1639       if (TMath::Abs(zt)<hlSSD) {
1640         xbest=xt; zbest=zt; 
1641
1642         qbest=0.5*(pos[i].GetQ()+neg[j].GetQ());
1643
1644         {
1645         Double_t loc[3]={xbest,0.,zbest},trk[3]={0.,0.,0.};
1646         mT2L->MasterToLocal(loc,trk);
1647         lp[0]=trk[1];
1648         lp[1]=trk[2];
1649         }
1650         lp[4]=qbest;        //Q
1651         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1652         for (Int_t ilab=0;ilab<3;ilab++){
1653           milab[ilab] = pos[i].GetLabel(ilab);
1654           milab[ilab+3] = neg[j].GetLabel(ilab);
1655         }
1656         //
1657         CheckLabels2(milab);
1658         milab[3]=(((i<<10) + j)<<10) + idet; // pos|neg|det
1659         Int_t info[3] = {pos[i].GetNd(),neg[j].GetNd(),fNlayer[fModule]};
1660
1661         lp[2]=0.0022*0.0022;  //SigmaY2
1662         lp[3]=0.110*0.110;  //SigmaZ2
1663         // out-of-diagonal element of covariance matrix
1664         if( (info[0]==1) && (info[1]==1) ) lp[5]=-0.00012;
1665         else if ( (info[0]>1) && (info[1]>1) ) { 
1666           lp[2]=0.0016*0.0016;  //SigmaY2
1667           lp[3]=0.08*0.08;  //SigmaZ2
1668           lp[5]=-0.00006;
1669         }
1670         else {
1671           lp[3]=0.093*0.093;
1672           if (info[0]==1) { lp[5]=-0.00014;}
1673           else { lp[2]=0.0017*0.0017; lp[5]=-0.00004;}
1674         }
1675
1676         AliITSRecPoint * cl2;
1677         if(clusters){
1678           cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);
1679
1680           cl2->SetChargeRatio(ratio);
1681           cl2->SetType(100+cpositive[j]+cnegative[i]);    
1682
1683           if(pos[i].GetQ()==0) cl2->SetType(200+cpositive[j]+cnegative[i]);
1684           if(neg[j].GetQ()==0) cl2->SetType(300+cpositive[j]+cnegative[i]);
1685
1686         }
1687         else{
1688           cl2 = new AliITSRecPoint(milab,lp,info);
1689           cl2->SetChargeRatio(ratio);
1690           cl2->SetType(100+cpositive[j]+cnegative[i]);
1691           
1692           if(pos[i].GetQ()==0) cl2->SetType(200+cpositive[j]+cnegative[i]);
1693           if(neg[j].GetQ()==0) cl2->SetType(300+cpositive[j]+cnegative[i]);
1694
1695           fDetTypeRec->AddRecPoint(*cl2);
1696         }
1697         ncl++;
1698       }
1699     }
1700   }
1701
1702
1703
1704   if(repa->GetUseBadChannelsInClusterFinderSSD()==kTRUE) {
1705     
1706     //---------------------------------------------------------
1707     // recover crosses of good 1D clusters with bad strips on the other side
1708     // Note1: at first iteration skip modules with a bad side (or almost), (would produce too many fake!) 
1709     // Note2: for modules with a bad side see below 
1710     
1711     AliITSCalibrationSSD* cal = (AliITSCalibrationSSD*)GetResp(fModule);
1712     Int_t countPbad=0, countNbad=0;
1713     for(Int_t ib=0; ib<768; ib++) {
1714       if(cal->IsPChannelBad(ib)) countPbad++;
1715       if(cal->IsNChannelBad(ib)) countNbad++;
1716     }
1717     //  AliInfo(Form("module %d has %d P- and %d N-bad strips",fModule,countPbad,countNbad));
1718     
1719     if( (countPbad<100) && (countNbad<100) ) { // no bad side!!
1720       
1721       for (Int_t i=0; i<np; i++) { // loop over Nside 1Dclusters with no crosses
1722         if(cnegative[i]) continue; // if intersecting Pside clusters continue;
1723         
1724         //      for(Int_t ib=0; ib<768; ib++) { // loop over all Pstrips
1725         for(Int_t ib=15; ib<753; ib++) { // loop over all Pstrips
1726           
1727           if(cal->IsPChannelBad(ib)) { // check if strips is bad
1728             Float_t yN=pos[i].GetY();   
1729             Float_t xt, zt;
1730             seg->GetPadCxz(1.*ib, yN, xt, zt);  
1731             
1732             //----------
1733             // bad Pstrip is crossing the Nside 1Dcluster -> create recpoint
1734             // 
1735             if ( (TMath::Abs(xt)<hwSSD) && (TMath::Abs(zt)<hlSSD) ) {
1736               Double_t loc[3]={xt,0.,zt},trk[3]={0.,0.,0.};
1737               mT2L->MasterToLocal(loc,trk);
1738               lp[0]=trk[1];
1739               lp[1]=trk[2];        
1740               lp[4]=pos[i].GetQ(); //Q
1741               for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1742               for (Int_t ilab=0;ilab<3;ilab++) milab[ilab] = pos[i].GetLabel(ilab);       
1743               CheckLabels2(milab);
1744               milab[3]=( (i<<10) << 10 ) + idet; // pos|neg|det
1745               Int_t info[3] = {pos[i].GetNd(),0,fNlayer[fModule]};
1746               
1747               // out-of-diagonal element of covariance matrix
1748               if (info[0]==1) lp[5]=0.0065;
1749               else lp[5]=0.0093;
1750               
1751               lp[2]=0.0022*0.0022;  //SigmaY2
1752               lp[3]=0.110*0.110;  //SigmaZ2
1753               lp[5]=-0.00012; // out-of-diagonal element of covariance matrix
1754               
1755               AliITSRecPoint * cl2;
1756               if(clusters){
1757                 cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);          
1758                 cl2->SetChargeRatio(1.);
1759               cl2->SetType(50);   
1760               }
1761               else{
1762                 cl2 = new AliITSRecPoint(milab,lp,info);
1763                 cl2->SetChargeRatio(1.);
1764                 cl2->SetType(50);
1765                 fDetTypeRec->AddRecPoint(*cl2);
1766               }
1767               ncl++;
1768             } // cross is within the detector
1769             //
1770             //--------------
1771             
1772           } // bad Pstrip
1773           
1774         } // end loop over Pstrips
1775         
1776       } // end loop over Nside 1D clusters
1777       
1778       for (Int_t j=0; j<nn; j++) { // loop over Pside 1D clusters with no crosses
1779         if(cpositive[j]) continue;
1780         
1781         //      for(Int_t ib=0; ib<768; ib++) { // loop over all Nside strips
1782         for(Int_t ib=15; ib<753; ib++) { // loop over all Nside strips
1783           
1784           if(cal->IsNChannelBad(ib)) { // check if strip is bad
1785             Float_t yP=neg[j].GetY();   
1786             Float_t xt, zt;
1787             seg->GetPadCxz(yP, 1.*ib, xt, zt);  
1788             
1789             //----------
1790             // bad Nstrip is crossing the Pside 1Dcluster -> create recpoint
1791             // 
1792             if ( (TMath::Abs(xt)<hwSSD) && (TMath::Abs(zt)<hlSSD) ) {
1793               Double_t loc[3]={xt,0.,zt},trk[3]={0.,0.,0.};
1794               mT2L->MasterToLocal(loc,trk);
1795               lp[0]=trk[1];
1796               lp[1]=trk[2];        
1797               lp[4]=neg[j].GetQ(); //Q
1798               for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1799               for (Int_t ilab=0;ilab<3;ilab++) milab[ilab] = neg[j].GetLabel(ilab);       
1800               CheckLabels2(milab);
1801               milab[3]=( j << 10 ) + idet; // pos|neg|det
1802               Int_t info[3]={0,(Int_t)neg[j].GetNd(),fNlayer[fModule]};
1803               
1804               lp[2]=0.0022*0.0022;  //SigmaY2
1805               lp[3]=0.110*0.110;  //SigmaZ2
1806               lp[5]=-0.00012; // out-of-diagonal element of covariance matrix
1807               
1808               AliITSRecPoint * cl2;
1809               if(clusters){
1810                 cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);          
1811                 cl2->SetChargeRatio(1.);
1812                 cl2->SetType(60);         
1813               }
1814               else{
1815                 cl2 = new AliITSRecPoint(milab,lp,info);
1816                 cl2->SetChargeRatio(1.);
1817                 cl2->SetType(60);
1818                 fDetTypeRec->AddRecPoint(*cl2);
1819               }
1820               ncl++;
1821             } // cross is within the detector
1822             //
1823             //--------------
1824             
1825           } // bad Nstrip
1826         } // end loop over Nstrips
1827       } // end loop over Pside 1D clusters
1828       
1829     } // no bad sides 
1830     
1831     //---------------------------------------------------------
1832     
1833     else if( (countPbad>700) && (countNbad<100) ) { // bad Pside!!
1834       
1835       for (Int_t i=0; i<np; i++) { // loop over Nside 1Dclusters with no crosses
1836         if(cnegative[i]) continue; // if intersecting Pside clusters continue;
1837         
1838         Float_t xt, zt;
1839         Float_t yN=pos[i].GetY();       
1840         Float_t yP=0.;
1841         if (seg->GetLayer()==5) yP = yN + (7.6/1.9);
1842         else yP = yN - (7.6/1.9);
1843         seg->GetPadCxz(yP, yN, xt, zt); 
1844         
1845         if ( (TMath::Abs(xt)<hwSSD) && (TMath::Abs(zt)<hlSSD) ) {
1846           Double_t loc[3]={xt,0.,zt},trk[3]={0.,0.,0.};
1847           mT2L->MasterToLocal(loc,trk);
1848           lp[0]=trk[1];
1849           lp[1]=trk[2];        
1850           lp[4]=pos[i].GetQ(); //Q
1851           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1852           for (Int_t ilab=0;ilab<3;ilab++) milab[ilab] = pos[i].GetLabel(ilab);   
1853           CheckLabels2(milab);
1854           milab[3]=( (i<<10) << 10 ) + idet; // pos|neg|det
1855           Int_t info[3] = {(Int_t)pos[i].GetNd(),0,fNlayer[fModule]};
1856           
1857           lp[2]=0.031*0.031;  //SigmaY2
1858           lp[3]=1.15*1.15;  //SigmaZ2
1859           lp[5]=-0.036;
1860           
1861           AliITSRecPoint * cl2;
1862           if(clusters){
1863             cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);      
1864             cl2->SetChargeRatio(1.);
1865             cl2->SetType(70);     
1866           }
1867           else{
1868             cl2 = new AliITSRecPoint(milab,lp,info);
1869             cl2->SetChargeRatio(1.);
1870             cl2->SetType(70);
1871             fDetTypeRec->AddRecPoint(*cl2);
1872           }
1873           ncl++;
1874         } // cross is within the detector
1875         //
1876         //--------------
1877         
1878       } // end loop over Nside 1D clusters
1879       
1880     } // bad Pside module
1881     
1882     else if( (countNbad>700) && (countPbad<100) ) { // bad Nside!!
1883       
1884       for (Int_t j=0; j<nn; j++) { // loop over Pside 1D clusters with no crosses
1885         if(cpositive[j]) continue;
1886         
1887         Float_t xt, zt;
1888         Float_t yP=neg[j].GetY();       
1889         Float_t yN=0.;
1890         if (seg->GetLayer()==5) yN = yP - (7.6/1.9);
1891         else yN = yP + (7.6/1.9);
1892         seg->GetPadCxz(yP, yN, xt, zt); 
1893         
1894         if ( (TMath::Abs(xt)<hwSSD) && (TMath::Abs(zt)<hlSSD) ) {
1895           Double_t loc[3]={xt,0.,zt},trk[3]={0.,0.,0.};
1896           mT2L->MasterToLocal(loc,trk);
1897           lp[0]=trk[1];
1898           lp[1]=trk[2];        
1899           lp[4]=neg[j].GetQ(); //Q
1900           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1901           for (Int_t ilab=0;ilab<3;ilab++) milab[ilab] = neg[j].GetLabel(ilab);   
1902           CheckLabels2(milab);
1903           milab[3]=( j << 10 ) + idet; // pos|neg|det
1904           Int_t info[3] = {0,(Int_t)neg[j].GetNd(),fNlayer[fModule]};
1905           
1906           lp[2]=0.0085*0.0085;  //SigmaY2
1907           lp[3]=1.15*1.15;  //SigmaZ2
1908           lp[5]=0.0093;
1909           
1910           AliITSRecPoint * cl2;
1911           if(clusters){
1912             cl2 = new (cl[ncl]) AliITSRecPoint(milab,lp,info);      
1913             cl2->SetChargeRatio(1.);
1914             cl2->SetType(80);     
1915           }
1916           else{
1917             cl2 = new AliITSRecPoint(milab,lp,info);
1918             cl2->SetChargeRatio(1.);
1919             cl2->SetType(80);
1920             fDetTypeRec->AddRecPoint(*cl2);
1921           }
1922           ncl++;
1923         } // cross is within the detector
1924         //
1925         //--------------
1926         
1927       } // end loop over Pside 1D clusters
1928       
1929     } // bad Nside module
1930     
1931     //---------------------------------------------------------
1932     
1933   } // use bad channels
1934     
1935   //cout<<ncl<<" clusters for this module"<<endl;
1936
1937   delete [] cnegative;
1938   delete [] cused1;
1939   delete [] negativepair;
1940   delete [] cpositive;
1941   delete [] cused2;
1942   delete [] positivepair;
1943
1944 }