]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ITS/AliITSclustererV2.cxx
Fixed some coding violations and warnings. Added some FIXME's
[u/mrichter/AliRoot.git] / ITS / AliITSclustererV2.cxx
1 //-------------------------------------------------------------------------
2 //            Implementation of the ITS clusterer V2 class
3 //
4 //          Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
5 //-------------------------------------------------------------------------
6 //uncomment the line below for running with V1 cluster finder classes 
7 //#define V1
8
9 #include "AliRun.h"
10
11 #include "AliITSclustererV2.h"
12 #include "AliITSclusterV2.h"
13 #include "AliRawReader.h"
14 #include "AliITSRawStreamSPD.h"
15 #include "AliITSRawStreamSDD.h"
16 #include "AliITSRawStreamSSD.h"
17
18 #include <TFile.h>
19 #include <TTree.h>
20 #include <TClonesArray.h>
21 #include "AliITSgeom.h"
22 #include "AliITSdigitSPD.h"
23 #include "AliITSdigitSDD.h"
24 #include "AliITSdigitSSD.h"
25 #include "AliMC.h"
26
27 ClassImp(AliITSclustererV2)
28
29 extern AliRun *gAlice;
30
31 AliITSclustererV2::AliITSclustererV2(const AliITSgeom *geom) {
32   //------------------------------------------------------------
33   // Standard constructor
34   //------------------------------------------------------------
35   AliITSgeom *g=(AliITSgeom*)geom;
36
37   fEvent=0;
38   fI=0;
39
40   Int_t mmax=geom->GetIndexMax();
41   if (mmax>2200) {
42      Fatal("AliITSclustererV2","Too many ITS subdetectors !"); 
43   }
44   Int_t m;
45   for (m=0; m<mmax; m++) {
46      Int_t lay,lad,det; g->GetModuleId(m,lay,lad,det);
47      Float_t x,y,z;     g->GetTrans(lay,lad,det,x,y,z); 
48      Double_t rot[9];   g->GetRotMatrix(lay,lad,det,rot);
49      Double_t alpha=TMath::ATan2(rot[1],rot[0])+TMath::Pi();
50      Double_t ca=TMath::Cos(alpha), sa=TMath::Sin(alpha);
51      fYshift[m] = x*ca + y*sa;
52      fZshift[m] = (Double_t)z;
53      fNdet[m] = (lad-1)*g->GetNdetectors(lay) + (det-1);
54      fNlayer[m] = lay-1;
55   }
56   fNModules = g->GetIndexMax();
57
58   //SPD geometry  
59   fLastSPD1=g->GetModuleIndex(2,1,1)-1;
60   fNySPD=256; fNzSPD=160;
61   fYpitchSPD=0.0050;
62   fZ1pitchSPD=0.0425; fZ2pitchSPD=0.0625;
63   fHwSPD=0.64; fHlSPD=3.48;
64   fYSPD[0]=0.5*fYpitchSPD;
65   for (m=1; m<fNySPD; m++) fYSPD[m]=fYSPD[m-1]+fYpitchSPD; 
66   fZSPD[0]=fZ1pitchSPD;
67   for (m=1; m<fNzSPD; m++) {
68     Double_t dz=fZ1pitchSPD;
69     if (m==31 || m==32 || m==63  || m==64  || m==95 || m==96 || 
70         m==127 || m==128) dz=fZ2pitchSPD; 
71     fZSPD[m]=fZSPD[m-1]+dz;
72   }
73   for (m=0; m<fNzSPD; m++) {
74     Double_t dz=0.5*fZ1pitchSPD;
75     if (m==31 || m==32 || m==63  || m==64  || m==95 || m==96 || 
76         m==127 || m==128) dz=0.5*fZ2pitchSPD; 
77     fZSPD[m]-=dz;
78   }
79
80   //SDD geometry 
81   fNySDD=256; fNzSDD=256;
82   fYpitchSDD=0.01825;
83   fZpitchSDD=0.02940;
84   fHwSDD=3.5085; fHlSDD=3.7632;
85   fYoffSDD=0.0425;
86
87   //SSD geometry
88   fLastSSD1=g->GetModuleIndex(6,1,1)-1;
89   fYpitchSSD=0.0095;
90   fHwSSD=3.65;
91   fHlSSD=2.00;
92   fTanP=0.0275;
93   fTanN=0.0075;
94
95 }
96
97
98 Int_t AliITSclustererV2::Digits2Clusters(TTree *dTree, TTree *cTree) {
99   //------------------------------------------------------------
100   // This function creates ITS clusters
101   //------------------------------------------------------------
102   Int_t ncl=0;
103
104   if (!dTree) {
105     Error("Digits2Clusters","Can't get the tree with digits !");
106     return 1;
107   }
108
109   TClonesArray *digitsSPD=new TClonesArray("AliITSdigitSPD",3000);
110   dTree->SetBranchAddress("ITSDigitsSPD",&digitsSPD);
111   TClonesArray *digitsSDD=new TClonesArray("AliITSdigitSDD",3000);
112   dTree->SetBranchAddress("ITSDigitsSDD",&digitsSDD);
113   TClonesArray *digitsSSD=new TClonesArray("AliITSdigitSSD",3000);
114   dTree->SetBranchAddress("ITSDigitsSSD",&digitsSSD);
115
116   TClonesArray *clusters=new TClonesArray("AliITSclusterV2",1000);
117   TBranch *branch=cTree->GetBranch("Clusters");
118   if (!branch) cTree->Branch("Clusters",&clusters);
119   else branch->SetAddress(&clusters);
120
121   Int_t mmax=(Int_t)dTree->GetEntries();
122
123   for (fI=0; fI<mmax; fI++) {
124     dTree->GetEvent(fI);
125
126     if     (digitsSPD->GetEntriesFast()!=0) 
127       FindClustersSPD(digitsSPD,clusters);
128     else 
129       if(digitsSDD->GetEntriesFast()!=0) 
130         FindClustersSDD(digitsSDD,clusters);
131       else if(digitsSSD->GetEntriesFast()!=0) 
132         FindClustersSSD(digitsSSD,clusters);
133     
134     ncl+=clusters->GetEntriesFast();
135
136     cTree->Fill();
137
138     digitsSPD->Clear();
139     digitsSDD->Clear();
140     digitsSSD->Clear();
141     clusters->Clear();
142   }
143
144   //cTree->Write();
145
146   delete clusters;
147
148   delete digitsSPD;
149   delete digitsSDD;
150   delete digitsSSD;
151
152   //delete dTree;
153
154   Info("Digits2Clusters","Number of found clusters : %d",ncl);
155
156   return 0;
157 }
158
159 void AliITSclustererV2::Digits2Clusters(AliRawReader* rawReader) {
160   //------------------------------------------------------------
161   // This function creates ITS clusters from raw data
162   //------------------------------------------------------------
163   AliRunLoader* runLoader = AliRunLoader::GetRunLoader();
164   if (!runLoader) {
165     Error("Digits2Clusters", "no run loader found");
166     return;
167   }
168   runLoader->LoadKinematics();
169   AliLoader* itsLoader = runLoader->GetLoader("ITSLoader");
170   if (!itsLoader) {
171     Error("Digits2Clusters", "no loader for ITS found");
172     return;
173   }
174   if (!itsLoader->TreeR()) itsLoader->MakeTree("R");
175   TTree* cTree = itsLoader->TreeR();
176
177   TClonesArray *array=new TClonesArray("AliITSclusterV2",1000);
178   cTree->Branch("Clusters",&array);
179   delete array;
180
181   TClonesArray** clusters = new TClonesArray*[fNModules]; 
182   for (Int_t iModule = 0; iModule < fNModules; iModule++) {
183     clusters[iModule] = NULL;
184   }
185   // one TClonesArray per module
186
187   rawReader->Reset();
188   AliITSRawStreamSPD inputSPD(rawReader);
189   FindClustersSPD(&inputSPD, clusters);
190
191   rawReader->Reset();
192   AliITSRawStreamSDD inputSDD(rawReader);
193   FindClustersSDD(&inputSDD, clusters);
194
195   rawReader->Reset();
196   AliITSRawStreamSSD inputSSD(rawReader);
197   FindClustersSSD(&inputSSD, clusters);
198
199   // write all clusters to the tree
200   Int_t nClusters = 0;
201   for (Int_t iModule = 0; iModule < fNModules; iModule++) {
202     array = clusters[iModule];
203     if (!array) {
204       Error("Digits2Clusters", "data for module %d missing!", iModule);
205       array = new TClonesArray("AliITSclusterV2");
206     }
207     cTree->SetBranchAddress("Clusters", &array);
208     cTree->Fill();
209     nClusters += array->GetEntriesFast();
210     delete array;
211   }
212   itsLoader->WriteRecPoints("OVERWRITE");
213
214   delete[] clusters;
215
216   Info("Digits2Clusters", "total number of found clusters in ITS: %d\n", 
217        nClusters);
218 }
219
220 //**** Fast clusters *******************************
221 #include "TParticle.h"
222
223 #include "AliITS.h"
224 #include "AliITSmodule.h"
225 #include "AliITSRecPoint.h"
226 #include "AliITSsimulationFastPoints.h"
227 #include "AliITSRecPoint.h"
228
229 /*
230 static void CheckLabels(Int_t lab[3]) {
231   //------------------------------------------------------------
232   // Tries to find mother's labels
233   //------------------------------------------------------------
234     Int_t label=lab[0];
235     if (label>=0) {
236        TParticle *part=(TParticle*)gAlice->GetMCApp()->Particle(label);
237        label=-3;
238        while (part->P() < 0.005) {
239           Int_t m=part->GetFirstMother();
240           if (m<0) {
241              Info("CheckLabels","Primary momentum: %f",part->P()); 
242              break;
243           }
244           if (part->GetStatusCode()>0) {
245              Info("CheckLabels","Primary momentum: %f",part->P()); 
246              break;
247           }
248           label=m;
249           part=(TParticle*)gAlice->GetMCApp()->Particle(label);
250         }
251         if      (lab[1]<0) lab[1]=label;
252         else if (lab[2]<0) lab[2]=label;
253         else ;//cerr<<"CheckLabels : No empty labels !\n";
254     }
255 }
256 */
257 static void CheckLabels(Int_t lab[3]) {
258   //------------------------------------------------------------
259   // Tries to find mother's labels
260   //------------------------------------------------------------
261
262   if(lab[0]<0 && lab[1]<0 && lab[2]<0) return; // In case of no labels just exit
263
264   Int_t ntracks = gAlice->GetMCApp()->GetNtrack();
265   for (Int_t i=0;i<3;i++){
266     Int_t label = lab[i];
267     if (label>=0 && label<ntracks) {
268       TParticle *part=(TParticle*)gAlice->GetMCApp()->Particle(label);
269       if (part->P() < 0.005) {
270         Int_t m=part->GetFirstMother();
271         if (m<0) {      
272           continue;
273         }
274         if (part->GetStatusCode()>0) {
275           continue;
276         }
277         lab[i]=m;       
278       }
279     }    
280   }
281   
282 }
283
284 static void CheckLabels2(Int_t lab[10]) {
285   //------------------------------------------------------------
286   // Tries to find mother's labels
287   //------------------------------------------------------------
288   Int_t nlabels =0; 
289   for (Int_t i=0;i<10;i++) if (lab[i]>=0) nlabels++;
290   if(nlabels == 0) return; // In case of no labels just exit
291
292   Int_t ntracks = gAlice->GetMCApp()->GetNtrack();
293
294   for (Int_t i=0;i<10;i++){
295     Int_t label = lab[i];
296     if (label>=0 && label<ntracks) {
297       TParticle *part=(TParticle*)gAlice->GetMCApp()->Particle(label);
298       if (part->P() < 0.02) {
299           Int_t m=part->GetFirstMother();
300           if (m<0) {    
301             continue;
302           }
303           if (part->GetStatusCode()>0) {
304             continue;
305           }
306           lab[i]=m;       
307       }
308       else
309         if (part->P() < 0.12 && nlabels>3) {
310           lab[i]=-2;
311           nlabels--;
312         } 
313     }
314     else{
315       if ( (label>ntracks||label <0) && nlabels>3) {
316         lab[i]=-2;
317         nlabels--;
318       } 
319     }
320   }  
321   if (nlabels>3){
322     for (Int_t i=0;i<10;i++){
323       if (nlabels>3){
324         Int_t label = lab[i];
325         if (label>=0 && label<ntracks) {
326           TParticle *part=(TParticle*)gAlice->GetMCApp()->Particle(label);
327           if (part->P() < 0.1) {
328             lab[i]=-2;
329             nlabels--;
330           }
331         }
332       }
333     }
334   }
335
336   //compress labels -- if multi-times the same
337   Int_t lab2[10];
338   for (Int_t i=0;i<10;i++) lab2[i]=-2;
339   for (Int_t i=0;i<10  ;i++){
340     if (lab[i]<0) continue;
341     for (Int_t j=0;j<10 &&lab2[j]!=lab[i];j++){
342       if (lab2[j]<0) {
343         lab2[j]= lab[i];
344         break;
345       }
346     }
347   }
348   for (Int_t j=0;j<10;j++) lab[j]=lab2[j];
349   
350 }
351
352 static void AddLabel(Int_t lab[10], Int_t label) {
353
354   if(label<0) return; // In case of no label just exit
355
356   Int_t ntracks = gAlice->GetMCApp()->GetNtrack();
357   if (label>ntracks) return;
358   for (Int_t i=0;i<10;i++){
359     //    if (label<0) break;
360     if (lab[i]==label) break;
361     if (lab[i]<0) {
362       lab[i]= label;
363       break;
364     }
365   }
366 }
367
368 void AliITSclustererV2::RecPoints2Clusters
369 (const TClonesArray *points, Int_t idx, TClonesArray *clusters) {
370   //------------------------------------------------------------
371   // Conversion AliITSRecPoint -> AliITSclusterV2 for the ITS 
372   // subdetector indexed by idx 
373   //------------------------------------------------------------
374   TClonesArray &cl=*clusters;
375   Int_t ncl=points->GetEntriesFast();
376   for (Int_t i=0; i<ncl; i++) {
377     AliITSRecPoint *p = (AliITSRecPoint *)points->UncheckedAt(i);
378     Float_t lp[5];
379     lp[0]=-(-p->GetX()+fYshift[idx]); if (idx<=fLastSPD1) lp[0]*=-1; //SPD1
380     lp[1]=  -p->GetZ()+fZshift[idx];
381     lp[2]=p->GetSigmaX2();
382     lp[3]=p->GetSigmaZ2();
383     lp[4]=p->GetQ()*36./23333.;  //electrons -> ADC
384     Int_t lab[4]; 
385     lab[0]=p->GetLabel(0); lab[1]=p->GetLabel(1); lab[2]=p->GetLabel(2);
386     lab[3]=fNdet[idx];
387     CheckLabels(lab);
388     Int_t dummy[3]={0,0,0};
389     new (cl[i]) AliITSclusterV2(lab,lp, dummy);
390   }  
391
392
393 Int_t AliITSclustererV2::Hits2Clusters(TTree *hTree, TTree *cTree) {
394   //------------------------------------------------------------
395   // This function creates ITS clusters
396   //------------------------------------------------------------
397   if (!gAlice) {
398      Error("Hits2Clusters","gAlice==0 !");
399      return 1;
400   }
401
402   AliITS *its  = (AliITS*)gAlice->GetModule("ITS");
403   if (!its) { 
404      Error("Hits2Clusters","Can't find the ITS !"); 
405      return 2; 
406   }
407   AliITSgeom *geom=its->GetITSgeom();
408   Int_t mmax=geom->GetIndexMax();
409
410   its->InitModules(-1,mmax);
411   its->FillModules(hTree,0);
412
413   TClonesArray *clusters=new TClonesArray("AliITSclusterV2",1000);
414   TBranch *branch=cTree->GetBranch("Clusters");
415   if (!branch) cTree->Branch("Clusters",&clusters);
416   else branch->SetAddress(&clusters);
417
418   static TClonesArray *points=its->RecPoints();
419   AliITSsimulationFastPoints sim;
420   Int_t ncl=0;
421   for (Int_t m=0; m<mmax; m++) {
422     AliITSmodule *mod=its->GetModule(m);      
423     sim.CreateFastRecPoints(mod,m,gRandom);      
424
425     RecPoints2Clusters(points, m, clusters);
426     its->ResetRecPoints();
427
428     ncl+=clusters->GetEntriesFast();
429     cTree->Fill();
430     clusters->Clear();
431   }
432
433   Info("Hits2Clusters","Number of found fast clusters : %d",ncl);
434
435   //cTree->Write();
436
437   delete clusters;
438
439   return 0;
440 }
441
442 //***********************************
443
444 #ifndef V1
445
446 void AliITSclustererV2:: 
447 FindCluster(Int_t k,Int_t maxz,AliBin *bins,Int_t &n,Int_t *idx) {
448   //------------------------------------------------------------
449   // returns an array of indices of digits belonging to the cluster
450   // (needed when the segmentation is not regular) 
451   //------------------------------------------------------------
452   if (n<200) idx[n++]=bins[k].GetIndex();
453   bins[k].Use();
454
455   if (bins[k-maxz].IsNotUsed()) FindCluster(k-maxz,maxz,bins,n,idx);
456   if (bins[k-1   ].IsNotUsed()) FindCluster(k-1   ,maxz,bins,n,idx);
457   if (bins[k+maxz].IsNotUsed()) FindCluster(k+maxz,maxz,bins,n,idx);
458   if (bins[k+1   ].IsNotUsed()) FindCluster(k+1   ,maxz,bins,n,idx);
459   /*
460   if (bins[k-maxz-1].IsNotUsed()) FindCluster(k-maxz-1,maxz,bins,n,idx);
461   if (bins[k-maxz+1].IsNotUsed()) FindCluster(k-maxz+1,maxz,bins,n,idx);
462   if (bins[k+maxz-1].IsNotUsed()) FindCluster(k+maxz-1,maxz,bins,n,idx);
463   if (bins[k+maxz+1].IsNotUsed()) FindCluster(k+maxz+1,maxz,bins,n,idx);
464   */
465 }
466
467 void AliITSclustererV2::
468 FindClustersSPD(const TClonesArray *digits, TClonesArray *clusters) {
469   //------------------------------------------------------------
470   // Actual SPD cluster finder
471   //------------------------------------------------------------
472   Int_t kNzBins = fNzSPD + 2;
473   const Int_t kMAXBIN=kNzBins*(fNySPD+2);
474
475   Int_t ndigits=digits->GetEntriesFast();
476   AliBin *bins=new AliBin[kMAXBIN];
477
478   Int_t k;
479   AliITSdigitSPD *d=0;
480   for (k=0; k<ndigits; k++) {
481      d=(AliITSdigitSPD*)digits->UncheckedAt(k);
482      Int_t i=d->GetCoord2()+1;   //y
483      Int_t j=d->GetCoord1()+1;
484      bins[i*kNzBins+j].SetIndex(k);
485      bins[i*kNzBins+j].SetMask(1);
486   }
487    
488   Int_t n=0; TClonesArray &cl=*clusters;
489   for (k=0; k<kMAXBIN; k++) {
490      if (!bins[k].IsNotUsed()) continue;
491      Int_t ni=0, idx[200];
492      FindCluster(k,kNzBins,bins,ni,idx);
493      if (ni==200) {
494         Info("FindClustersSPD","Too big cluster !"); 
495         continue;
496      }
497      Int_t milab[10];
498      for (Int_t ilab=0;ilab<10;ilab++){
499        milab[ilab]=-2;
500      }
501
502      d=(AliITSdigitSPD*)digits->UncheckedAt(idx[0]);
503      Int_t ymin=d->GetCoord2(),ymax=ymin;
504      Int_t zmin=d->GetCoord1(),zmax=zmin;
505
506      for (Int_t l=0; l<ni; l++) {
507         d=(AliITSdigitSPD*)digits->UncheckedAt(idx[l]);
508
509         if (ymin > d->GetCoord2()) ymin=d->GetCoord2();
510         if (ymax < d->GetCoord2()) ymax=d->GetCoord2();
511         if (zmin > d->GetCoord1()) zmin=d->GetCoord1();
512         if (zmax < d->GetCoord1()) zmax=d->GetCoord1();
513         // MI addition - find all labels in cluster
514         for (Int_t dlab=0;dlab<10;dlab++){
515           Int_t digitlab = (d->GetTracks())[dlab];
516           if (digitlab<0) continue;
517           AddLabel(milab,digitlab);       
518         }
519         if (milab[9]>0) CheckLabels2(milab);
520      }
521      CheckLabels2(milab);
522      //
523      //Int_t idy = (fNlayer[fI]==0)? 2:3; 
524      //for (Int_t iz=zmin; iz<=zmax;iz+=2)
525      //Int_t idy = (ymax-ymin)/4.; // max 2 clusters
526      Int_t idy = 0; // max 2 clusters
527      if (fNlayer[fI]==0 &&idy<3) idy=3;
528      if (fNlayer[fI]==1 &&idy<4) idy=4; 
529      Int_t idz =3;
530      for (Int_t iz=zmin; iz<=zmax;iz+=idz)
531        for (Int_t iy=ymin; iy<=ymax;iy+=idy){
532          //
533          Int_t ndigits =0;
534          Float_t y=0.,z=0.,q=0.;         
535          for (Int_t l=0; l<ni; l++) {
536            d=(AliITSdigitSPD*)digits->UncheckedAt(idx[l]);
537            if (zmax-zmin>=idz || ymax-ymin>=idy){
538              if (TMath::Abs( d->GetCoord2()-iy)>0.75*idy) continue;
539              if (TMath::Abs( d->GetCoord1()-iz)>0.75*idz) continue;
540            }
541            ndigits++;
542            Float_t qq=d->GetSignal();
543            y+=qq*fYSPD[d->GetCoord2()]; z+=qq*fZSPD[d->GetCoord1()]; q+=qq;   
544           
545          }     
546          if (ndigits==0) continue;
547          y/=q; z/=q;
548          y-=fHwSPD; z-=fHlSPD;
549          
550          Float_t lp[5];
551          lp[0]=-(-y+fYshift[fI]); if (fI<=fLastSPD1) lp[0]=-lp[0];
552          lp[1]=  -z+fZshift[fI];
553          // Float_t factor=TMath::Max(double(ni-3.),1.5);
554          Float_t factory=TMath::Max(ymax-ymin,1);
555          Float_t factorz=TMath::Max(zmax-zmin,1);
556          factory*= factory;
557          factorz*= factorz;     
558          //lp[2]= (fYpitchSPD*fYpitchSPD/12.)*factory;
559          //lp[3]= (fZ1pitchSPD*fZ1pitchSPD/12.)*factorz;
560          lp[2]= (fYpitchSPD*fYpitchSPD/12.);
561          lp[3]= (fZ1pitchSPD*fZ1pitchSPD/12.);
562          //lp[4]= q;
563          lp[4]= (zmax-zmin+1)*100 + (ymax-ymin+1);
564          
565          milab[3]=fNdet[fI];
566          d=(AliITSdigitSPD*)digits->UncheckedAt(idx[0]);
567          Int_t info[3] = {ymax-ymin+1,zmax-zmin+1,fNlayer[fI]};
568          new (cl[n]) AliITSclusterV2(milab,lp,info); n++;        
569        }
570   }
571   
572   delete [] bins;
573 }
574
575 void AliITSclustererV2::FindClustersSPD(AliITSRawStream* input, 
576                                         TClonesArray** clusters) 
577 {
578   //------------------------------------------------------------
579   // Actual SPD cluster finder for raw data
580   //------------------------------------------------------------
581
582   Int_t nClustersSPD = 0;
583   Int_t kNzBins = fNzSPD + 2;
584   Int_t kNyBins = fNySPD + 2;
585   Int_t kMaxBin = kNzBins * kNyBins;
586   AliBin *binsSPD = new AliBin[kMaxBin];
587   AliBin *binsSPDInit = new AliBin[kMaxBin];
588   AliBin *bins = NULL;
589
590   // read raw data input stream
591   while (kTRUE) {
592     Bool_t next = input->Next();
593     if (!next || input->IsNewModule()) {
594       Int_t iModule = input->GetPrevModuleID();
595
596       // when all data from a module was read, search for clusters
597       if (bins) { 
598         clusters[iModule] = new TClonesArray("AliITSclusterV2");
599         Int_t nClusters = 0;
600
601         for (Int_t iBin = 0; iBin < kMaxBin; iBin++) {
602           if (bins[iBin].IsUsed()) continue;
603           Int_t nBins = 0;
604           Int_t idxBins[200];
605           FindCluster(iBin, kNzBins, bins, nBins, idxBins);
606           if (nBins == 200) {
607             Error("FindClustersSPD", "SPD: Too big cluster !\n"); 
608             continue;
609           }
610
611           Int_t label[4]; 
612           label[0] = -2;
613           label[1] = -2;
614           label[2] = -2;
615 //        label[3] = iModule;
616           label[3] = fNdet[iModule];
617
618           Int_t ymin = (idxBins[0] / kNzBins) - 1;
619           Int_t ymax = ymin;
620           Int_t zmin = (idxBins[0] % kNzBins) - 1;
621           Int_t zmax = zmin;
622           for (Int_t idx = 0; idx < nBins; idx++) {
623             Int_t iy = (idxBins[idx] / kNzBins) - 1;
624             Int_t iz = (idxBins[idx] % kNzBins) - 1;
625             if (ymin > iy) ymin = iy;
626             if (ymax < iy) ymax = iy;
627             if (zmin > iz) zmin = iz;
628             if (zmax < iz) zmax = iz;
629           }
630
631           Int_t idy = 0; // max 2 clusters
632           if ((iModule <= fLastSPD1) &&idy<3) idy=3;
633           if ((iModule > fLastSPD1) &&idy<4) idy=4; 
634           Int_t idz =3;
635           for (Int_t iiz=zmin; iiz<=zmax;iiz+=idz)
636             for (Int_t iiy=ymin; iiy<=ymax;iiy+=idy){
637               //
638               Int_t ndigits =0;
639               Float_t y=0.,z=0.,q=0.;    
640               for (Int_t idx = 0; idx < nBins; idx++) {
641                 Int_t iy = (idxBins[idx] / kNzBins) - 1;
642                 Int_t iz = (idxBins[idx] % kNzBins) - 1;
643                 if (zmax-zmin>=idz || ymax-ymin>=idy){
644                   if (TMath::Abs(iy-iiy)>0.75*idy) continue;
645                   if (TMath::Abs(iz-iiz)>0.75*idz) continue;
646                 }
647                 ndigits++;
648                 Float_t qBin = bins[idxBins[idx]].GetQ();
649                 y += qBin * fYSPD[iy]; 
650                 z += qBin * fZSPD[iz]; 
651                 q += qBin;   
652               }
653               if (ndigits==0) continue;
654               y /= q; 
655               z /= q;
656               y -= fHwSPD; 
657               z -= fHlSPD;
658
659               Float_t hit[5];  // y, z, sigma(y)^2, sigma(z)^2, charge
660               hit[0] = -(-y+fYshift[iModule]); 
661               if (iModule <= fLastSPD1) hit[0] = -hit[0];
662               hit[1] = -z+fZshift[iModule];
663               hit[2] = fYpitchSPD*fYpitchSPD/12.;
664               hit[3] = fZ1pitchSPD*fZ1pitchSPD/12.;
665               //          hit[4] = q;
666               hit[4] = (zmax-zmin+1)*100 + (ymax-ymin+1);
667               //          CheckLabels(label);
668               Int_t info[3]={ymax-ymin+1,zmax-zmin+1,fNlayer[iModule]};
669               new (clusters[iModule]->AddrAt(nClusters)) 
670                 AliITSclusterV2(label, hit,info); 
671               nClusters++;
672             }
673         }
674
675         nClustersSPD += nClusters;
676         bins = NULL;
677       }
678
679       if (!next) break;
680       bins = binsSPD;
681       memcpy(binsSPD,binsSPDInit,sizeof(AliBin)*kMaxBin);
682     }
683
684     // fill the current digit into the bins array
685     Int_t index = (input->GetCoord2()+1) * kNzBins + (input->GetCoord1()+1);
686     bins[index].SetIndex(index);
687     bins[index].SetMask(1);
688     bins[index].SetQ(1);
689   }
690
691   delete [] binsSPDInit;
692   delete [] binsSPD;
693
694   Info("FindClustersSPD", "found clusters in ITS SPD: %d", nClustersSPD);
695 }
696
697
698 Bool_t AliITSclustererV2::IsMaximum(Int_t k,Int_t max,const AliBin *bins) {
699   //------------------------------------------------------------
700   //is this a local maximum ?
701   //------------------------------------------------------------
702   UShort_t q=bins[k].GetQ();
703   if (q==1023) return kFALSE;
704   if (bins[k-max].GetQ() > q) return kFALSE;
705   if (bins[k-1  ].GetQ() > q) return kFALSE; 
706   if (bins[k+max].GetQ() > q) return kFALSE; 
707   if (bins[k+1  ].GetQ() > q) return kFALSE; 
708   if (bins[k-max-1].GetQ() > q) return kFALSE;
709   if (bins[k+max-1].GetQ() > q) return kFALSE; 
710   if (bins[k+max+1].GetQ() > q) return kFALSE; 
711   if (bins[k-max+1].GetQ() > q) return kFALSE;
712   return kTRUE; 
713 }
714
715 void AliITSclustererV2::
716 FindPeaks(Int_t k,Int_t max,AliBin *b,Int_t *idx,UInt_t *msk,Int_t& n) {
717   //------------------------------------------------------------
718   //find local maxima
719   //------------------------------------------------------------
720   if (n<31)
721   if (IsMaximum(k,max,b)) {
722     idx[n]=k; msk[n]=(2<<n);
723     n++;
724   }
725   b[k].SetMask(0);
726   if (b[k-max].GetMask()&1) FindPeaks(k-max,max,b,idx,msk,n);
727   if (b[k-1  ].GetMask()&1) FindPeaks(k-1  ,max,b,idx,msk,n);
728   if (b[k+max].GetMask()&1) FindPeaks(k+max,max,b,idx,msk,n);
729   if (b[k+1  ].GetMask()&1) FindPeaks(k+1  ,max,b,idx,msk,n);
730 }
731
732 void AliITSclustererV2::
733 MarkPeak(Int_t k, Int_t max, AliBin *bins, UInt_t m) {
734   //------------------------------------------------------------
735   //mark this peak
736   //------------------------------------------------------------
737   UShort_t q=bins[k].GetQ();
738
739   bins[k].SetMask(bins[k].GetMask()|m); 
740
741   if (bins[k-max].GetQ() <= q)
742      if ((bins[k-max].GetMask()&m) == 0) MarkPeak(k-max,max,bins,m);
743   if (bins[k-1  ].GetQ() <= q)
744      if ((bins[k-1  ].GetMask()&m) == 0) MarkPeak(k-1  ,max,bins,m);
745   if (bins[k+max].GetQ() <= q)
746      if ((bins[k+max].GetMask()&m) == 0) MarkPeak(k+max,max,bins,m);
747   if (bins[k+1  ].GetQ() <= q)
748      if ((bins[k+1  ].GetMask()&m) == 0) MarkPeak(k+1  ,max,bins,m);
749 }
750
751 void AliITSclustererV2::
752 MakeCluster(Int_t k,Int_t max,AliBin *bins,UInt_t m,AliITSclusterV2 &c) {
753   //------------------------------------------------------------
754   //make cluster using digits of this peak
755   //------------------------------------------------------------
756   Float_t q=(Float_t)bins[k].GetQ();
757   Int_t i=k/max, j=k-i*max;
758
759   c.SetQ(c.GetQ()+q);
760   c.SetY(c.GetY()+i*q); 
761   c.SetZ(c.GetZ()+j*q); 
762   c.SetSigmaY2(c.GetSigmaY2()+i*i*q);
763   c.SetSigmaZ2(c.GetSigmaZ2()+j*j*q);
764
765   bins[k].SetMask(0xFFFFFFFE);
766   
767   if (bins[k-max].GetMask() == m) MakeCluster(k-max,max,bins,m,c);
768   if (bins[k-1  ].GetMask() == m) MakeCluster(k-1  ,max,bins,m,c);
769   if (bins[k+max].GetMask() == m) MakeCluster(k+max,max,bins,m,c);
770   if (bins[k+1  ].GetMask() == m) MakeCluster(k+1  ,max,bins,m,c);
771 }
772
773 void AliITSclustererV2::
774 FindClustersSDD(AliBin* bins[2], Int_t nMaxBin, Int_t nzBins, 
775                 const TClonesArray *digits, TClonesArray *clusters) {
776   //------------------------------------------------------------
777   // Actual SDD cluster finder
778   //------------------------------------------------------------
779   Int_t ncl=0; TClonesArray &cl=*clusters;
780   for (Int_t s=0; s<2; s++)
781     for (Int_t i=0; i<nMaxBin; i++) {
782       if (bins[s][i].IsUsed()) continue;
783       Int_t idx[32]; UInt_t msk[32]; Int_t npeaks=0;
784       FindPeaks(i, nzBins, bins[s], idx, msk, npeaks);
785
786       if (npeaks>30) continue;
787       if (npeaks==0) continue;
788
789       Int_t k,l;
790       for (k=0; k<npeaks-1; k++){//mark adjacent peaks
791         if (idx[k] < 0) continue; //this peak is already removed
792         for (l=k+1; l<npeaks; l++) {
793            if (idx[l] < 0) continue; //this peak is already removed
794            Int_t ki=idx[k]/nzBins, kj=idx[k] - ki*nzBins;
795            Int_t li=idx[l]/nzBins, lj=idx[l] - li*nzBins;
796            Int_t di=TMath::Abs(ki - li);
797            Int_t dj=TMath::Abs(kj - lj);
798            if (di>1 || dj>1) continue;
799            if (bins[s][idx[k]].GetQ() > bins[s][idx[l]].GetQ()) {
800               msk[l]=msk[k];
801               idx[l]*=-1;
802            } else {
803               msk[k]=msk[l];
804               idx[k]*=-1;
805               break;
806            } 
807         }
808       }
809
810       for (k=0; k<npeaks; k++) {
811         MarkPeak(TMath::Abs(idx[k]), nzBins, bins[s], msk[k]);
812       }
813         
814       for (k=0; k<npeaks; k++) {
815          if (idx[k] < 0) continue; //removed peak
816          AliITSclusterV2 c;
817          MakeCluster(idx[k], nzBins, bins[s], msk[k], c);
818          //mi change
819          Int_t milab[10];
820          for (Int_t ilab=0;ilab<10;ilab++){
821            milab[ilab]=-2;
822          }
823          Int_t maxi=0,mini=0,maxj=0,minj=0;
824          //AliBin *bmax=&bins[s][idx[k]];
825          //Float_t max = TMath::Max(TMath::Abs(bmax->GetQ())/5.,3.);
826          Float_t max=3;
827          for (Int_t di=-2; di<=2;di++)
828            for (Int_t dj=-3;dj<=3;dj++){
829              Int_t index = idx[k]+di+dj*nzBins;
830              if (index<0) continue;
831              if (index>=nMaxBin) continue;
832              AliBin *b=&bins[s][index];
833              if (TMath::Abs(b->GetQ())>max){
834                if (di>maxi) maxi=di;
835                if (di<mini) mini=di;
836                if (dj>maxj) maxj=dj;
837                if (dj<minj) minj=dj;
838                //
839                if(digits) {
840                  if (TMath::Abs(di)<2&&TMath::Abs(dj)<2){
841                    AliITSdigitSDD* d=(AliITSdigitSDD*)digits->UncheckedAt(b->GetIndex());
842                    for (Int_t itrack=0;itrack<10;itrack++){
843                      Int_t track = (d->GetTracks())[itrack];
844                      if (track>=0) {
845                        AddLabel(milab, track); 
846                      }
847                    }
848                  }
849                }
850              }
851            }
852          
853          /* 
854             Float_t s2 = c.GetSigmaY2()/c.GetQ() - c.GetY()*c.GetY();
855             Float_t w=par->GetPadPitchWidth(sec);
856             c.SetSigmaY2(s2);
857             if (s2 != 0.) {
858             c.SetSigmaY2(c.GetSigmaY2()*0.108);
859             if (sec<par->GetNInnerSector()) c.SetSigmaY2(c.GetSigmaY2()*2.07);
860             }    
861             s2 = c.GetSigmaZ2()/c.GetQ() - c.GetZ()*c.GetZ();
862             w=par->GetZWidth();
863             c.SetSigmaZ2(s2);
864             
865             if (s2 != 0.) {
866             c.SetSigmaZ2(c.GetSigmaZ2()*0.169);
867             if (sec<par->GetNInnerSector()) c.SetSigmaZ2(c.GetSigmaZ2()*1.77);
868             }
869          */
870
871          c.SetSigmaY2(0.0030*0.0030);
872          c.SetSigmaZ2(0.0020*0.0020);
873          c.SetDetectorIndex(fNdet[fI]);
874
875          Float_t y=c.GetY(),z=c.GetZ(), q=c.GetQ();
876          y/=q; z/=q;
877          //
878          //Float_t s2 = c.GetSigmaY2()/c.GetQ() - y*y;
879          // c.SetSigmaY2(s2);
880          //s2 = c.GetSigmaZ2()/c.GetQ() - z*z;
881          //c.SetSigmaZ2(s2);
882          //
883          y=(y-0.5)*fYpitchSDD;
884          y-=fHwSDD;
885          y-=fYoffSDD;  //delay ?
886          if (s) y=-y;
887
888          z=(z-0.5)*fZpitchSDD;
889          z-=fHlSDD;
890
891          y=-(-y+fYshift[fI]);
892          z=  -z+fZshift[fI];
893          c.SetY(y);
894          c.SetZ(z);
895          c.SetNy(maxj-minj+1);
896          c.SetNz(maxi-mini+1);
897          c.SetType(npeaks);
898          c.SetQ(q/12.7);  //to be consistent with the SSD charges
899
900          if (c.GetQ() < 20.) continue; //noise cluster
901          
902          if (digits) {    
903            //      AliBin *b=&bins[s][idx[k]];
904            //      AliITSdigitSDD* d=(AliITSdigitSDD*)digits->UncheckedAt(b->GetIndex());
905            {
906              //Int_t lab[3];
907              //lab[0]=(d->GetTracks())[0];
908              //lab[1]=(d->GetTracks())[1];
909              //lab[2]=(d->GetTracks())[2];
910              //CheckLabels(lab);
911              CheckLabels2(milab); 
912              c.SetLabel(milab[0],0);
913              c.SetLabel(milab[1],1);
914              c.SetLabel(milab[2],2);
915              c.SetLayer(fNlayer[fI]);
916            }
917          }
918          new (cl[ncl]) AliITSclusterV2(c); ncl++;
919       }
920     }
921 }
922
923 void AliITSclustererV2::
924 FindClustersSDD(const TClonesArray *digits, TClonesArray *clusters) {
925   //------------------------------------------------------------
926   // Actual SDD cluster finder
927   //------------------------------------------------------------
928   Int_t kNzBins = fNzSDD + 2;
929   const Int_t kMAXBIN=kNzBins*(fNySDD+2);
930
931   AliBin *bins[2];
932   bins[0]=new AliBin[kMAXBIN];
933   bins[1]=new AliBin[kMAXBIN];
934
935   AliITSdigitSDD *d=0;
936   Int_t i, ndigits=digits->GetEntriesFast();
937   for (i=0; i<ndigits; i++) {
938      d=(AliITSdigitSDD*)digits->UncheckedAt(i);
939      Int_t y=d->GetCoord2()+1;   //y
940      Int_t z=d->GetCoord1()+1;   //z
941      Int_t q=d->GetSignal();
942      if (q<3) continue;
943
944      if (z <= fNzSDD) {
945        bins[0][y*kNzBins+z].SetQ(q);
946        bins[0][y*kNzBins+z].SetMask(1);
947        bins[0][y*kNzBins+z].SetIndex(i);
948      } else {
949        z-=fNzSDD; 
950        bins[1][y*kNzBins+z].SetQ(q);
951        bins[1][y*kNzBins+z].SetMask(1);
952        bins[1][y*kNzBins+z].SetIndex(i);
953      }
954   }
955   
956   FindClustersSDD(bins, kMAXBIN, kNzBins, digits, clusters);
957
958   delete[] bins[0];
959   delete[] bins[1];
960
961 }
962
963 void AliITSclustererV2::FindClustersSDD(AliITSRawStream* input, 
964                                         TClonesArray** clusters) 
965 {
966   //------------------------------------------------------------
967   // Actual SDD cluster finder for raw data
968   //------------------------------------------------------------
969   Int_t nClustersSDD = 0;
970   Int_t kNzBins = fNzSDD + 2;
971   Int_t kMaxBin = kNzBins * (fNySDD+2);
972   AliBin *binsSDDInit = new AliBin[kMaxBin];
973   AliBin *binsSDD1 = new AliBin[kMaxBin];
974   AliBin *binsSDD2 = new AliBin[kMaxBin];
975   AliBin *bins[2] = {NULL, NULL};
976
977   // read raw data input stream
978   while (kTRUE) {
979     Bool_t next = input->Next();
980     if (!next || input->IsNewModule()) {
981       Int_t iModule = input->GetPrevModuleID();
982
983       // when all data from a module was read, search for clusters
984       if (bins[0]) { 
985         clusters[iModule] = new TClonesArray("AliITSclusterV2");
986         fI = iModule;
987         FindClustersSDD(bins, kMaxBin, kNzBins, NULL, clusters[iModule]);
988         Int_t nClusters = clusters[iModule]->GetEntriesFast();
989         nClustersSDD += nClusters;
990         bins[0] = bins[1] = NULL;
991       }
992
993       if (!next) break;
994       bins[0]=binsSDD1;
995       bins[1]=binsSDD2;
996       memcpy(binsSDD1,binsSDDInit,sizeof(AliBin)*kMaxBin);
997       memcpy(binsSDD2,binsSDDInit,sizeof(AliBin)*kMaxBin);
998     }
999
1000     // fill the current digit into the bins array
1001     if(input->GetSignal()>=3) {
1002       Int_t iz = input->GetCoord1()+1;
1003       Int_t side = ((iz <= fNzSDD) ? 0 : 1);
1004       iz -= side*fNzSDD;
1005       Int_t index = (input->GetCoord2()+1) * kNzBins + iz;
1006       bins[side][index].SetQ(input->GetSignal());
1007       bins[side][index].SetMask(1);
1008       bins[side][index].SetIndex(index);
1009     }
1010   }
1011
1012   delete[] binsSDD1;
1013   delete[] binsSDD2;
1014   delete[] binsSDDInit;
1015
1016   Info("FindClustersSDD", "found clusters in ITS SDD: %d", nClustersSDD);
1017 }
1018
1019
1020
1021 void AliITSclustererV2::
1022 FindClustersSSD(Ali1Dcluster* neg, Int_t nn, 
1023                 Ali1Dcluster* pos, Int_t np,
1024                 TClonesArray *clusters) {
1025   //------------------------------------------------------------
1026   // Actual SSD cluster finder
1027   //------------------------------------------------------------
1028   TClonesArray &cl=*clusters;
1029   //
1030   Float_t tanp=fTanP, tann=fTanN;
1031   if (fI>fLastSSD1) {tann=fTanP; tanp=fTanN;}
1032   Int_t idet=fNdet[fI];
1033   Int_t ncl=0;
1034   //
1035   Int_t negativepair[30000];
1036   Int_t cnegative[3000];  
1037   Int_t cused1[3000];
1038   Int_t positivepair[30000];
1039   Int_t cpositive[3000];
1040   Int_t cused2[3000];
1041   for (Int_t i=0;i<3000;i++) {cnegative[i]=0; cused1[i]=0;}
1042   for (Int_t i=0;i<3000;i++) {cpositive[i]=0; cused2[i]=0;}
1043   static Short_t pairs[1000][1000];
1044   memset(pairs,0,sizeof(Short_t)*1000000);
1045 //   Short_t ** pairs = new Short_t*[1000];
1046 //   for (Int_t i=0; i<1000; i++) {
1047 //     pairs[i] = new Short_t[1000];
1048 //     memset(pairs[i],0,sizeof(Short_t)*1000);
1049 //   }  
1050   //
1051   // find available pairs
1052   //
1053   for (Int_t i=0; i<np; i++) {
1054     Float_t yp=pos[i].GetY()*fYpitchSSD; 
1055     if (pos[i].GetQ()<3) continue;
1056     for (Int_t j=0; j<nn; j++) {
1057       if (neg[j].GetQ()<3) continue;
1058       Float_t yn=neg[j].GetY()*fYpitchSSD;
1059       Float_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1060       Float_t yt=yn + tann*zt;
1061       zt-=fHlSSD; yt-=fHwSSD;
1062       if (TMath::Abs(yt)<fHwSSD+0.01)
1063       if (TMath::Abs(zt)<fHlSSD+0.01*(neg[j].GetNd()+pos[i].GetNd())) {
1064         negativepair[i*10+cnegative[i]] =j;  //index
1065         positivepair[j*10+cpositive[j]] =i;
1066         cnegative[i]++;  //counters
1067         cpositive[j]++; 
1068         pairs[i][j]=100;
1069       }
1070     }
1071   }
1072   //
1073   for (Int_t i=0; i<np; i++) {
1074     Float_t yp=pos[i].GetY()*fYpitchSSD; 
1075     if (pos[i].GetQ()<3) continue;
1076     for (Int_t j=0; j<nn; j++) {
1077       if (neg[j].GetQ()<3) continue;
1078       if (cpositive[j]&&cnegative[i]) continue;
1079       Float_t yn=neg[j].GetY()*fYpitchSSD;
1080       Float_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1081       Float_t yt=yn + tann*zt;
1082       zt-=fHlSSD; yt-=fHwSSD;
1083       if (TMath::Abs(yt)<fHwSSD+0.1)
1084       if (TMath::Abs(zt)<fHlSSD+0.15) {
1085         if (cnegative[i]==0) pos[i].SetNd(100);  // not available pair
1086         if (cpositive[j]==0) neg[j].SetNd(100);  // not available pair
1087         negativepair[i*10+cnegative[i]] =j;  //index
1088         positivepair[j*10+cpositive[j]] =i;
1089         cnegative[i]++;  //counters
1090         cpositive[j]++; 
1091         pairs[i][j]=100;
1092       }
1093     }
1094   }
1095   //
1096   Float_t lp[5];
1097   Int_t milab[10];
1098   Double_t ratio;
1099   
1100   //
1101   // sign gold tracks
1102   //
1103   for (Int_t ip=0;ip<np;ip++){
1104     Float_t ybest=1000,zbest=1000,qbest=0;
1105     //
1106     // select gold clusters
1107     if ( (cnegative[ip]==1) && cpositive[negativepair[10*ip]]==1){ 
1108       Float_t yp=pos[ip].GetY()*fYpitchSSD; 
1109       Int_t j = negativepair[10*ip];      
1110       ratio = (pos[ip].GetQ()-neg[j].GetQ())/(pos[ip].GetQ()+neg[j].GetQ());
1111       //
1112       Float_t yn=neg[j].GetY()*fYpitchSSD;
1113       Float_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1114       Float_t yt=yn + tann*zt;
1115       zt-=fHlSSD; yt-=fHwSSD;
1116       ybest=yt; zbest=zt; 
1117       qbest=0.5*(pos[ip].GetQ()+neg[j].GetQ());
1118       lp[0]=-(-ybest+fYshift[fI]);
1119       lp[1]=  -zbest+fZshift[fI];
1120       lp[2]=0.0025*0.0025;  //SigmaY2
1121       lp[3]=0.110*0.110;  //SigmaZ2
1122       
1123       lp[4]=qbest;        //Q
1124       for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1125       for (Int_t ilab=0;ilab<3;ilab++){
1126         milab[ilab] = pos[ip].GetLabel(ilab);
1127         milab[ilab+3] = neg[j].GetLabel(ilab);
1128       }
1129       //
1130       CheckLabels2(milab);
1131       milab[3]=(((ip<<10) + j)<<10) + idet; // pos|neg|det
1132       Int_t info[3] = {pos[ip].GetNd(),neg[j].GetNd(),fNlayer[fI]};
1133       AliITSclusterV2 * cl2 = new (cl[ncl]) AliITSclusterV2(milab,lp,info);
1134       ncl++;
1135       cl2->SetChargeRatio(ratio);       
1136       cl2->SetType(1);
1137       pairs[ip][j]=1;
1138       if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
1139         cl2->SetType(2);
1140         pairs[ip][j]=2;
1141       }
1142       cused1[ip]++;
1143       cused2[j]++;
1144     }
1145   }
1146     
1147   for (Int_t ip=0;ip<np;ip++){
1148     Float_t ybest=1000,zbest=1000,qbest=0;
1149     //
1150     //
1151     // select "silber" cluster
1152     if ( cnegative[ip]==1 && cpositive[negativepair[10*ip]]==2){
1153       Int_t in  = negativepair[10*ip];
1154       Int_t ip2 = positivepair[10*in];
1155       if (ip2==ip) ip2 =  positivepair[10*in+1];
1156       Float_t pcharge = pos[ip].GetQ()+pos[ip2].GetQ();
1157       if (TMath::Abs(pcharge-neg[in].GetQ())<10){
1158         //
1159         // add first pair
1160         if (pairs[ip][in]==100){  //
1161           Float_t yp=pos[ip].GetY()*fYpitchSSD; 
1162           Float_t yn=neg[in].GetY()*fYpitchSSD;
1163           Float_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1164           Float_t yt=yn + tann*zt;
1165           zt-=fHlSSD; yt-=fHwSSD;
1166           ybest =yt;  zbest=zt; 
1167           qbest =pos[ip].GetQ();
1168           lp[0]=-(-ybest+fYshift[fI]);
1169           lp[1]=  -zbest+fZshift[fI];
1170           lp[2]=0.0025*0.0025;  //SigmaY2
1171           lp[3]=0.110*0.110;  //SigmaZ2
1172           
1173           lp[4]=qbest;        //Q
1174           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1175           for (Int_t ilab=0;ilab<3;ilab++){
1176             milab[ilab] = pos[ip].GetLabel(ilab);
1177             milab[ilab+3] = neg[in].GetLabel(ilab);
1178           }
1179           //
1180           CheckLabels2(milab);
1181           ratio = (pos[ip].GetQ()-neg[in].GetQ())/(pos[ip].GetQ()+neg[in].GetQ());
1182           milab[3]=(((ip<<10) + in)<<10) + idet; // pos|neg|det
1183           Int_t info[3] = {pos[ip].GetNd(),neg[in].GetNd(),fNlayer[fI]};
1184           AliITSclusterV2 * cl2 = new (cl[ncl]) AliITSclusterV2(milab,lp,info);
1185           ncl++;
1186           cl2->SetChargeRatio(ratio);           
1187           cl2->SetType(5);
1188           pairs[ip][in] = 5;
1189           if ((pos[ip].GetNd()+neg[in].GetNd())>6){ //multi cluster
1190             cl2->SetType(6);
1191             pairs[ip][in] = 6;
1192           }
1193         }
1194         //
1195         // add second pair
1196         
1197         //      if (!(cused1[ip2] || cused2[in])){  //
1198         if (pairs[ip2][in]==100){
1199           Float_t yp=pos[ip2].GetY()*fYpitchSSD;
1200           Float_t yn=neg[in].GetY()*fYpitchSSD;
1201           Float_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1202           Float_t yt=yn + tann*zt;
1203           zt-=fHlSSD; yt-=fHwSSD;
1204           ybest =yt;  zbest=zt; 
1205           qbest =pos[ip2].GetQ();
1206           lp[0]=-(-ybest+fYshift[fI]);
1207           lp[1]=  -zbest+fZshift[fI];
1208           lp[2]=0.0025*0.0025;  //SigmaY2
1209           lp[3]=0.110*0.110;  //SigmaZ2
1210           
1211           lp[4]=qbest;        //Q
1212           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1213           for (Int_t ilab=0;ilab<3;ilab++){
1214             milab[ilab] = pos[ip2].GetLabel(ilab);
1215             milab[ilab+3] = neg[in].GetLabel(ilab);
1216           }
1217           //
1218           CheckLabels2(milab);
1219           ratio = (pos[ip2].GetQ()-neg[in].GetQ())/(pos[ip2].GetQ()+neg[in].GetQ());
1220           milab[3]=(((ip2<<10) + in)<<10) + idet; // pos|neg|det
1221           Int_t info[3] = {pos[ip2].GetNd(),neg[in].GetNd(),fNlayer[fI]};
1222           AliITSclusterV2 *cl2 = new (cl[ncl]) AliITSclusterV2(milab,lp,info);
1223           ncl++;
1224           cl2->SetChargeRatio(ratio);           
1225           cl2->SetType(5);
1226           pairs[ip2][in] =5;
1227           if ((pos[ip2].GetNd()+neg[in].GetNd())>6){ //multi cluster
1228             cl2->SetType(6);
1229             pairs[ip2][in] =6;
1230           }
1231         }       
1232         cused1[ip]++;
1233         cused1[ip2]++;
1234         cused2[in]++;
1235       }
1236     }    
1237   }
1238   
1239   //  
1240   for (Int_t jn=0;jn<nn;jn++){
1241     if (cused2[jn]) continue;
1242     Float_t ybest=1000,zbest=1000,qbest=0;
1243     // select "silber" cluster
1244     if ( cpositive[jn]==1 && cnegative[positivepair[10*jn]]==2){
1245       Int_t ip  = positivepair[10*jn];
1246       Int_t jn2 = negativepair[10*ip];
1247       if (jn2==jn) jn2 =  negativepair[10*ip+1];
1248       Float_t pcharge = neg[jn].GetQ()+neg[jn2].GetQ();
1249       //
1250       if (TMath::Abs(pcharge-pos[ip].GetQ())<10){
1251         //
1252         // add first pair
1253         //      if (!(cused1[ip]||cused2[jn])){
1254         if (pairs[ip][jn]==100){
1255           Float_t yn=neg[jn].GetY()*fYpitchSSD; 
1256           Float_t yp=pos[ip].GetY()*fYpitchSSD;
1257           Float_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1258           Float_t yt=yn + tann*zt;
1259           zt-=fHlSSD; yt-=fHwSSD;
1260           ybest =yt;  zbest=zt; 
1261           qbest =neg[jn].GetQ();
1262           lp[0]=-(-ybest+fYshift[fI]);
1263           lp[1]=  -zbest+fZshift[fI];
1264           lp[2]=0.0025*0.0025;  //SigmaY2
1265           lp[3]=0.110*0.110;  //SigmaZ2
1266           
1267           lp[4]=qbest;        //Q
1268           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1269           for (Int_t ilab=0;ilab<3;ilab++){
1270             milab[ilab] = pos[ip].GetLabel(ilab);
1271             milab[ilab+3] = neg[jn].GetLabel(ilab);
1272           }
1273           //
1274           CheckLabels2(milab);
1275           ratio = (pos[ip].GetQ()-neg[jn].GetQ())/(pos[ip].GetQ()+neg[jn].GetQ());
1276           milab[3]=(((ip<<10) + jn)<<10) + idet; // pos|neg|det
1277           Int_t info[3] = {pos[ip].GetNd(),neg[jn].GetNd(),fNlayer[fI]};
1278           AliITSclusterV2 * cl2 = new (cl[ncl]) AliITSclusterV2(milab,lp,info);
1279           ncl++;
1280           cl2->SetChargeRatio(ratio);           
1281           cl2->SetType(7);
1282           pairs[ip][jn] =7;
1283           if ((pos[ip].GetNd()+neg[jn].GetNd())>6){ //multi cluster
1284             cl2->SetType(8);
1285             pairs[ip][jn]=8;
1286           }
1287         }
1288         //
1289         // add second pair
1290         //      if (!(cused1[ip]||cused2[jn2])){
1291         if (pairs[ip][jn2]==100){
1292           Float_t yn=neg[jn2].GetY()*fYpitchSSD; 
1293           Double_t yp=pos[ip].GetY()*fYpitchSSD; 
1294           Double_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1295           Double_t yt=yn + tann*zt;
1296           zt-=fHlSSD; yt-=fHwSSD;
1297           ybest =yt;  zbest=zt; 
1298           qbest =neg[jn2].GetQ();
1299           lp[0]=-(-ybest+fYshift[fI]);
1300           lp[1]=  -zbest+fZshift[fI];
1301           lp[2]=0.0025*0.0025;  //SigmaY2
1302           lp[3]=0.110*0.110;  //SigmaZ2
1303           
1304           lp[4]=qbest;        //Q
1305           for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1306           for (Int_t ilab=0;ilab<3;ilab++){
1307             milab[ilab] = pos[ip].GetLabel(ilab);
1308             milab[ilab+3] = neg[jn2].GetLabel(ilab);
1309           }
1310           //
1311           CheckLabels2(milab);
1312           ratio = (pos[ip].GetQ()-neg[jn2].GetQ())/(pos[ip].GetQ()+neg[jn2].GetQ());
1313           milab[3]=(((ip<<10) + jn2)<<10) + idet; // pos|neg|det
1314           Int_t info[3] = {pos[ip].GetNd(),neg[jn2].GetNd(),fNlayer[fI]};
1315           AliITSclusterV2* cl2 = new (cl[ncl]) AliITSclusterV2(milab,lp,info);
1316           ncl++;
1317           cl2->SetChargeRatio(ratio);           
1318           pairs[ip][jn2]=7;
1319           cl2->SetType(7);
1320           if ((pos[ip].GetNd()+neg[jn2].GetNd())>6){ //multi cluster
1321             cl2->SetType(8);
1322             pairs[ip][jn2]=8;
1323           }
1324         }
1325         cused1[ip]++;
1326         cused2[jn]++;
1327         cused2[jn2]++;
1328       }
1329     }    
1330   }
1331   
1332   for (Int_t ip=0;ip<np;ip++){
1333     Float_t ybest=1000,zbest=1000,qbest=0;
1334     //
1335     // 2x2 clusters
1336     //
1337     if ( (cnegative[ip]<5) && cpositive[negativepair[10*ip]]<5){ 
1338       Float_t minchargediff =4.;
1339       Int_t j=-1;
1340       for (Int_t di=0;di<cnegative[ip];di++){
1341         Int_t   jc = negativepair[ip*10+di];
1342         Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
1343         if (TMath::Abs(chargedif)<minchargediff){
1344           j =jc;
1345           minchargediff = TMath::Abs(chargedif);
1346         }
1347       }
1348       if (j<0) continue;  // not proper cluster      
1349       Int_t count =0;
1350       for (Int_t di=0;di<cnegative[ip];di++){
1351         Int_t   jc = negativepair[ip*10+di];
1352         Float_t chargedif = pos[ip].GetQ()-neg[jc].GetQ();
1353         if (TMath::Abs(chargedif)<minchargediff+3.) count++;
1354       }
1355       if (count>1) continue;  // more than one "proper" cluster for positive
1356       //
1357       count =0;
1358       for (Int_t dj=0;dj<cpositive[j];dj++){
1359         Int_t   ic  = positivepair[j*10+dj];
1360         Float_t chargedif = pos[ic].GetQ()-neg[j].GetQ();
1361         if (TMath::Abs(chargedif)<minchargediff+3.) count++;
1362       }
1363       if (count>1) continue;  // more than one "proper" cluster for negative
1364       
1365       Int_t jp = 0;
1366       
1367       count =0;
1368       for (Int_t dj=0;dj<cnegative[jp];dj++){
1369         Int_t   ic = positivepair[jp*10+dj];
1370         Float_t chargedif = pos[ic].GetQ()-neg[jp].GetQ();
1371         if (TMath::Abs(chargedif)<minchargediff+4.) count++;
1372       }
1373       if (count>1) continue;   
1374       if (pairs[ip][j]<100) continue;
1375       //
1376       //almost gold clusters
1377       Float_t yp=pos[ip].GetY()*fYpitchSSD; 
1378       Float_t yn=neg[j].GetY()*fYpitchSSD;
1379       Float_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1380       Float_t yt=yn + tann*zt;
1381       zt-=fHlSSD; yt-=fHwSSD;
1382       ybest=yt; zbest=zt; 
1383       qbest=0.5*(pos[ip].GetQ()+neg[j].GetQ());
1384       lp[0]=-(-ybest+fYshift[fI]);
1385       lp[1]=  -zbest+fZshift[fI];
1386       lp[2]=0.0025*0.0025;  //SigmaY2
1387       lp[3]=0.110*0.110;  //SigmaZ2     
1388       lp[4]=qbest;        //Q
1389       for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1390       for (Int_t ilab=0;ilab<3;ilab++){
1391         milab[ilab] = pos[ip].GetLabel(ilab);
1392         milab[ilab+3] = neg[j].GetLabel(ilab);
1393       }
1394       //
1395       CheckLabels2(milab);
1396       ratio = (pos[ip].GetQ()-neg[j].GetQ())/(pos[ip].GetQ()+neg[j].GetQ());
1397       milab[3]=(((ip<<10) + j)<<10) + idet; // pos|neg|det
1398       Int_t info[3] = {pos[ip].GetNd(),neg[j].GetNd(),fNlayer[fI]};
1399       AliITSclusterV2 * cl2 = new (cl[ncl]) AliITSclusterV2(milab,lp,info);
1400       ncl++;
1401       cl2->SetChargeRatio(ratio);       
1402       cl2->SetType(10);
1403       pairs[ip][j]=10;
1404       if ((pos[ip].GetNd()+neg[j].GetNd())>6){ //multi cluster
1405         cl2->SetType(11);
1406         pairs[ip][j]=11;
1407       }
1408       cused1[ip]++;
1409       cused2[j]++;      
1410     }
1411
1412   }
1413   
1414   //  
1415   for (Int_t i=0; i<np; i++) {
1416     Float_t ybest=1000,zbest=1000,qbest=0;
1417     Float_t yp=pos[i].GetY()*fYpitchSSD; 
1418     if (pos[i].GetQ()<3) continue;
1419     for (Int_t j=0; j<nn; j++) {
1420     //    for (Int_t di = 0;di<cpositive[i];di++){
1421     //  Int_t j = negativepair[10*i+di];
1422       if (neg[j].GetQ()<3) continue;
1423       if (cused2[j]||cused1[i]) continue;      
1424       if (pairs[i][j]>0 &&pairs[i][j]<100) continue;
1425       ratio = (pos[i].GetQ()-neg[j].GetQ())/(pos[i].GetQ()+neg[j].GetQ());      
1426       Float_t yn=neg[j].GetY()*fYpitchSSD;
1427       Float_t zt=(2*fHlSSD*tanp + yp - yn)/(tann+tanp);
1428       Float_t yt=yn + tann*zt;
1429       zt-=fHlSSD; yt-=fHwSSD;
1430       if (TMath::Abs(yt)<fHwSSD+0.01)
1431       if (TMath::Abs(zt)<fHlSSD+0.01*(neg[j].GetNd()+pos[i].GetNd())) {
1432         ybest=yt; zbest=zt; 
1433         qbest=0.5*(pos[i].GetQ()+neg[j].GetQ());
1434         lp[0]=-(-ybest+fYshift[fI]);
1435         lp[1]=  -zbest+fZshift[fI];
1436         lp[2]=0.0025*0.0025;  //SigmaY2
1437         lp[3]=0.110*0.110;  //SigmaZ2
1438
1439         lp[4]=qbest;        //Q
1440         for (Int_t ilab=0;ilab<10;ilab++) milab[ilab]=-2;
1441         for (Int_t ilab=0;ilab<3;ilab++){
1442           milab[ilab] = pos[i].GetLabel(ilab);
1443           milab[ilab+3] = neg[j].GetLabel(ilab);
1444         }
1445         //
1446         CheckLabels2(milab);
1447         milab[3]=(((i<<10) + j)<<10) + idet; // pos|neg|det
1448         Int_t info[3] = {pos[i].GetNd(),neg[j].GetNd(),fNlayer[fI]};
1449         AliITSclusterV2 * cl2 = new (cl[ncl]) AliITSclusterV2(milab,lp,info); 
1450         ncl++;
1451         cl2->SetChargeRatio(ratio);
1452         cl2->SetType(100+cpositive[j]+cnegative[i]);
1453         //cl2->SetType(0);
1454         /*
1455           if (pairs[i][j]<100){
1456           printf("problem:- %d\n", pairs[i][j]);
1457           }
1458           if (cnegative[i]<2&&cpositive[j]<2){
1459           printf("problem:- %d\n", pairs[i][j]);
1460           }
1461         */
1462       }
1463     }
1464   }
1465
1466 //   for (Int_t i=0; i<1000; i++) delete [] pairs[i];
1467 //   delete [] pairs;
1468
1469 }
1470
1471
1472 void AliITSclustererV2::
1473 FindClustersSSD(const TClonesArray *alldigits, TClonesArray *clusters) {
1474   //------------------------------------------------------------
1475   // Actual SSD cluster finder
1476   //------------------------------------------------------------
1477   Int_t smaxall=alldigits->GetEntriesFast();
1478   if (smaxall==0) return;
1479   TObjArray *digits = new TObjArray;
1480   for (Int_t i=0;i<smaxall; i++){
1481     AliITSdigitSSD *d=(AliITSdigitSSD*)alldigits->UncheckedAt(i);
1482     if (d->GetSignal()<3) continue;
1483     digits->AddLast(d);
1484   }
1485   Int_t smax = digits->GetEntriesFast();
1486   if (smax==0) return;
1487   
1488   const Int_t MAX=1000;
1489   Int_t np=0, nn=0; 
1490   Ali1Dcluster pos[MAX], neg[MAX];
1491   Float_t y=0., q=0., qmax=0.; 
1492   Int_t lab[4]={-2,-2,-2,-2};
1493   
1494   AliITSdigitSSD *d=(AliITSdigitSSD*)digits->UncheckedAt(0);
1495   q += d->GetSignal();
1496   y += d->GetCoord2()*d->GetSignal();
1497   qmax=d->GetSignal();
1498   lab[0]=d->GetTrack(0); lab[1]=d->GetTrack(1); lab[2]=d->GetTrack(2);
1499   Int_t curr=d->GetCoord2();
1500   Int_t flag=d->GetCoord1();
1501   Int_t *n=&nn;
1502   Ali1Dcluster *c=neg;
1503   Int_t nd=1;
1504   Int_t milab[10];
1505   for (Int_t ilab=0;ilab<10;ilab++){
1506     milab[ilab]=-2;
1507   }
1508   milab[0]=d->GetTrack(0); milab[1]=d->GetTrack(1); milab[2]=d->GetTrack(2);
1509
1510   for (Int_t s=1; s<smax; s++) {
1511       d=(AliITSdigitSSD*)digits->UncheckedAt(s);      
1512       Int_t strip=d->GetCoord2();
1513       if ((strip-curr) > 1 || flag!=d->GetCoord1()) {
1514          c[*n].SetY(y/q);
1515          c[*n].SetQ(q);
1516          c[*n].SetNd(nd);
1517          CheckLabels2(milab);
1518          c[*n].SetLabels(milab);
1519          //Split suspiciously big cluster
1520          /*
1521          if (nd>10&&nd<16){
1522            c[*n].SetY(y/q-0.3*nd);
1523            c[*n].SetQ(0.5*q);
1524            (*n)++;
1525            if (*n==MAX) {
1526              Error("FindClustersSSD","Too many 1D clusters !");
1527               return;
1528            }
1529            c[*n].SetY(y/q-0.0*nd);
1530            c[*n].SetQ(0.5*q);
1531            c[*n].SetNd(nd);
1532            (*n)++;
1533            if (*n==MAX) {
1534              Error("FindClustersSSD","Too many 1D clusters !");
1535               return;
1536            }
1537            //
1538            c[*n].SetY(y/q+0.3*nd);
1539            c[*n].SetQ(0.5*q);
1540            c[*n].SetNd(nd);
1541            c[*n].SetLabels(milab);
1542          }
1543          else{
1544          */
1545          if (nd>4&&nd<25) {
1546            c[*n].SetY(y/q-0.25*nd);
1547            c[*n].SetQ(0.5*q);
1548            (*n)++;
1549            if (*n==MAX) {
1550              Error("FindClustersSSD","Too many 1D clusters !");
1551              return;
1552            }
1553            c[*n].SetY(y/q+0.25*nd);
1554            c[*n].SetQ(0.5*q);
1555            c[*n].SetNd(nd);
1556            c[*n].SetLabels(milab);
1557          }       
1558          (*n)++;
1559          if (*n==MAX) {
1560           Error("FindClustersSSD","Too many 1D clusters !");
1561           return;
1562          }
1563          y=q=qmax=0.;
1564          nd=0;
1565          lab[0]=lab[1]=lab[2]=-2;
1566          //
1567          for (Int_t ilab=0;ilab<10;ilab++){
1568            milab[ilab]=-2;
1569          }
1570          //
1571          if (flag!=d->GetCoord1()) { n=&np; c=pos; }
1572       }
1573       flag=d->GetCoord1();
1574       q += d->GetSignal();
1575       y += d->GetCoord2()*d->GetSignal();
1576       nd++;
1577       if (d->GetSignal()>qmax) {
1578          qmax=d->GetSignal();
1579          lab[0]=d->GetTrack(0); lab[1]=d->GetTrack(1); lab[2]=d->GetTrack(2);
1580       }
1581       for (Int_t ilab=0;ilab<10;ilab++) {
1582         if (d->GetTrack(ilab)>=0) AddLabel(milab, (d->GetTrack(ilab))); 
1583       }
1584       curr=strip;
1585   }
1586   c[*n].SetY(y/q);
1587   c[*n].SetQ(q);
1588   c[*n].SetNd(nd);
1589   c[*n].SetLabels(lab);
1590   //Split suspiciously big cluster
1591   if (nd>4 && nd<25) {
1592      c[*n].SetY(y/q-0.25*nd);
1593      c[*n].SetQ(0.5*q);
1594      (*n)++;
1595      if (*n==MAX) {
1596         Error("FindClustersSSD","Too many 1D clusters !");
1597         return;
1598      }
1599      c[*n].SetY(y/q+0.25*nd);
1600      c[*n].SetQ(0.5*q);
1601      c[*n].SetNd(nd);
1602      c[*n].SetLabels(lab);
1603   }
1604   (*n)++;
1605   if (*n==MAX) {
1606      Error("FindClustersSSD","Too many 1D clusters !");
1607      return;
1608   }
1609
1610   FindClustersSSD(neg, nn, pos, np, clusters);
1611 }
1612
1613 void AliITSclustererV2::FindClustersSSD(AliITSRawStream* input, 
1614                                         TClonesArray** clusters) 
1615 {
1616   //------------------------------------------------------------
1617   // Actual SSD cluster finder for raw data
1618   //------------------------------------------------------------
1619   Int_t nClustersSSD = 0;
1620   const Int_t MAX = 1000;
1621   Ali1Dcluster clusters1D[2][MAX];
1622   Int_t nClusters[2] = {0, 0};
1623   Int_t lab[3]={-2,-2,-2};
1624   Float_t q = 0.;
1625   Float_t y = 0.;
1626   Int_t nDigits = 0;
1627   Int_t prevStrip = -1;
1628   Int_t prevFlag = -1;
1629   Int_t prevModule = -1;
1630
1631   // read raw data input stream
1632   while (kTRUE) {
1633     Bool_t next = input->Next();
1634
1635     if(input->GetSignal()<3 && next) continue;
1636     // check if a new cluster starts
1637     Int_t strip = input->GetCoord2();
1638     Int_t flag = input->GetCoord1();
1639     if ((!next || (input->GetModuleID() != prevModule)||
1640          (strip-prevStrip > 1) || (flag != prevFlag)) &&
1641         (nDigits > 0)) {
1642       if (nClusters[prevFlag] == MAX) {
1643         Error("FindClustersSSD", "Too many 1D clusters !");
1644         return;
1645       }
1646       Ali1Dcluster& cluster = clusters1D[prevFlag][nClusters[prevFlag]++];
1647       cluster.SetY(y/q);
1648       cluster.SetQ(q);
1649       cluster.SetNd(nDigits);
1650       cluster.SetLabels(lab);
1651
1652       //Split suspiciously big cluster
1653       if (nDigits > 4&&nDigits < 25) {
1654         cluster.SetY(y/q - 0.25*nDigits);
1655         cluster.SetQ(0.5*q);
1656         if (nClusters[prevFlag] == MAX) {
1657           Error("FindClustersSSD", "Too many 1D clusters !");
1658           return;
1659         }
1660         Ali1Dcluster& cluster2 = clusters1D[prevFlag][nClusters[prevFlag]++];
1661         cluster2.SetY(y/q + 0.25*nDigits);
1662         cluster2.SetQ(0.5*q);
1663         cluster2.SetNd(nDigits);
1664         cluster2.SetLabels(lab);
1665       }
1666       y = q = 0.;
1667       nDigits = 0;
1668     }
1669
1670     if (!next || (input->GetModuleID() != prevModule)) {
1671       Int_t iModule = prevModule;
1672
1673       // when all data from a module was read, search for clusters
1674       if (prevFlag >= 0) {
1675         clusters[iModule] = new TClonesArray("AliITSclusterV2");
1676         fI = iModule;
1677         FindClustersSSD(&clusters1D[0][0], nClusters[0], 
1678                         &clusters1D[1][0], nClusters[1], clusters[iModule]);
1679         Int_t nClusters = clusters[iModule]->GetEntriesFast();
1680         nClustersSSD += nClusters;
1681       }
1682
1683       if (!next) break;
1684       nClusters[0] = nClusters[1] = 0;
1685       y = q = 0.;
1686       nDigits = 0;
1687     }
1688
1689     // add digit to current cluster
1690     q += input->GetSignal();
1691     y += strip * input->GetSignal();
1692     nDigits++;
1693     prevStrip = strip;
1694     prevFlag = flag;
1695     prevModule = input->GetModuleID();
1696
1697   }
1698
1699   Info("FindClustersSSD", "found clusters in ITS SSD: %d", nClustersSSD);
1700 }
1701
1702 #else   //V1
1703
1704 #include "AliITSDetType.h"
1705
1706 #include "AliITSsegmentationSPD.h"
1707 #include "AliITSClusterFinderSPD.h"
1708
1709 #include "AliITSresponseSDD.h"
1710 #include "AliITSsegmentationSDD.h"
1711 #include "AliITSClusterFinderSDD.h"
1712
1713 #include "AliITSsegmentationSSD.h"
1714 #include "AliITSClusterFinderSSD.h"
1715
1716
1717 void AliITSclustererV2::
1718 FindClustersSPD(const TClonesArray *digits, TClonesArray *clusters) {
1719   //------------------------------------------------------------
1720   // Actual SPD cluster finding based on AliITSClusterFinderSPD
1721   //------------------------------------------------------------
1722   static AliITS *its=(AliITS*)gAlice->GetModule("ITS");
1723   static TClonesArray *points=its->RecPoints();
1724   static AliITSsegmentationSPD *seg=
1725          (AliITSsegmentationSPD *)its->DetType(0)->GetSegmentationModel();
1726   static AliITSClusterFinderSPD cf(seg, (TClonesArray*)digits, points);
1727
1728   cf.FindRawClusters(fI);
1729   RecPoints2Clusters(points, fI, clusters);
1730   its->ResetRecPoints();
1731
1732 }
1733
1734 void AliITSclustererV2::
1735 FindClustersSDD(const TClonesArray *digits, TClonesArray *clusters) {
1736   //------------------------------------------------------------
1737   // Actual SDD cluster finding based on AliITSClusterFinderSDD
1738   //------------------------------------------------------------
1739   static AliITS *its=(AliITS*)gAlice->GetModule("ITS");
1740   static TClonesArray *points=its->RecPoints();
1741   static AliITSresponseSDD *resp=
1742         (AliITSresponseSDD *)its->DetType(1)->GetResponseModel();
1743   static AliITSsegmentationSDD *seg=
1744          (AliITSsegmentationSDD *)its->DetType(1)->GetSegmentationModel();
1745   static AliITSClusterFinderSDD 
1746          cf(seg,resp,(TClonesArray*)digits,its->ClustersAddress(1));
1747
1748   cf.FindRawClusters(fI);
1749   Int_t nc=points->GetEntriesFast();
1750   while (nc--) { //To be consistent with the SSD cluster charges
1751      AliITSRecPoint *p=(AliITSRecPoint*)points->UncheckedAt(nc);
1752      p->SetQ(p->GetQ()/12.);
1753   }
1754   RecPoints2Clusters(points, fI, clusters);
1755   its->ResetClusters(1);
1756   its->ResetRecPoints();
1757
1758 }
1759
1760 void AliITSclustererV2::
1761 FindClustersSSD(const TClonesArray *digits, TClonesArray *clusters) {
1762   //------------------------------------------------------------
1763   // Actual SSD cluster finding based on AliITSClusterFinderSSD
1764   //------------------------------------------------------------
1765   static AliITS *its=(AliITS*)gAlice->GetModule("ITS");
1766   static TClonesArray *points=its->RecPoints();
1767   static AliITSsegmentationSSD *seg=
1768          (AliITSsegmentationSSD *)its->DetType(2)->GetSegmentationModel();
1769   static AliITSClusterFinderSSD cf(seg,(TClonesArray*)digits);
1770
1771   cf.FindRawClusters(fI);
1772   RecPoints2Clusters(points, fI, clusters);
1773   its->ResetRecPoints();
1774
1775 }
1776
1777 #endif