]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ITS/AliITSClusterFinderSDD.cxx
Changes to obey our coding conventions
[u/mrichter/AliRoot.git] / ITS / AliITSClusterFinderSDD.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-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   $Log$
18   Revision 1.34  2003/09/11 13:48:52  masera
19   Data members of AliITSdigit classes defined as protected (They were public)
20
21   Revision 1.33  2003/07/21 14:20:51  masera
22   Fix to track labes in SDD Rec-points
23
24   Revision 1.31.2.1  2003/07/16 13:18:04  masera
25   Proper fix to track labels associated to SDD rec-points
26
27   Revision 1.31  2003/05/19 14:44:41  masera
28   Fix to track labels associated to SDD rec-points
29
30   Revision 1.30  2003/03/03 16:34:35  masera
31   Corrections to comply with coding conventions
32
33   Revision 1.29  2002/10/25 18:54:22  barbera
34   Various improvements and updates from B.S.Nilsen and T. Virgili
35
36   Revision 1.28  2002/10/22 14:45:29  alibrary
37   Introducing Riostream.h
38
39   Revision 1.27  2002/10/14 14:57:00  hristov
40   Merging the VirtualMC branch to the main development branch (HEAD)
41
42   Revision 1.23.4.2  2002/10/14 13:14:07  hristov
43   Updating VirtualMC to v3-09-02
44
45   Revision 1.26  2002/09/09 17:23:28  nilsen
46   Minor changes in support of changes to AliITSdigitS?D class'.
47
48   Revision 1.25  2002/05/10 22:29:40  nilsen
49   Change my Massimo Masera in the default constructor to bring things into
50   compliance.
51
52   Revision 1.24  2002/04/24 22:02:31  nilsen
53   New SDigits and Digits routines, and related changes,  (including new
54   noise values).
55
56  */
57 // 
58 //  Cluster finder 
59 //  for Silicon
60 //  Drift Detector
61 //
62 #include <Riostream.h>
63
64 #include <TMath.h>
65 #include <math.h>
66
67 #include "AliITSClusterFinderSDD.h"
68 #include "AliITSMapA1.h"
69 #include "AliITS.h"
70 #include "AliITSdigit.h"
71 #include "AliITSRawClusterSDD.h"
72 #include "AliITSRecPoint.h"
73 #include "AliITSsegmentation.h"
74 #include "AliITSresponseSDD.h"
75 #include "AliRun.h"
76
77 ClassImp(AliITSClusterFinderSDD)
78
79 //______________________________________________________________________
80 AliITSClusterFinderSDD::AliITSClusterFinderSDD(AliITSsegmentation *seg,
81                                                AliITSresponse *response,
82                                                TClonesArray *digits,
83                                                TClonesArray *recp){
84     // standard constructor
85
86     fSegmentation = seg;
87     fResponse     = response;
88     fDigits       = digits;
89     fClusters     = recp;
90     fNclusters    = fClusters->GetEntriesFast();
91     SetCutAmplitude();
92     SetDAnode();
93     SetDTime();
94     SetMinPeak((Int_t)(((AliITSresponseSDD*)fResponse)->GetNoiseAfterElectronics()*5));
95     //    SetMinPeak();
96     SetMinNCells();
97     SetMaxNCells();
98     SetTimeCorr();
99     SetMinCharge();
100     fMap = new AliITSMapA1(fSegmentation,fDigits,fCutAmplitude);
101 }
102 //______________________________________________________________________
103 AliITSClusterFinderSDD::AliITSClusterFinderSDD(){
104     // default constructor
105
106     fSegmentation = 0;
107     fResponse     = 0;
108     fDigits       = 0;
109     fClusters     = 0;
110     fNclusters    = 0;
111     fMap          = 0;
112     fCutAmplitude = 0;
113     fDAnode = 0;
114     fDTime = 0;
115     fMinPeak = 0;
116     fMinNCells = 0;
117     fMaxNCells = 0;
118     fTimeCorr = 0;
119     fMinCharge = 0;
120     /*
121     SetDAnode();
122     SetDTime();
123     SetMinPeak((Int_t)(((AliITSresponseSDD*)fResponse)->GetNoiseAfterElectronics()*5));
124     SetMinNCells();
125     SetMaxNCells();
126     SetTimeCorr();
127     SetMinCharge();
128     */
129 }
130 //____________________________________________________________________________
131 AliITSClusterFinderSDD::~AliITSClusterFinderSDD(){
132     // destructor
133
134     if(fMap) delete fMap;
135 }
136 //______________________________________________________________________
137 void AliITSClusterFinderSDD::SetCutAmplitude(Float_t nsigma){
138     // set the signal threshold for cluster finder
139     Float_t baseline,noise,noiseAfterEl;
140
141     fResponse->GetNoiseParam(noise,baseline);
142     noiseAfterEl = ((AliITSresponseSDD*)fResponse)->GetNoiseAfterElectronics();
143     fCutAmplitude = (Int_t)((baseline + nsigma*noiseAfterEl));
144 }
145 //______________________________________________________________________
146 void AliITSClusterFinderSDD::Find1DClusters(){
147     // find 1D clusters
148     static AliITS *iTS = (AliITS*)gAlice->GetModule("ITS");
149   
150     // retrieve the parameters 
151     Int_t fNofMaps       = fSegmentation->Npz();
152     Int_t fMaxNofSamples = fSegmentation->Npx();
153     Int_t fNofAnodes     = fNofMaps/2;
154     Int_t dummy          = 0;
155     Float_t fTimeStep    = fSegmentation->Dpx(dummy);
156     Float_t fSddLength   = fSegmentation->Dx();
157     Float_t fDriftSpeed  = fResponse->DriftSpeed();  
158     Float_t anodePitch   = fSegmentation->Dpz(dummy);
159
160     // map the signal
161     fMap->ClearMap();
162     fMap->SetThreshold(fCutAmplitude);
163     fMap->FillMap();
164   
165     Float_t noise;
166     Float_t baseline;
167     fResponse->GetNoiseParam(noise,baseline);
168   
169     Int_t nofFoundClusters = 0;
170     Int_t i;
171     Float_t **dfadc = new Float_t*[fNofAnodes];
172     for(i=0;i<fNofAnodes;i++) dfadc[i] = new Float_t[fMaxNofSamples];
173     Float_t fadc  = 0.;
174     Float_t fadc1 = 0.;
175     Float_t fadc2 = 0.;
176     Int_t j,k,idx,l,m;
177     for(j=0;j<2;j++) {
178         for(k=0;k<fNofAnodes;k++) {
179             idx = j*fNofAnodes+k;
180             // signal (fadc) & derivative (dfadc)
181             dfadc[k][255]=0.;
182             for(l=0; l<fMaxNofSamples; l++) {
183                 fadc2=(Float_t)fMap->GetSignal(idx,l);
184                 if(l>0) fadc1=(Float_t)fMap->GetSignal(idx,l-1);
185                 if(l>0) dfadc[k][l-1] = fadc2-fadc1;
186             } // samples
187         } // anodes
188
189         for(k=0;k<fNofAnodes;k++) {
190         //cout << "Anode: " << k+1 << ", Wing: " << j+1 << endl;
191             idx = j*fNofAnodes+k;
192             Int_t imax  = 0;
193             Int_t imaxd = 0;
194             Int_t it    = 0;
195             while(it <= fMaxNofSamples-3) {
196                 imax  = it;
197                 imaxd = it;
198                 // maximum of signal          
199                 Float_t fadcmax  = 0.;
200                 Float_t dfadcmax = 0.;
201                 Int_t lthrmina   = 1;
202                 Int_t lthrmint   = 3;
203                 Int_t lthra      = 1;
204                 Int_t lthrt      = 0;
205                 for(m=0;m<20;m++) {
206                     Int_t id = it+m;
207                     if(id>=fMaxNofSamples) break;
208                     fadc=(float)fMap->GetSignal(idx,id);
209                     if(fadc > fadcmax) { fadcmax = fadc; imax = id;}
210                     if(fadc > (float)fCutAmplitude) { 
211                         lthrt++; 
212                     } // end if
213                     if(dfadc[k][id] > dfadcmax) {
214                         dfadcmax = dfadc[k][id];
215                         imaxd    = id;
216                     } // end if
217                 } // end for m
218                 it = imaxd;
219                 if(fMap->TestHit(idx,imax) == kEmpty) {it++; continue;}
220                 // cluster charge
221                 Int_t tstart = it-2;
222                 if(tstart < 0) tstart = 0;
223                 Bool_t ilcl = 0;
224                 if(lthrt >= lthrmint && lthra >= lthrmina) ilcl = 1;
225                 if(ilcl) {
226                     nofFoundClusters++;
227                     Int_t tstop      = tstart;
228                     Float_t dfadcmin = 10000.;
229                     Int_t ij;
230                     for(ij=0; ij<20; ij++) {
231                         if(tstart+ij > 255) { tstop = 255; break; }
232                         fadc=(float)fMap->GetSignal(idx,tstart+ij);
233                         if((dfadc[k][tstart+ij] < dfadcmin) && 
234                            (fadc > fCutAmplitude)) {
235                             tstop = tstart+ij+5;
236                             if(tstop > 255) tstop = 255;
237                             dfadcmin = dfadc[k][it+ij];
238                         } // end if
239                     } // end for ij
240
241                     Float_t clusterCharge = 0.;
242                     Float_t clusterAnode  = k+0.5;
243                     Float_t clusterTime   = 0.;
244                     Int_t   clusterMult   = 0;
245                     Float_t clusterPeakAmplitude = 0.;
246                     Int_t its,peakpos     = -1;
247                     Float_t n, baseline;
248                     fResponse->GetNoiseParam(n,baseline);
249                     for(its=tstart; its<=tstop; its++) {
250                         fadc=(float)fMap->GetSignal(idx,its);
251                         if(fadc>baseline) fadc -= baseline;
252                         else fadc = 0.;
253                         clusterCharge += fadc;
254                         // as a matter of fact we should take the peak
255                         // pos before FFT
256                         // to get the list of tracks !!!
257                         if(fadc > clusterPeakAmplitude) {
258                             clusterPeakAmplitude = fadc;
259                             //peakpos=fMap->GetHitIndex(idx,its);
260                             Int_t shift = (int)(fTimeCorr/fTimeStep);
261                             if(its>shift && its<(fMaxNofSamples-shift))
262                                 peakpos  = fMap->GetHitIndex(idx,its+shift);
263                             else peakpos = fMap->GetHitIndex(idx,its);
264                             if(peakpos<0) peakpos =fMap->GetHitIndex(idx,its);
265                         } // end if
266                         clusterTime += fadc*its;
267                         if(fadc > 0) clusterMult++;
268                         if(its == tstop) {
269                             clusterTime /= (clusterCharge/fTimeStep);   // ns
270                             if(clusterTime>fTimeCorr) clusterTime -=fTimeCorr;
271                             //ns
272                         } // end if
273                     } // end for its
274
275                     Float_t clusteranodePath = (clusterAnode - fNofAnodes/2)*
276                                                anodePitch;
277                     Float_t clusterDriftPath = clusterTime*fDriftSpeed;
278                     clusterDriftPath = fSddLength-clusterDriftPath;
279                     if(clusterCharge <= 0.) break;
280                     AliITSRawClusterSDD clust(j+1,//i
281                                               clusterAnode,clusterTime,//ff
282                                               clusterCharge, //f
283                                               clusterPeakAmplitude, //f
284                                               peakpos, //i
285                                               0.,0.,clusterDriftPath,//fff
286                                               clusteranodePath, //f
287                                               clusterMult, //i
288                                               0,0,0,0,0,0,0);//7*i
289                     iTS->AddCluster(1,&clust);
290                     it = tstop;
291                 } // ilcl
292                 it++;
293             } // while (samples)
294         } // anodes
295     } // detectors (2)
296
297     for(i=0;i<fNofAnodes;i++) delete[] dfadc[i];
298     delete [] dfadc;
299
300     return;
301 }
302
303
304
305 //______________________________________________________________________
306 void AliITSClusterFinderSDD::Find1DClustersE(){
307     // find 1D clusters
308     static AliITS *iTS=(AliITS*)gAlice->GetModule("ITS");
309     // retrieve the parameters 
310     Int_t fNofMaps = fSegmentation->Npz();
311     Int_t fMaxNofSamples = fSegmentation->Npx();
312     Int_t fNofAnodes = fNofMaps/2;
313     Int_t dummy=0;
314     Float_t fTimeStep = fSegmentation->Dpx( dummy );
315     Float_t fSddLength = fSegmentation->Dx();
316     Float_t fDriftSpeed = fResponse->DriftSpeed();
317     Float_t anodePitch = fSegmentation->Dpz( dummy );
318     Float_t n, baseline;
319     fResponse->GetNoiseParam( n, baseline );
320     // map the signal
321     fMap->ClearMap();
322     fMap->SetThreshold( fCutAmplitude );
323     fMap->FillMap();
324     
325     Int_t nClu = 0;
326     //        cout << "Search  cluster... "<< endl;
327     for( Int_t j=0; j<2; j++ ){
328         for( Int_t k=0; k<fNofAnodes; k++ ){
329             Int_t idx = j*fNofAnodes+k;
330             Bool_t on = kFALSE;
331             Int_t start = 0;
332             Int_t nTsteps = 0;
333             Float_t fmax = 0.;
334             Int_t lmax = 0;
335             Float_t charge = 0.;
336             Float_t time = 0.;
337             Float_t anode = k+0.5;
338             Int_t peakpos = -1;
339             for( Int_t l=0; l<fMaxNofSamples; l++ ){
340                 Float_t fadc = (Float_t)fMap->GetSignal( idx, l );
341                 if( fadc > 0.0 ){
342                     if( on == kFALSE && l<fMaxNofSamples-4){
343                         // star RawCluster (reset var.)
344                         Float_t fadc1 = (Float_t)fMap->GetSignal( idx, l+1 );
345                         if( fadc1 < fadc ) continue;
346                         start = l;
347                         fmax = 0.;
348                         lmax = 0;
349                         time = 0.;
350                         charge = 0.; 
351                         on = kTRUE; 
352                         nTsteps = 0;
353                     } // end if on...
354                     nTsteps++ ;
355                     if( fadc > baseline ) fadc -= baseline;
356                     else fadc=0.;
357                     charge += fadc;
358                     time += fadc*l;
359                     if( fadc > fmax ){ 
360                         fmax = fadc; 
361                         lmax = l; 
362                         Int_t shift = (Int_t)(fTimeCorr/fTimeStep + 0.5);
363                         if( l > shift && l < (fMaxNofSamples-shift) )  
364                             peakpos = fMap->GetHitIndex( idx, l+shift );
365                         else
366                             peakpos = fMap->GetHitIndex( idx, l );
367                         if( peakpos < 0) peakpos = fMap->GetHitIndex( idx, l );
368                     } // end if fadc
369                 }else{ // end fadc>0
370                     if( on == kTRUE ){        
371                         if( nTsteps > 2 ){
372                             //  min # of timesteps for a RawCluster
373                             // Found a RawCluster...
374                             Int_t stop = l-1;
375                             time /= (charge/fTimeStep);   // ns
376                                 // time = lmax*fTimeStep;   // ns
377                             if( time > fTimeCorr ) time -= fTimeCorr;   // ns
378                             Float_t anodePath = (anode - fNofAnodes/2)*anodePitch;
379                             Float_t driftPath = time*fDriftSpeed;
380                             driftPath = fSddLength-driftPath;
381                             AliITSRawClusterSDD clust(j+1,anode,time,charge,
382                                                       fmax, peakpos,0.,0.,
383                                                       driftPath,anodePath,
384                                                       nTsteps,start,stop,
385                                                       start, stop, 1, k, k );
386                             iTS->AddCluster( 1, &clust );
387                             //        clust.PrintInfo();
388                             nClu++;
389                         } // end if nTsteps
390                         on = kFALSE;
391                     } // end if on==kTRUE
392                 } // end if fadc>0
393             } // samples
394         } // anodes
395     } // wings
396     //        cout << "# Rawclusters " << nClu << endl;         
397     return; 
398 }
399 //_______________________________________________________________________
400 Int_t AliITSClusterFinderSDD::SearchPeak(Float_t *spect,Int_t xdim,Int_t zdim,
401                                          Int_t *peakX, Int_t *peakZ, 
402                                          Float_t *peakAmp, Float_t minpeak ){
403     // search peaks on a 2D cluster
404     Int_t npeak = 0;    // # peaks
405     Int_t i,j;
406     // search peaks
407     for( Int_t z=1; z<zdim-1; z++ ){
408         for( Int_t x=1; x<xdim-2; x++ ){
409             Float_t sxz = spect[x*zdim+z];
410             Float_t sxz1 = spect[(x+1)*zdim+z];
411             Float_t sxz2 = spect[(x-1)*zdim+z];
412             // search a local max. in s[x,z]
413             if( sxz < minpeak || sxz1 <= 0 || sxz2 <= 0 ) continue;
414             if( sxz >= spect[(x+1)*zdim+z  ] && sxz >= spect[(x-1)*zdim+z  ] &&
415                 sxz >= spect[x*zdim    +z+1] && sxz >= spect[x*zdim    +z-1] &&
416                 sxz >= spect[(x+1)*zdim+z+1] && sxz >= spect[(x+1)*zdim+z-1] &&
417                 sxz >= spect[(x-1)*zdim+z+1] && sxz >= spect[(x-1)*zdim+z-1] ){
418                 // peak found
419                 peakX[npeak] = x;
420                 peakZ[npeak] = z;
421                 peakAmp[npeak] = sxz;
422                 npeak++;
423             } // end if ....
424         } // end for x
425     } // end for z
426     // search groups of peaks with same amplitude.
427     Int_t *flag = new Int_t[npeak];
428     for( i=0; i<npeak; i++ ) flag[i] = 0;
429     for( i=0; i<npeak; i++ ){
430         for( j=0; j<npeak; j++ ){
431             if( i==j) continue;
432             if( flag[j] > 0 ) continue;
433             if( peakAmp[i] == peakAmp[j] && 
434                 TMath::Abs(peakX[i]-peakX[j])<=1 && 
435                 TMath::Abs(peakZ[i]-peakZ[j])<=1 ){
436                 if( flag[i] == 0) flag[i] = i+1;
437                 flag[j] = flag[i];
438             } // end if ...
439         } // end for j
440     } // end for i
441     // make average of peak groups        
442     for( i=0; i<npeak; i++ ){
443         Int_t nFlag = 1;
444         if( flag[i] <= 0 ) continue;
445         for( j=0; j<npeak; j++ ){
446             if( i==j ) continue;
447             if( flag[j] != flag[i] ) continue;
448             peakX[i] += peakX[j];
449             peakZ[i] += peakZ[j];
450             nFlag++;
451             npeak--;
452             for( Int_t k=j; k<npeak; k++ ){
453                 peakX[k] = peakX[k+1];
454                 peakZ[k] = peakZ[k+1];
455                 peakAmp[k] = peakAmp[k+1];
456                 flag[k] = flag[k+1];
457             } // end for k        
458             j--;
459         } // end for j
460         if( nFlag > 1 ){
461             peakX[i] /= nFlag;
462             peakZ[i] /= nFlag;
463         } // end fi nFlag
464     } // end for i
465     delete [] flag;
466     return( npeak );
467 }
468 //______________________________________________________________________
469 void AliITSClusterFinderSDD::PeakFunc( Int_t xdim, Int_t zdim, Float_t *par,
470                                        Float_t *spe, Float_t *integral){
471     // function used to fit the clusters
472     // par -> parameters..
473     // par[0]  number of peaks.
474     // for each peak i=1, ..., par[0]
475     //                 par[i] = Ampl.
476     //                 par[i+1] = xpos
477     //                 par[i+2] = zpos
478     //                 par[i+3] = tau
479     //                 par[i+4] = sigma.
480     Int_t electronics = fResponse->Electronics(); // 1 = PASCAL, 2 = OLA
481     const Int_t knParam = 5;
482     Int_t npeak = (Int_t)par[0];
483
484     memset( spe, 0, sizeof( Float_t )*zdim*xdim );
485
486     Int_t k = 1;
487     for( Int_t i=0; i<npeak; i++ ){
488         if( integral != 0 ) integral[i] = 0.;
489         Float_t sigmaA2 = par[k+4]*par[k+4]*2.;
490         Float_t t2 = par[k+3];   // PASCAL
491         if( electronics == 2 ) { t2 *= t2; t2 *= 2; } // OLA
492         for( Int_t z=0; z<zdim; z++ ){
493             for( Int_t x=0; x<xdim; x++ ){
494                 Float_t z2 = (z-par[k+2])*(z-par[k+2])/sigmaA2;
495                 Float_t x2 = 0.;
496                 Float_t signal = 0.;
497                 if( electronics == 1 ){ // PASCAL
498                     x2 = (x-par[k+1]+t2)/t2;
499                     signal = (x2>0.) ? par[k]*x2*exp(-x2+1.-z2) :0.0; // RCCR2
500                 //  signal =(x2>0.) ? par[k]*x2*x2*exp(-2*x2+2.-z2 ):0.0;//RCCR
501                 }else if( electronics == 2 ) { // OLA
502                     x2 = (x-par[k+1])*(x-par[k+1])/t2;
503                     signal = par[k]  * exp( -x2 - z2 );
504                 } else {
505                   Warning("PeakFunc","Wrong SDD Electronics = %d",electronics);
506                     // exit( 1 );
507                 } // end if electronicx
508                 spe[x*zdim+z] += signal;
509                 if( integral != 0 ) integral[i] += signal;
510             } // end for x
511         } // end for z
512         k += knParam;
513     } // end for i
514     return;
515 }
516 //__________________________________________________________________________
517 Float_t AliITSClusterFinderSDD::ChiSqr( Int_t xdim, Int_t zdim, Float_t *spe,
518                                         Float_t *speFit ) const{
519     // EVALUATES UNNORMALIZED CHI-SQUARED
520     Float_t chi2 = 0.;
521     for( Int_t z=0; z<zdim; z++ ){
522         for( Int_t x=1; x<xdim-1; x++ ){
523             Int_t index = x*zdim+z;
524             Float_t tmp = spe[index] - speFit[index];
525             chi2 += tmp*tmp;
526         } // end for x
527     } // end for z
528     return( chi2 );
529 }
530 //_______________________________________________________________________
531 void AliITSClusterFinderSDD::Minim( Int_t xdim, Int_t zdim, Float_t *param,
532                                     Float_t *prm0,Float_t *steprm,
533                                     Float_t *chisqr,Float_t *spe,
534                                     Float_t *speFit ){
535     // 
536     Int_t   k, nnn, mmm, i;
537     Float_t p1, delta, d1, chisq1, p2, chisq2, t, p3, chisq3, a, b, p0, chisqt;
538     const Int_t knParam = 5;
539     Int_t npeak = (Int_t)param[0];
540     for( k=1; k<(npeak*knParam+1); k++ ) prm0[k] = param[k];
541     for( k=1; k<(npeak*knParam+1); k++ ){
542         p1 = param[k];
543         delta = steprm[k];
544         d1 = delta;
545         // ENSURE THAT STEP SIZE IS SENSIBLY LARGER THAN MACHINE ROUND OFF
546         if( fabs( p1 ) > 1.0E-6 ) 
547             if ( fabs( delta/p1 ) < 1.0E-4 ) delta = p1/1000;
548             else  delta = (Float_t)1.0E-4;
549         //  EVALUATE CHI-SQUARED AT FIRST TWO SEARCH POINTS
550         PeakFunc( xdim, zdim, param, speFit );
551         chisq1 = ChiSqr( xdim, zdim, spe, speFit );
552         p2 = p1+delta;
553         param[k] = p2;
554         PeakFunc( xdim, zdim, param, speFit );
555         chisq2 = ChiSqr( xdim, zdim, spe, speFit );
556         if( chisq1 < chisq2 ){
557             // REVERSE DIRECTION OF SEARCH IF CHI-SQUARED IS INCREASING
558             delta = -delta;
559             t = p1;
560             p1 = p2;
561             p2 = t;
562             t = chisq1;
563             chisq1 = chisq2;
564             chisq2 = t;
565         } // end if
566         i = 1; nnn = 0;
567         do {   // INCREMENT param(K) UNTIL CHI-SQUARED STARTS TO INCREASE
568             nnn++;
569             p3 = p2 + delta;
570             mmm = nnn - (nnn/5)*5;  // multiplo de 5
571             if( mmm == 0 ){
572                 d1 = delta;
573                 // INCREASE STEP SIZE IF STEPPING TOWARDS MINIMUM IS TOO SLOW 
574                 delta *= 5;
575             } // end if
576             param[k] = p3;
577             // Constrain paramiters
578             Int_t kpos = (k-1) % knParam;
579             switch( kpos ){
580             case 0 :
581                 if( param[k] <= 20 ) param[k] = fMinPeak;
582                 break;
583             case 1 :
584                 if( fabs( param[k] - prm0[k] ) > 1.5 ) param[k] = prm0[k];
585                 break;
586             case 2 :
587                 if( fabs( param[k] - prm0[k] ) > 1. ) param[k] = prm0[k];
588                 break;
589             case 3 :
590                 if( param[k] < .5 ) param[k] = .5;        
591                 break;
592             case 4 :
593                 if( param[k] < .288 ) param[k] = .288;        // 1/sqrt(12) = 0.288
594                 if( param[k] > zdim*.5 ) param[k] = zdim*.5;
595                 break;
596             }; // end switch
597             PeakFunc( xdim, zdim, param, speFit );
598             chisq3 = ChiSqr( xdim, zdim, spe, speFit );
599             if( chisq3 < chisq2 && nnn < 50 ){
600                 p1 = p2;
601                 p2 = p3;
602                 chisq1 = chisq2;
603                 chisq2 = chisq3;
604             }else i=0;
605         } while( i );
606         // FIND MINIMUM OF PARABOLA DEFINED BY LAST THREE POINTS
607         a = chisq1*(p2-p3)+chisq2*(p3-p1)+chisq3*(p1-p2);
608         b = chisq1*(p2*p2-p3*p3)+chisq2*(p3*p3-p1*p1)+chisq3*(p1*p1-p2*p2);
609         if( a!=0 ) p0 = (Float_t)(0.5*b/a);
610         else p0 = 10000;
611         //--IN CASE OF NEARLY EQUAL CHI-SQUARED AND TOO SMALL STEP SIZE PREVENT
612         //   ERRONEOUS EVALUATION OF PARABOLA MINIMUM
613         //---NEXT TWO LINES CAN BE OMITTED FOR HIGHER PRECISION MACHINES
614         //dp = (Float_t) max (fabs(p3-p2), fabs(p2-p1));
615         //if( fabs( p2-p0 ) > dp ) p0 = p2;
616         param[k] = p0;
617         // Constrain paramiters
618         Int_t kpos = (k-1) % knParam;
619         switch( kpos ){
620         case 0 :
621             if( param[k] <= 20 ) param[k] = fMinPeak;   
622             break;
623         case 1 :
624             if( fabs( param[k] - prm0[k] ) > 1.5 ) param[k] = prm0[k];
625             break;
626         case 2 :
627             if( fabs( param[k] - prm0[k] ) > 1. ) param[k] = prm0[k];
628             break;
629         case 3 :
630             if( param[k] < .5 ) param[k] = .5;        
631             break;
632         case 4 :
633             if( param[k] < .288 ) param[k] = .288;  // 1/sqrt(12) = 0.288
634             if( param[k] > zdim*.5 ) param[k] = zdim*.5;
635             break;
636         }; // end switch
637         PeakFunc( xdim, zdim, param, speFit );
638         chisqt = ChiSqr( xdim, zdim, spe, speFit );
639         // DO NOT ALLOW ERRONEOUS INTERPOLATION
640         if( chisqt <= *chisqr ) *chisqr = chisqt;
641         else param[k] = prm0[k];
642         // OPTIMIZE SEARCH STEP FOR EVENTUAL NEXT CALL OF MINIM
643         steprm[k] = (param[k]-prm0[k])/5;
644         if( steprm[k] >= d1 ) steprm[k] = d1/5;
645     } // end for k
646     // EVALUATE FIT AND CHI-SQUARED FOR OPTIMIZED PARAMETERS
647     PeakFunc( xdim, zdim, param, speFit );
648     *chisqr = ChiSqr( xdim, zdim, spe, speFit );
649     return;
650 }
651 //_________________________________________________________________________
652 Int_t AliITSClusterFinderSDD::NoLinearFit( Int_t xdim, Int_t zdim, 
653                                            Float_t *param, Float_t *spe, 
654                                            Int_t *niter, Float_t *chir ){
655     // fit method from Comput. Phys. Commun 46(1987) 149
656     const Float_t kchilmt = 0.01;  //        relative accuracy           
657     const Int_t   knel = 3;        //        for parabolic minimization  
658     const Int_t   knstop = 50;     //        Max. iteration number          
659     const Int_t   knParam = 5;
660     Int_t npeak = (Int_t)param[0];
661     // RETURN IF NUMBER OF DEGREES OF FREEDOM IS NOT POSITIVE 
662     if( (xdim*zdim - npeak*knParam) <= 0 ) return( -1 );
663     Float_t degFree = (xdim*zdim - npeak*knParam)-1;
664     Int_t   n, k, iterNum = 0;
665     Float_t *prm0 = new Float_t[npeak*knParam+1];
666     Float_t *step = new Float_t[npeak*knParam+1];
667     Float_t *schi = new Float_t[npeak*knParam+1]; 
668     Float_t *sprm[3];
669     sprm[0] = new Float_t[npeak*knParam+1];
670     sprm[1] = new Float_t[npeak*knParam+1];
671     sprm[2] = new Float_t[npeak*knParam+1];
672     Float_t  chi0, chi1, reldif, a, b, prmin, dp;
673     Float_t *speFit = new Float_t[ xdim*zdim ];
674     PeakFunc( xdim, zdim, param, speFit );
675     chi0 = ChiSqr( xdim, zdim, spe, speFit );
676     chi1 = chi0;
677     for( k=1; k<(npeak*knParam+1); k++) prm0[k] = param[k];
678         for( k=1 ; k<(npeak*knParam+1); k+=knParam ){
679             step[k] = param[k] / 20.0 ;
680             step[k+1] = param[k+1] / 50.0;
681             step[k+2] = param[k+2] / 50.0;                 
682             step[k+3] = param[k+3] / 20.0;                 
683             step[k+4] = param[k+4] / 20.0;                 
684         } // end for k
685     Int_t out = 0;
686     do{
687         iterNum++;
688             chi0 = chi1;
689             Minim( xdim, zdim, param, prm0, step, &chi1, spe, speFit );
690             reldif = ( chi1 > 0 ) ? ((Float_t) fabs( chi1-chi0)/chi1 ) : 0;
691         // EXIT conditions
692         if( reldif < (float) kchilmt ){
693             *chir  = (chi1>0) ? (float) TMath::Sqrt (chi1/degFree) :0;
694             *niter = iterNum;
695             out = 0;
696             break;
697         } // end if
698         if( (reldif < (float)(5*kchilmt)) && (iterNum > knstop) ){
699             *chir = (chi1>0) ?(float) TMath::Sqrt (chi1/degFree):0;
700             *niter = iterNum;
701             out = 0;
702             break;
703         } // end if
704         if( iterNum > 5*knstop ){
705             *chir  = (chi1>0) ?(float) TMath::Sqrt (chi1/degFree):0;
706             *niter = iterNum;
707             out = 1;
708             break;
709         } // end if
710         if( iterNum <= knel ) continue;
711         n = iterNum - (iterNum/knel)*knel; // EXTRAPOLATION LIMIT COUNTER N
712         if( n > 3 || n == 0 ) continue;
713         schi[n-1] = chi1;
714         for( k=1; k<(npeak*knParam+1); k++ ) sprm[n-1][k] = param[k];
715         if( n != 3 ) continue;
716         // -EVALUATE EXTRAPOLATED VALUE OF EACH PARAMETER BY FINDING MINIMUM OF
717         //    PARABOLA DEFINED BY LAST THREE CALLS OF MINIM
718         for( k=1; k<(npeak*knParam+1); k++ ){
719             Float_t tmp0 = sprm[0][k];
720             Float_t tmp1 = sprm[1][k];
721             Float_t tmp2 = sprm[2][k];
722             a  = schi[0]*(tmp1-tmp2) + schi[1]*(tmp2-tmp0);
723             a += (schi[2]*(tmp0-tmp1));
724             b  = schi[0]*(tmp1*tmp1-tmp2*tmp2);
725             b += (schi[1]*(tmp2*tmp2-tmp0*tmp0)+(schi[2]*
726                                              (tmp0*tmp0-tmp1*tmp1)));
727             if ((double)a < 1.0E-6) prmin = 0;
728             else prmin = (float) (0.5*b/a);
729             dp = 5*(tmp2-tmp0);
730             if( fabs(prmin-tmp2) > fabs(dp) ) prmin = tmp2+dp;
731             param[k] = prmin;
732             step[k]  = dp/10; // OPTIMIZE SEARCH STEP
733         } // end for k
734     } while( kTRUE );
735     delete [] prm0;
736     delete [] step;
737     delete [] schi; 
738     delete [] sprm[0];
739     delete [] sprm[1];
740     delete [] sprm[2];
741     delete [] speFit;
742     return( out );
743 }
744
745 //______________________________________________________________________
746 void AliITSClusterFinderSDD::ResolveClustersE(){
747     // The function to resolve clusters if the clusters overlapping exists
748     Int_t i;
749     static AliITS *iTS = (AliITS*)gAlice->GetModule( "ITS" );
750     // get number of clusters for this module
751     Int_t nofClusters = fClusters->GetEntriesFast();
752     nofClusters -= fNclusters;
753     Int_t fNofMaps = fSegmentation->Npz();
754     Int_t fNofAnodes = fNofMaps/2;
755 //    Int_t fMaxNofSamples = fSegmentation->Npx();
756     Int_t dummy=0;
757     Double_t fTimeStep = fSegmentation->Dpx( dummy );
758     Double_t fSddLength = fSegmentation->Dx();
759     Double_t fDriftSpeed = fResponse->DriftSpeed();
760     Double_t anodePitch = fSegmentation->Dpz( dummy );
761     Float_t n, baseline;
762     fResponse->GetNoiseParam( n, baseline );
763     Int_t electronics = fResponse->Electronics(); // 1 = PASCAL, 2 = OLA
764
765     for( Int_t j=0; j<nofClusters; j++ ){ 
766         // get cluster information
767         AliITSRawClusterSDD *clusterJ=(AliITSRawClusterSDD*) fClusters->At(j);
768         Int_t astart = clusterJ->Astart();
769         Int_t astop = clusterJ->Astop();
770         Int_t tstart = clusterJ->Tstartf();
771         Int_t tstop = clusterJ->Tstopf();
772         Int_t wing = (Int_t)clusterJ->W();
773         if( wing == 2 ){
774             astart += fNofAnodes; 
775             astop  += fNofAnodes;
776         } // end if 
777         Int_t xdim = tstop-tstart+3;
778         Int_t zdim = astop-astart+3;
779         if( xdim > 50 || zdim > 30 ) { 
780             Warning("ResolveClustersE","xdim: %d , zdim: %d ",xdim,zdim);
781             continue;
782         }
783         Float_t *sp = new Float_t[ xdim*zdim+1 ];
784         memset( sp, 0, sizeof(Float_t)*(xdim*zdim+1) );
785         
786         // make a local map from cluster region
787         for( Int_t ianode=astart; ianode<=astop; ianode++ ){
788             for( Int_t itime=tstart; itime<=tstop; itime++ ){
789                 Float_t fadc = fMap->GetSignal( ianode, itime );
790                 if( fadc > baseline ) fadc -= (Double_t)baseline;
791                 else fadc = 0.;
792                 Int_t index = (itime-tstart+1)*zdim+(ianode-astart+1);
793                 sp[index] = fadc;
794             } // time loop
795         } // anode loop
796         
797         // search peaks on cluster
798         const Int_t kNp = 150;
799         Int_t peakX1[kNp];
800         Int_t peakZ1[kNp];
801         Float_t peakAmp1[kNp];
802         Int_t npeak = SearchPeak(sp,xdim,zdim,peakX1,peakZ1,peakAmp1,fMinPeak);
803
804         // if multiple peaks, split cluster
805         if( npeak >= 1 )
806         {
807             //        cout << "npeak " << npeak << endl;
808             //        clusterJ->PrintInfo();
809             Float_t *par = new Float_t[npeak*5+1];
810             par[0] = (Float_t)npeak;                
811             // Initial parameters in cell dimentions
812             Int_t k1 = 1;
813             for( i=0; i<npeak; i++ ){
814                 par[k1] = peakAmp1[i];
815                 par[k1+1] = peakX1[i]; // local time pos. [timebin]
816                 par[k1+2] = peakZ1[i]; // local anode pos. [anodepitch]
817                 if( electronics == 1 ) 
818                     par[k1+3] = 2.; // PASCAL
819                 else if( electronics == 2 ) 
820                     par[k1+3] = 0.7; // tau [timebin]  OLA 
821                 par[k1+4] = .4;    // sigma        [anodepich]
822                 k1+=5;
823             } // end for i                        
824             Int_t niter;
825             Float_t chir;                        
826             NoLinearFit( xdim, zdim, par, sp, &niter, &chir );
827             Float_t peakX[kNp];
828             Float_t peakZ[kNp];
829             Float_t sigma[kNp];
830             Float_t tau[kNp];
831             Float_t peakAmp[kNp];
832             Float_t integral[kNp];
833             //get integrals => charge for each peak
834             PeakFunc( xdim, zdim, par, sp, integral );
835             k1 = 1;
836             for( i=0; i<npeak; i++ ){
837                 peakAmp[i] = par[k1];
838                 peakX[i]   = par[k1+1];
839                 peakZ[i]   = par[k1+2];
840                 tau[i]     = par[k1+3];
841                 sigma[i]   = par[k1+4];
842                 k1+=5;
843             } // end for i
844             // calculate parameter for new clusters
845             for( i=0; i<npeak; i++ ){
846                 AliITSRawClusterSDD clusterI( *clusterJ );
847             
848                 Int_t newAnode = peakZ1[i]-1 + astart;
849
850             //    Int_t newiTime = peakX1[i]-1 + tstart;
851             //    Int_t shift = (Int_t)(fTimeCorr/fTimeStep + 0.5);
852             //    if( newiTime > shift && newiTime < (fMaxNofSamples-shift) ) 
853             //        shift = 0;
854             //    Int_t peakpos = fMap->GetHitIndex( newAnode, newiTime+shift );
855             //    clusterI.SetPeakPos( peakpos );
856             
857                 clusterI.SetPeakAmpl( peakAmp1[i] );
858                 Float_t newAnodef = peakZ[i] - 0.5 + astart;
859                 Float_t newiTimef = peakX[i] - 1 + tstart;
860                 if( wing == 2 ) newAnodef -= fNofAnodes; 
861                 Float_t anodePath = (newAnodef - fNofAnodes/2)*anodePitch;
862                 newiTimef *= fTimeStep;
863                 if( newiTimef > fTimeCorr ) newiTimef -= fTimeCorr;
864                 if( electronics == 1 ){
865                 //    newiTimef *= 0.999438;    // PASCAL
866                 //    newiTimef += (6./fDriftSpeed - newiTimef/3000.);
867                 }else if( electronics == 2 )
868                     newiTimef *= 0.99714;    // OLA
869                     
870                 Int_t timeBin = (Int_t)(newiTimef/fTimeStep+0.5);    
871                 Int_t peakpos = fMap->GetHitIndex( newAnode, timeBin );
872                 if( peakpos < 0 ) { 
873                     for( Int_t ii=0; ii<3; ii++ ) {
874                         peakpos = fMap->GetHitIndex( newAnode, timeBin+ii );
875                         if( peakpos > 0 ) break;
876                         peakpos = fMap->GetHitIndex( newAnode, timeBin-ii );
877                         if( peakpos > 0 ) break;
878                     }
879                 }
880                 
881                 if( peakpos < 0 ) { 
882              //      Warning( "ResolveClustersE", "Digit not found for cluster:\n" );
883              //      clusterI.PrintInfo(); 
884                    continue;
885                 }
886                 clusterI.SetPeakPos( peakpos );    
887                 Float_t driftPath = fSddLength - newiTimef * fDriftSpeed;
888                 Float_t sign = ( wing == 1 ) ? -1. : 1.;
889                 clusterI.SetX( driftPath*sign * 0.0001 );        
890                 clusterI.SetZ( anodePath * 0.0001 );
891                 clusterI.SetAnode( newAnodef );
892                 clusterI.SetTime( newiTimef );
893                 clusterI.SetAsigma( sigma[i]*anodePitch );
894                 clusterI.SetTsigma( tau[i]*fTimeStep );
895                 clusterI.SetQ( integral[i] );
896                 
897                 iTS->AddCluster( 1, &clusterI );
898             } // end for i
899             fClusters->RemoveAt( j );
900             delete [] par;
901         } else {  // something odd
902             Warning( "ResolveClustersE","--- Peak not found!!!!  minpeak=%d ,cluster peak= %f , module= %d",
903                       fMinPeak, clusterJ->PeakAmpl(), fModule ); 
904             clusterJ->PrintInfo();
905             Warning( "ResolveClustersE"," xdim= %d zdim= %d", xdim-2, zdim-2 );
906         }
907         delete [] sp;
908     } // cluster loop
909     fClusters->Compress();
910 //    fMap->ClearMap(); 
911 }
912
913
914 //________________________________________________________________________
915 void  AliITSClusterFinderSDD::GroupClusters(){
916     // group clusters
917     Int_t dummy=0;
918     Float_t fTimeStep = fSegmentation->Dpx(dummy);
919     // get number of clusters for this module
920     Int_t nofClusters = fClusters->GetEntriesFast();
921     nofClusters -= fNclusters;
922     AliITSRawClusterSDD *clusterI;
923     AliITSRawClusterSDD *clusterJ;
924     Int_t *label = new Int_t [nofClusters];
925     Int_t i,j;
926     for(i=0; i<nofClusters; i++) label[i] = 0;
927     for(i=0; i<nofClusters; i++) { 
928         if(label[i] != 0) continue;
929         for(j=i+1; j<nofClusters; j++) { 
930             if(label[j] != 0) continue;
931             clusterI = (AliITSRawClusterSDD*) fClusters->At(i);
932             clusterJ = (AliITSRawClusterSDD*) fClusters->At(j);
933             // 1.3 good
934             if(clusterI->T() < fTimeStep*60) fDAnode = 4.2;  // TB 3.2  
935             if(clusterI->T() < fTimeStep*10) fDAnode = 1.5;  // TB 1.
936             Bool_t pair = clusterI->Brother(clusterJ,fDAnode,fDTime);
937             if(!pair) continue;
938             //      clusterI->PrintInfo();
939             //      clusterJ->PrintInfo();
940             clusterI->Add(clusterJ);
941             label[j] = 1;
942             fClusters->RemoveAt(j);
943             j=i; // <- Ernesto
944         } // J clusters  
945         label[i] = 1;
946     } // I clusters
947     fClusters->Compress();
948
949     delete [] label;
950     return;
951 }
952 //________________________________________________________________________
953 void AliITSClusterFinderSDD::SelectClusters(){
954     // get number of clusters for this module
955     Int_t nofClusters = fClusters->GetEntriesFast();
956
957     nofClusters -= fNclusters;
958     Int_t i;
959     for(i=0; i<nofClusters; i++) { 
960         AliITSRawClusterSDD *clusterI =(AliITSRawClusterSDD*) fClusters->At(i);
961         Int_t rmflg = 0;
962         Float_t wy = 0.;
963         if(clusterI->Anodes() != 0.) {
964             wy = ((Float_t) clusterI->Samples())/clusterI->Anodes();
965         } // end if
966         Int_t amp = (Int_t) clusterI->PeakAmpl();
967         Int_t cha = (Int_t) clusterI->Q();
968         if(amp < fMinPeak) rmflg = 1;  
969         if(cha < fMinCharge) rmflg = 1;
970         if(wy < fMinNCells) rmflg = 1;
971         //if(wy > fMaxNCells) rmflg = 1;
972         if(rmflg) fClusters->RemoveAt(i);
973     } // I clusters
974     fClusters->Compress();
975     return;
976 }
977 //__________________________________________________________________________
978 void AliITSClusterFinderSDD::ResolveClusters(){
979     // The function to resolve clusters if the clusters overlapping exists
980 /*    AliITS *iTS=(AliITS*)gAlice->GetModule("ITS");
981     // get number of clusters for this module
982     Int_t nofClusters = fClusters->GetEntriesFast();
983     nofClusters -= fNclusters;
984     //cout<<"Resolve Cl: nofClusters, fNclusters ="<<nofClusters<<","
985     // <<fNclusters<<endl;
986     Int_t fNofMaps = fSegmentation->Npz();
987     Int_t fNofAnodes = fNofMaps/2;
988     Int_t dummy=0;
989     Double_t fTimeStep = fSegmentation->Dpx(dummy);
990     Double_t fSddLength = fSegmentation->Dx();
991     Double_t fDriftSpeed = fResponse->DriftSpeed();
992     Double_t anodePitch = fSegmentation->Dpz(dummy);
993     Float_t n, baseline;
994     fResponse->GetNoiseParam(n,baseline);
995     Float_t dzz_1A = anodePitch * anodePitch / 12;
996     // fill Map of signals
997     fMap->FillMap(); 
998     Int_t j,i,ii,ianode,anode,itime;
999     Int_t wing,astart,astop,tstart,tstop,nanode;
1000     Double_t fadc,ClusterTime;
1001     Double_t q[400],x[400],z[400]; // digit charges and coordinates
1002     for(j=0; j<nofClusters; j++) { 
1003         AliITSRawClusterSDD *clusterJ=(AliITSRawClusterSDD*) fClusters->At(j);
1004         Int_t ndigits = 0;
1005         astart=clusterJ->Astart();
1006         astop=clusterJ->Astop();
1007         tstart=clusterJ->Tstartf();
1008         tstop=clusterJ->Tstopf();
1009         nanode=clusterJ->Anodes();  // <- Ernesto
1010         wing=(Int_t)clusterJ->W();
1011         if(wing == 2) {
1012             astart += fNofAnodes; 
1013             astop  += fNofAnodes;
1014         }  // end if
1015         // cout<<"astart,astop,tstart,tstop ="<<astart<<","<<astop<<","
1016         //      <<tstart<<","<<tstop<<endl;
1017         // clear the digit arrays
1018         for(ii=0; ii<400; ii++) { 
1019             q[ii] = 0.; 
1020             x[ii] = 0.;
1021             z[ii] = 0.;
1022         } // end for ii
1023
1024         for(ianode=astart; ianode<=astop; ianode++) { 
1025             for(itime=tstart; itime<=tstop; itime++) { 
1026                 fadc=fMap->GetSignal(ianode,itime);
1027                 if(fadc>baseline) {
1028                     fadc-=(Double_t)baseline;
1029                     q[ndigits] = fadc*(fTimeStep/160);  // KeV
1030                     anode = ianode;
1031                     if(wing == 2) anode -= fNofAnodes;
1032                     z[ndigits] = (anode + 0.5 - fNofAnodes/2)*anodePitch;
1033                     ClusterTime = itime*fTimeStep;
1034                     if(ClusterTime > fTimeCorr) ClusterTime -= fTimeCorr;// ns
1035                     x[ndigits] = fSddLength - ClusterTime*fDriftSpeed;
1036                     if(wing == 1) x[ndigits] *= (-1);
1037                     // cout<<"ianode,itime,fadc ="<<ianode<<","<<itime<<","
1038                     //     <<fadc<<endl;
1039                     // cout<<"wing,anode,ndigits,charge ="<<wing<<","
1040                     //      <<anode<<","<<ndigits<<","<<q[ndigits]<<endl;
1041                     ndigits++;
1042                     continue;
1043                 } //  end if
1044                 fadc=0;
1045                 //              cout<<"fadc=0, ndigits ="<<ndigits<<endl;
1046             } // time loop
1047         } // anode loop
1048         //     cout<<"for new cluster ndigits ="<<ndigits<<endl;
1049         // Fit cluster to resolve for two separate ones --------------------
1050         Double_t qq=0., xm=0., zm=0., xx=0., zz=0., xz=0.;
1051         Double_t dxx=0., dzz=0., dxz=0.;
1052         Double_t scl = 0., tmp, tga, elps = -1.;
1053         Double_t xfit[2], zfit[2], qfit[2];
1054         Double_t pitchz = anodePitch*1.e-4;             // cm
1055         Double_t pitchx = fTimeStep*fDriftSpeed*1.e-4;  // cm
1056         Double_t sigma2;
1057         Int_t nfhits;
1058         Int_t nbins = ndigits;
1059         Int_t separate = 0;
1060         // now, all lengths are in microns
1061         for (ii=0; ii<nbins; ii++) {
1062             qq += q[ii];
1063             xm += x[ii]*q[ii];
1064             zm += z[ii]*q[ii];
1065             xx += x[ii]*x[ii]*q[ii];
1066             zz += z[ii]*z[ii]*q[ii];
1067             xz += x[ii]*z[ii]*q[ii];
1068         } // end for ii
1069         xm /= qq;
1070         zm /= qq;
1071         xx /= qq;
1072         zz /= qq;
1073         xz /= qq;
1074         dxx = xx - xm*xm;
1075         dzz = zz - zm*zm;
1076         dxz = xz - xm*zm;
1077
1078         // shrink the cluster in the time direction proportionaly to the 
1079         // dxx/dzz, which lineary depends from the drift path
1080         // new  Ernesto........         
1081         if( nanode == 1 ){
1082             dzz = dzz_1A; // for one anode cluster dzz = anode**2/12
1083             scl = TMath::Sqrt( 7.2/(-0.57*xm*1.e-3+71.8) );
1084         } // end if
1085         if( nanode == 2 ){
1086             scl = TMath::Sqrt( (-0.18*xm*1.e-3+21.3)/(-0.57*xm*1.e-3+71.8) );
1087         } // end if
1088         if( nanode == 3 ){
1089             scl = TMath::Sqrt( (-0.5*xm*1.e-3+34.5)/(-0.57*xm*1.e-3+71.8) );
1090         } // end if
1091         if( nanode > 3 ){
1092             scl = TMath::Sqrt( (1.3*xm*1.e-3+49.)/(-0.57*xm*1.e-3+71.8) );
1093         } // end if
1094         //   cout<<"1 microns: zm,dzz,xm,dxx,dxz,qq ="<<zm<<","<<dzz<<","
1095         //  <<xm<<","<<dxx<<","<<dxz<<","<<qq<<endl;
1096         //  old Boris.........
1097         //  tmp=29730. - 585.*fabs(xm/1000.); 
1098         //  scl=TMath::Sqrt(tmp/130000.);
1099    
1100         xm *= scl;
1101         xx *= scl*scl;
1102         xz *= scl;
1103
1104         dxx = xx - xm*xm;
1105         //   dzz = zz - zm*zm;
1106         dxz = xz - xm*zm;
1107         //   cout<<"microns: zm,dzz,xm,dxx,xz,dxz,qq ="<<zm<<","<<dzz<<","
1108         // <<xm<<","<<dxx<<","<<xz<<","<<dxz<<","<<qq<<endl;
1109         // if(dzz < 7200.) dzz=7200.;//for one anode cluster dzz = anode**2/12
1110   
1111         if (dxx < 0.) dxx=0.;
1112         // the data if no cluster overlapping (the coordunates are in cm) 
1113         nfhits = 1;
1114         xfit[0] = xm*1.e-4;
1115         zfit[0] = zm*1.e-4;
1116         qfit[0] = qq;
1117         //   if(nbins < 7) cout<<"**** nbins ="<<nbins<<endl;
1118   
1119         if (nbins >= 7) {
1120             if (dxz==0.) tga=0.;
1121             else {
1122                 tmp=0.5*(dzz-dxx)/dxz;
1123                 tga = (dxz<0.) ? tmp-TMath::Sqrt(tmp*tmp+1) : 
1124                                                    tmp+TMath::Sqrt(tmp*tmp+1);
1125             } // end if dxz
1126             elps=(tga*tga*dxx-2*tga*dxz+dzz)/(dxx+2*tga*dxz+tga*tga*dzz);
1127             // change from microns to cm
1128             xm *= 1.e-4; 
1129             zm *= 1.e-4; 
1130             zz *= 1.e-8;
1131             xx *= 1.e-8;
1132             xz *= 1.e-8;
1133             dxz *= 1.e-8;
1134             dxx *= 1.e-8;
1135             dzz *= 1.e-8;
1136             //   cout<<"cm: zm,dzz,xm,dxx,xz,dxz,qq ="<<zm<<","<<dzz<<","
1137             //  <<xm<<","<<dxx<<","<<xz<<","<<dxz<<","<<qq<<endl;
1138             for (i=0; i<nbins; i++) {     
1139                 x[i] = x[i] *= scl;
1140                 x[i] = x[i] *= 1.e-4;
1141                 z[i] = z[i] *= 1.e-4;
1142             } // end for i
1143             //     cout<<"!!! elps ="<<elps<<endl;
1144             if (elps < 0.3) { // try to separate hits 
1145                 separate = 1;
1146                 tmp=atan(tga);
1147                 Double_t cosa=cos(tmp),sina=sin(tmp);
1148                 Double_t a1=0., x1=0., xxx=0.;
1149                 for (i=0; i<nbins; i++) {
1150                     tmp=x[i]*cosa + z[i]*sina;
1151                     if (q[i] > a1) {
1152                         a1=q[i];
1153                         x1=tmp;
1154                     } // end if
1155                     xxx += tmp*tmp*tmp*q[i];
1156                 } // end for i
1157                 xxx /= qq;
1158                 Double_t z12=-sina*xm + cosa*zm;
1159                 sigma2=(sina*sina*xx-2*cosa*sina*xz+cosa*cosa*zz) - z12*z12;
1160                 xm=cosa*xm + sina*zm;
1161                 xx=cosa*cosa*xx + 2*cosa*sina*xz + sina*sina*zz;
1162                 Double_t x2=(xx - xm*x1 - sigma2)/(xm - x1);
1163                 Double_t r=a1*2*TMath::ACos(-1.)*sigma2/(qq*pitchx*pitchz);
1164                 for (i=0; i<33; i++) { // solve a system of equations
1165                     Double_t x1_old=x1, x2_old=x2, r_old=r;
1166                     Double_t c11=x1-x2;
1167                     Double_t c12=r;
1168                     Double_t c13=1-r;
1169                     Double_t c21=x1*x1 - x2*x2;
1170                     Double_t c22=2*r*x1;
1171                     Double_t c23=2*(1-r)*x2;
1172                     Double_t c31=3*sigma2*(x1-x2) + x1*x1*x1 - x2*x2*x2;
1173                     Double_t c32=3*r*(sigma2 + x1*x1);
1174                     Double_t c33=3*(1-r)*(sigma2 + x2*x2);
1175                     Double_t f1=-(r*x1 + (1-r)*x2 - xm);
1176                     Double_t f2=-(r*(sigma2+x1*x1)+(1-r)*(sigma2+x2*x2)- xx);
1177                     Double_t f3=-(r*x1*(3*sigma2+x1*x1)+(1-r)*x2*
1178                                                          (3*sigma2+x2*x2)-xxx);
1179                     Double_t d=c11*c22*c33+c21*c32*c13+c12*c23*c31-
1180                                        c31*c22*c13 - c21*c12*c33 - c32*c23*c11;
1181                     if (d==0.) {
1182                         cout<<"*********** d=0 ***********\n";
1183                         break;
1184                     } // end if
1185                     Double_t dr=f1*c22*c33 + f2*c32*c13 + c12*c23*f3 -
1186                         f3*c22*c13 - f2*c12*c33 - c32*c23*f1;
1187                     Double_t d1=c11*f2*c33 + c21*f3*c13 + f1*c23*c31 -
1188                         c31*f2*c13 - c21*f1*c33 - f3*c23*c11;
1189                     Double_t d2=c11*c22*f3 + c21*c32*f1 + c12*f2*c31 -
1190                         c31*c22*f1 - c21*c12*f3 - c32*f2*c11;
1191                     r  += dr/d;
1192                     x1 += d1/d;
1193                     x2 += d2/d;
1194                     if (fabs(x1-x1_old) > 0.0001) continue;
1195                     if (fabs(x2-x2_old) > 0.0001) continue;
1196                     if (fabs(r-r_old)/5 > 0.001) continue;
1197                     a1=r*qq*pitchx*pitchz/(2*TMath::ACos(-1.)*sigma2);
1198                     Double_t a2=a1*(1-r)/r;
1199                     qfit[0]=a1; xfit[0]=x1*cosa - z12*sina; zfit[0]=x1*sina + 
1200                                                                 z12*cosa;
1201                     qfit[1]=a2; xfit[1]=x2*cosa - z12*sina; zfit[1]=x2*sina + 
1202                                                                 z12*cosa;
1203                     nfhits=2;
1204                     break; // Ok !
1205                 } // end for i
1206                 if (i==33) cerr<<"No more iterations ! "<<endl;
1207             } // end of attempt to separate overlapped clusters
1208         } // end of nbins cut 
1209         if(elps < 0.) cout<<" elps=-1 ="<<elps<<endl;
1210         if(elps >0. && elps< 0.3 && nfhits == 1) cout<<" small elps, nfh=1 ="
1211                                                      <<elps<<","<<nfhits<<endl;
1212         if(nfhits == 2) cout<<" nfhits=2 ="<<nfhits<<endl;
1213         for (i=0; i<nfhits; i++) {
1214             xfit[i] *= (1.e+4/scl);
1215             if(wing == 1) xfit[i] *= (-1);
1216             zfit[i] *= 1.e+4;
1217             //       cout<<" ---------  i,xfiti,zfiti,qfiti ="<<i<<","
1218             // <<xfit[i]<<","<<zfit[i]<<","<<qfit[i]<<endl;
1219         } // end for i
1220         Int_t ncl = nfhits;
1221         if(nfhits == 1 && separate == 1) {
1222             cout<<"!!!!! no separate"<<endl;
1223             ncl = -2;
1224         }  // end if
1225         if(nfhits == 2) {
1226             cout << "Split cluster: " << endl;
1227             clusterJ->PrintInfo();
1228             cout << " in: " << endl;
1229             for (i=0; i<nfhits; i++) {
1230                 // AliITSRawClusterSDD *clust = new AliITSRawClusterSDD(wing,
1231                                                -1,-1,(Float_t)qfit[i],ncl,0,0,
1232                                                (Float_t)xfit[i],
1233                                                (Float_t)zfit[i],0,0,0,0,
1234                                                 tstart,tstop,astart,astop);
1235             //        AliITSRawClusterSDD *clust = new AliITSRawClusterSDD(wing,-1,
1236             //                                 -1,(Float_t)qfit[i],0,0,0,
1237             //                                  (Float_t)xfit[i],
1238             //                                  (Float_t)zfit[i],0,0,0,0,
1239             //                                  tstart,tstop,astart,astop,ncl);
1240             // ???????????
1241             // if(wing == 1) xfit[i] *= (-1);
1242             Float_t Anode = (zfit[i]/anodePitch+fNofAnodes/2-0.5);
1243             Float_t Time = (fSddLength - xfit[i])/fDriftSpeed;
1244             Float_t clusterPeakAmplitude = clusterJ->PeakAmpl();
1245             Float_t peakpos = clusterJ->PeakPos();
1246             Float_t clusteranodePath = (Anode - fNofAnodes/2)*anodePitch;
1247             Float_t clusterDriftPath = Time*fDriftSpeed;
1248             clusterDriftPath = fSddLength-clusterDriftPath;
1249             AliITSRawClusterSDD *clust = new AliITSRawClusterSDD(wing,Anode,
1250                                                                  Time,qfit[i],
1251                                                clusterPeakAmplitude,peakpos,
1252                                                0.,0.,clusterDriftPath,
1253                                          clusteranodePath,clusterJ->Samples()/2
1254                                     ,tstart,tstop,0,0,0,astart,astop);
1255             clust->PrintInfo();
1256             iTS->AddCluster(1,clust);
1257             //        cout<<"new cluster added: tstart,tstop,astart,astop,x,ncl ="
1258             // <<tstart<<","<<tstop<<","<<astart<<","<<astop<<","<<xfit[i]
1259             // <<","<<ncl<<endl;
1260             delete clust;
1261         }// nfhits loop
1262         fClusters->RemoveAt(j);
1263     } // if nfhits = 2
1264 } // cluster loop
1265 fClusters->Compress();
1266 fMap->ClearMap(); 
1267 */
1268     return;
1269 }
1270 //______________________________________________________________________
1271 void AliITSClusterFinderSDD::GetRecPoints(){
1272     // get rec points
1273     static AliITS *iTS=(AliITS*)gAlice->GetModule("ITS");
1274     // get number of clusters for this module
1275     Int_t nofClusters = fClusters->GetEntriesFast();
1276     nofClusters -= fNclusters;
1277     const Float_t kconvGeV = 1.e-6; // GeV -> KeV
1278     const Float_t kconv = 1.0e-4; 
1279     const Float_t kRMSx = 38.0*kconv; // microns->cm ITS TDR Table 1.3
1280     const Float_t kRMSz = 28.0*kconv; // microns->cm ITS TDR Table 1.3
1281     Int_t i;
1282     Int_t ix, iz, idx=-1;
1283     AliITSdigitSDD *dig=0;
1284     Int_t ndigits=fDigits->GetEntriesFast();
1285     for(i=0; i<nofClusters; i++) { 
1286         AliITSRawClusterSDD *clusterI = (AliITSRawClusterSDD*)fClusters->At(i);
1287         if(!clusterI) Error("SDD: GetRecPoints","i clusterI ",i,clusterI);
1288         if(clusterI) idx=clusterI->PeakPos();
1289         if(idx>ndigits) Error("SDD: GetRecPoints","idx ndigits",idx,ndigits);
1290         // try peak neighbours - to be done 
1291         if(idx&&idx<= ndigits) dig =(AliITSdigitSDD*)fDigits->UncheckedAt(idx);
1292         if(!dig) {
1293             // try cog
1294             fSegmentation->GetPadIxz(clusterI->X(),clusterI->Z(),ix,iz);
1295             dig = (AliITSdigitSDD*)fMap->GetHit(iz-1,ix-1);
1296             // if null try neighbours
1297             if (!dig) dig = (AliITSdigitSDD*)fMap->GetHit(iz-1,ix); 
1298             if (!dig) dig = (AliITSdigitSDD*)fMap->GetHit(iz-1,ix+1); 
1299             if (!dig) printf("SDD: cannot assign the track number!\n");
1300         } //  end if !dig
1301         AliITSRecPoint rnew;
1302         rnew.SetX(clusterI->X());
1303         rnew.SetZ(clusterI->Z());
1304         rnew.SetQ(clusterI->Q());   // in KeV - should be ADC
1305         rnew.SetdEdX(kconvGeV*clusterI->Q());
1306         rnew.SetSigmaX2(kRMSx*kRMSx);
1307         rnew.SetSigmaZ2(kRMSz*kRMSz);
1308
1309         if(dig) rnew.fTracks[0]=dig->GetTrack(0);
1310         if(dig) rnew.fTracks[1]=dig->GetTrack(1);
1311         if(dig) rnew.fTracks[2]=dig->GetTrack(2);
1312
1313         iTS->AddRecPoint(rnew);
1314     } // I clusters
1315 //    fMap->ClearMap();
1316 }
1317 //______________________________________________________________________
1318 void AliITSClusterFinderSDD::FindRawClusters(Int_t mod){
1319     // find raw clusters
1320     
1321     fModule = mod;
1322     
1323     Find1DClustersE();
1324     GroupClusters();
1325     SelectClusters();
1326     ResolveClustersE();
1327     GetRecPoints();
1328 }
1329 //_______________________________________________________________________
1330 void AliITSClusterFinderSDD::Print() const{
1331     // Print SDD cluster finder Parameters
1332
1333     cout << "**************************************************" << endl;
1334     cout << " Silicon Drift Detector Cluster Finder Parameters " << endl;
1335     cout << "**************************************************" << endl;
1336     cout << "Number of Clusters: " << fNclusters << endl;
1337     cout << "Anode Tolerance: " << fDAnode << endl;
1338     cout << "Time  Tolerance: " << fDTime << endl;
1339     cout << "Time  correction (electronics): " << fTimeCorr << endl;
1340     cout << "Cut Amplitude (threshold): " << fCutAmplitude << endl;
1341     cout << "Minimum Amplitude: " << fMinPeak << endl;
1342     cout << "Minimum Charge: " << fMinCharge << endl;
1343     cout << "Minimum number of cells/clusters: " << fMinNCells << endl;
1344     cout << "Maximum number of cells/clusters: " << fMaxNCells << endl;
1345     cout << "**************************************************" << endl;
1346 }