]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONClusterFinderVS.cxx
Reversing previous commit (Gines)
[u/mrichter/AliRoot.git] / MUON / AliMUONClusterFinderVS.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
18 #include <TMinuit.h> 
19 #include <TF1.h>
20
21 #include "AliMUONClusterFinderVS.h"
22 #include "AliMUONDigit.h"
23 #include "AliMUONRawCluster.h"
24 #include "AliSegmentation.h"
25 #include "AliMUONResponse.h"
26 #include "AliMUONClusterInput.h"
27 #include "AliMUONHitMapA1.h"
28
29 //_____________________________________________________________________
30 // This function is minimized in the double-Mathieson fit
31 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
32 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
33 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
34 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
35
36 ClassImp(AliMUONClusterFinderVS)
37
38 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
39   : TObject()
40 {
41 // Default constructor
42     fInput=AliMUONClusterInput::Instance();
43     fHitMap[0] = 0;
44     fHitMap[1] = 0;
45     fTrack[0]=fTrack[1]=-1;
46     fDebugLevel = 0; // make silent default
47     fGhostChi2Cut = 1e6; // nothing done by default
48     fSeg[0]    = 0;
49     fSeg[1]    = 0;
50     for(Int_t i=0; i<100; i++) {
51       for (Int_t j=0; j<2; j++) {
52         fDig[i][j] = 0;
53       }
54     } 
55     fRawClusters = new TClonesArray("AliMUONRawCluster",1000);
56     fNRawClusters = 0;
57 }
58  //____________________________________________________________________________
59 AliMUONClusterFinderVS::~AliMUONClusterFinderVS()
60 {
61   // Reset tracks information
62    fNRawClusters = 0;
63    if (fRawClusters) {
64      fRawClusters->Delete();
65      delete fRawClusters;
66    }
67 }
68
69 AliMUONClusterFinderVS::AliMUONClusterFinderVS(const AliMUONClusterFinderVS & clusterFinder):TObject(clusterFinder)
70 {
71 // Protected copy constructor
72
73   Fatal("AliMUONClusterFinderAZModule", "Not implemented.");
74 }
75 //____________________________________________________________________________
76 void AliMUONClusterFinderVS::ResetRawClusters()
77 {
78   // Reset tracks information
79   fNRawClusters = 0;
80   if (fRawClusters) fRawClusters->Clear();
81 }
82 //____________________________________________________________________________
83 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
84 {
85 // Decluster by local maxima
86     SplitByLocalMaxima(cluster);
87 }
88 //____________________________________________________________________________
89 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
90 {
91 // Split complex cluster by local maxima 
92     Int_t cath, i;
93
94     fInput->SetCluster(c);
95
96     fMul[0]=c->GetMultiplicity(0);
97     fMul[1]=c->GetMultiplicity(1);
98
99 //
100 //  dump digit information into arrays
101 //
102
103     Float_t qtot;
104     
105     for (cath=0; cath<2; cath++) {
106         qtot=0;
107         for (i=0; i<fMul[cath]; i++)
108         {
109             // pointer to digit
110             fDig[i][cath]=fInput->Digit(cath, c->GetIndex(i, cath));
111             // pad coordinates
112             fIx[i][cath]= fDig[i][cath]->PadX();
113             fIy[i][cath]= fDig[i][cath]->PadY();
114             // pad charge
115             fQ[i][cath] = fDig[i][cath]->Signal();
116             // pad centre coordinates
117             fSeg[cath]->
118                 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], fZ[i][cath]);
119         } // loop over cluster digits
120     }  // loop over cathodes
121
122
123     FindLocalMaxima(c);
124
125 //
126 //  Initialise and perform mathieson fits
127     Float_t chi2, oldchi2;
128 //  ++++++++++++++++++*************+++++++++++++++++++++
129 //  (1) No more than one local maximum per cathode plane 
130 //  +++++++++++++++++++++++++++++++*************++++++++
131     if ((fNLocal[0]==1 && (fNLocal[1]==0 ||  fNLocal[1]==1)) || 
132         (fNLocal[0]==0 && fNLocal[1]==1)) {
133 // Perform combined single Mathieson fit
134 // Initial values for coordinates (x,y) 
135
136         // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
137         if (fNLocal[0]==1 &&  fNLocal[1]==1) {
138             fXInit[0]=c->GetX(1);
139             fYInit[0]=c->GetY(0);
140             // One local maximum on cathode 1 (X,Y->cathode 1)
141         } else if (fNLocal[0]==1) {
142             fXInit[0]=c->GetX(0);
143             fYInit[0]=c->GetY(0);
144             // One local maximum on cathode 2  (X,Y->cathode 2)
145         } else {
146             fXInit[0]=c->GetX(1);
147             fYInit[0]=c->GetY(1);
148         }
149         if (fDebugLevel)
150             fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
151         chi2=CombiSingleMathiesonFit(c);
152 //      Int_t ndf = fgNbins[0]+fgNbins[1]-2;
153 //      Float_t prob = TMath::Prob(Double_t(chi2),ndf);
154 //      prob1->Fill(prob);
155 //      chi2_1->Fill(chi2);
156         oldchi2=chi2;
157         if (fDebugLevel)
158             fprintf(stderr," chi2 %f ",chi2);
159
160         c->SetX(0, fXFit[0]);
161         c->SetY(0, fYFit[0]);
162
163         c->SetX(1,fXFit[0]);
164         c->SetY(1,fYFit[0]);
165         c->SetChi2(0,chi2);
166         c->SetChi2(1,chi2);
167         // Force on anod
168         c->SetX(0, fSeg[0]->GetAnod(c->GetX(0)));
169         c->SetX(1, fSeg[1]->GetAnod(c->GetX(1)));
170         
171 // If reasonable chi^2 add result to the list of rawclusters
172         if (chi2 < 0.3) {
173             AddRawCluster(*c);
174 // If not try combined double Mathieson Fit
175         } else {
176           if (fDebugLevel)
177             fprintf(stderr," MAUVAIS CHI2 !!!\n");
178             if (fNLocal[0]==1 &&  fNLocal[1]==1) {
179                 fXInit[0]=fX[fIndLocal[0][1]][1];
180                 fYInit[0]=fY[fIndLocal[0][0]][0];
181                 fXInit[1]=fX[fIndLocal[0][1]][1];
182                 fYInit[1]=fY[fIndLocal[0][0]][0];
183             } else if (fNLocal[0]==1) {
184                 fXInit[0]=fX[fIndLocal[0][0]][0];
185                 fYInit[0]=fY[fIndLocal[0][0]][0];
186                 fXInit[1]=fX[fIndLocal[0][0]][0];
187                 fYInit[1]=fY[fIndLocal[0][0]][0];
188             } else {
189                 fXInit[0]=fX[fIndLocal[0][1]][1];
190                 fYInit[0]=fY[fIndLocal[0][1]][1];
191                 fXInit[1]=fX[fIndLocal[0][1]][1];
192                 fYInit[1]=fY[fIndLocal[0][1]][1];
193             }
194             
195 //  Initial value for charge ratios
196             fQrInit[0]=0.5;
197             fQrInit[1]=0.5;
198             if (fDebugLevel)
199             fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
200             chi2=CombiDoubleMathiesonFit(c);
201 //          Int_t ndf = fgNbins[0]+fgNbins[1]-6;
202 //          Float_t prob = TMath::Prob(chi2,ndf);
203 //          prob2->Fill(prob);
204 //          chi2_2->Fill(chi2);
205             
206 // Was this any better ??
207             if (fDebugLevel)
208               fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
209             if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
210               if (fDebugLevel)
211                 fprintf(stderr," Split\n");
212                 // Split cluster into two according to fit result
213                 Split(c);
214             } else {
215               if (fDebugLevel)
216                 fprintf(stderr," Don't Split\n");
217                 // Don't split
218                 AddRawCluster(*c);
219             }
220         }
221
222 //  +++++++++++++++++++++++++++++++++++++++
223 //  (2) Two local maxima per cathode plane 
224 //  +++++++++++++++++++++++++++++++++++++++
225     } else if (fNLocal[0]==2 &&  fNLocal[1]==2) {
226 //
227 //  Let's look for ghosts first 
228
229         Float_t xm[4][2], ym[4][2];
230         Float_t dpx, dpy, dx, dy;
231         Int_t ixm[4][2], iym[4][2];
232         Int_t isec, im1, im2, ico;
233 //
234 //  Form the 2x2 combinations
235 //  0-0, 0-1, 1-0, 1-1  
236         ico=0;
237         for (im1=0; im1<2; im1++) {
238             for (im2=0; im2<2; im2++) {     
239                 xm[ico][0]=fX[fIndLocal[im1][0]][0];
240                 ym[ico][0]=fY[fIndLocal[im1][0]][0];
241                 xm[ico][1]=fX[fIndLocal[im2][1]][1];
242                 ym[ico][1]=fY[fIndLocal[im2][1]][1];
243
244                 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
245                 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
246                 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
247                 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
248                 ico++;
249             }
250         }
251 // ico = 0 : first local maximum on cathodes 1 and 2
252 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
253 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
254 // ico = 3 : second local maximum on cathodes 1 and 2
255
256 // Analyse the combinations and keep those that are possible !
257 // For each combination check consistency in x and y    
258         Int_t   iacc;
259         Bool_t  accepted[4];
260         Float_t dr[4] = {1.e4, 1.e4, 1.e4, 1.e4};
261         iacc=0;
262
263 // In case of staggering maxima are displaced by exactly half the pad-size in y. 
264 // We have to take into account the numerical precision in the consistency check;       
265         Float_t eps = 1.e-5;
266 //
267         for (ico=0; ico<4; ico++) {
268             accepted[ico]=kFALSE;
269 // cathode one: x-coordinate
270             isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
271             dpx=fSeg[0]->Dpx(isec)/2.;
272             dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
273 // cathode two: y-coordinate
274             isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
275             dpy=fSeg[1]->Dpy(isec)/2.;
276             dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
277             if (fDebugLevel>1) 
278                 printf("\n %i %f %f %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy, dx, dpx );
279             if ((dx <= dpx) && (dy <= dpy+eps)) {
280                 // consistent
281                 accepted[ico]=kTRUE;
282                 dr[ico] = TMath::Sqrt(dx*dx+dy*dy);
283                 iacc++;
284             } else {
285                 // reject
286                 accepted[ico]=kFALSE;
287             }
288         }
289         if (fDebugLevel)
290           printf("\n iacc= %d:\n", iacc);
291         if (iacc == 3) {
292             if (accepted[0] && accepted[1]) {
293                 if (dr[0] >= dr[1]) {
294                     accepted[0]=kFALSE;
295                 } else {
296                     accepted[1]=kFALSE;
297                 }
298             }
299
300             if (accepted[2] && accepted[3]) {
301                 if (dr[2] >= dr[3]) {
302                     accepted[2]=kFALSE;
303                 } else {
304                     accepted[3]=kFALSE;
305                 }
306             }
307 /*          
308 // eliminate one candidate
309             Float_t drmax = 0;
310             Int_t icobad = -1;
311
312             for (ico=0; ico<4; ico++) {
313                 if (accepted[ico] && dr[ico] > drmax) {
314                     icobad = ico;
315                     drmax  = dr[ico];
316                 }
317             }
318             
319             accepted[icobad] = kFALSE;
320 */
321             iacc = 2;
322         }
323         
324         
325         if (fDebugLevel) {
326           printf("\n iacc= %d:\n", iacc);
327             if (iacc==2) {
328                 fprintf(stderr,"\n iacc=2: No problem ! \n");
329             } else if (iacc==4) {
330                 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
331             } else if (iacc==0) {
332                 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
333             }
334         }
335
336 //  Initial value for charge ratios
337         fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
338             Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
339         fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
340             Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
341         
342 // ******* iacc = 0 *******
343 // No combinations found between the 2 cathodes
344 // We keep the center of gravity of the cluster
345         if (iacc==0) {
346             AddRawCluster(*c);
347         }
348
349 // ******* iacc = 1 *******
350 // Only one combination found between the 2 cathodes
351         if (iacc==1) {
352 // Initial values for the 2 maxima (x,y)
353
354 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
355 // 1 maximum is initialised with the other maximum of the first cathode  
356             if (accepted[0]){
357                 if (fDebugLevel) fprintf(stderr,"ico=0\n");
358                 fXInit[0]=xm[0][1];
359                 fYInit[0]=ym[0][0];
360                 fXInit[1]=xm[3][0];
361                 fYInit[1]=ym[3][0];
362             } else if (accepted[1]){
363                 if (fDebugLevel) fprintf(stderr,"ico=1\n");
364                 fXInit[0]=xm[1][1];
365                 fYInit[0]=ym[1][0];
366                 fXInit[1]=xm[2][0];
367                 fYInit[1]=ym[2][0];
368             } else if (accepted[2]){
369                 if (fDebugLevel) fprintf(stderr,"ico=2\n");
370                 fXInit[0]=xm[2][1];
371                 fYInit[0]=ym[2][0];
372                 fXInit[1]=xm[1][0];
373                 fYInit[1]=ym[1][0];
374             } else if (accepted[3]){
375                 if (fDebugLevel) fprintf(stderr,"ico=3\n");
376                 fXInit[0]=xm[3][1];
377                 fYInit[0]=ym[3][0];
378                 fXInit[1]=xm[0][0];
379                 fYInit[1]=ym[0][0];
380             }
381             if (fDebugLevel)
382                 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
383             chi2=CombiDoubleMathiesonFit(c);
384 //          Int_t ndf = fgNbins[0]+fgNbins[1]-6;
385 //          Float_t prob = TMath::Prob(chi2,ndf);
386 //          prob2->Fill(prob);
387 //          chi2_2->Fill(chi2);
388             if (fDebugLevel)
389                 fprintf(stderr," chi2 %f\n",chi2);
390
391 // If reasonable chi^2 add result to the list of rawclusters
392             if (chi2<10) {
393                 Split(c);
394
395             } else {
396 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
397 // 1 maximum is initialised with the other maximum of the second cathode  
398                 if (accepted[0]){
399                     if (fDebugLevel) fprintf(stderr,"ico=0\n");
400                     fXInit[0]=xm[0][1];
401                     fYInit[0]=ym[0][0];
402                     fXInit[1]=xm[3][1];
403                     fYInit[1]=ym[3][1];
404                 } else if (accepted[1]){
405                     if (fDebugLevel) fprintf(stderr,"ico=1\n");
406                     fXInit[0]=xm[1][1];
407                     fYInit[0]=ym[1][0];
408                     fXInit[1]=xm[2][1];
409                     fYInit[1]=ym[2][1];
410                 } else if (accepted[2]){
411                     if (fDebugLevel) fprintf(stderr,"ico=2\n");
412                     fXInit[0]=xm[2][1];
413                     fYInit[0]=ym[2][0];
414                     fXInit[1]=xm[1][1];
415                     fYInit[1]=ym[1][1];
416                 } else if (accepted[3]){
417                     if (fDebugLevel) fprintf(stderr,"ico=3\n");
418                     fXInit[0]=xm[3][1];
419                     fYInit[0]=ym[3][0];
420                     fXInit[1]=xm[0][1];
421                     fYInit[1]=ym[0][1];
422                 }
423                 if (fDebugLevel)
424                     fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
425                 chi2=CombiDoubleMathiesonFit(c);
426 //              Int_t ndf = fgNbins[0]+fgNbins[1]-6;
427 //              Float_t prob = TMath::Prob(chi2,ndf);
428 //              prob2->Fill(prob);
429 //              chi2_2->Fill(chi2);
430                 if (fDebugLevel)
431                     fprintf(stderr," chi2 %f\n",chi2);
432
433 // If reasonable chi^2 add result to the list of rawclusters
434                 if (chi2<10) {
435                     Split(c);
436                 } else {
437 //We keep only the combination found (X->cathode 2, Y->cathode 1)
438                     for (Int_t ico=0; ico<2; ico++) {
439                         if (accepted[ico]) {
440                             AliMUONRawCluster cnew;
441                             Int_t cath;    
442                             for (cath=0; cath<2; cath++) {
443                                 cnew.SetX(cath, Float_t(xm[ico][1]));
444                                 cnew.SetY(cath, Float_t(ym[ico][0]));
445                                 cnew.SetZ(cath, fZPlane);
446                                 
447                                 cnew.SetMultiplicity(cath,c->GetMultiplicity(cath));
448                                 for (i=0; i<fMul[cath]; i++) {
449                                     cnew.SetIndex(i, cath, c->GetIndex(i,cath));
450                                     fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
451                                 }
452                                 if (fDebugLevel) {
453                                   fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
454                                   fprintf(stderr,"mult_av %d\n",c->GetMultiplicity(cath));
455                                 }
456                                 FillCluster(&cnew,cath);
457                             } 
458                             cnew.SetClusterType(cnew.PhysicsContribution());
459                             AddRawCluster(cnew);
460                             fNPeaks++;
461                         }
462                     }
463                 }
464             }
465         }
466         
467 // ******* iacc = 2 *******
468 // Two combinations found between the 2 cathodes
469         if (iacc==2) {
470 // Was the same maximum taken twice
471             if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
472                 if (fDebugLevel) fprintf(stderr,"\n Maximum taken twice !!!\n");
473
474 // Have a try !! with that
475                 if (accepted[0]&&accepted[3]) {
476                     fXInit[0]=xm[0][1];
477                     fYInit[0]=ym[0][0];
478                     fXInit[1]=xm[1][1];
479                     fYInit[1]=ym[1][0];
480                 } else {
481                     fXInit[0]=xm[2][1];
482                     fYInit[0]=ym[2][0];
483                     fXInit[1]=xm[3][1];
484                     fYInit[1]=ym[3][0];
485                 }
486                 if (fDebugLevel)
487                     fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
488                 chi2=CombiDoubleMathiesonFit(c);
489 //                  Int_t ndf = fgNbins[0]+fgNbins[1]-6;
490 //                  Float_t prob = TMath::Prob(chi2,ndf);
491 //                  prob2->Fill(prob);
492 //                  chi2_2->Fill(chi2);
493                 Split(c);
494                 
495             } else {
496 // No ghosts ! No Problems ! -  Perform one fit only !
497                 if (accepted[0]&&accepted[3]) {
498                     fXInit[0]=xm[0][1];
499                     fYInit[0]=ym[0][0];
500                     fXInit[1]=xm[3][1];
501                     fYInit[1]=ym[3][0];
502                 } else {
503                     fXInit[0]=xm[1][1];
504                     fYInit[0]=ym[1][0];
505                     fXInit[1]=xm[2][1];
506                     fYInit[1]=ym[2][0];
507                 }
508                 if (fDebugLevel)
509                     fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
510                 chi2=CombiDoubleMathiesonFit(c);
511 //                  Int_t ndf = fgNbins[0]+fgNbins[1]-6;
512 //                  Float_t prob = TMath::Prob(chi2,ndf);
513 //                  prob2->Fill(prob);
514 //                  chi2_2->Fill(chi2);
515                 if (fDebugLevel)
516                     fprintf(stderr," chi2 %f\n",chi2);
517                 Split(c);
518             }
519             
520 // ******* iacc = 4 *******
521 // Four combinations found between the 2 cathodes
522 // Ghost !!
523         } else if (iacc==4) {
524 // Perform fits for the two possibilities !!    
525 // Accept if charges are compatible on both cathodes
526 // If none are compatible, keep everything
527             fXInit[0]=xm[0][1];
528             fYInit[0]=ym[0][0];
529             fXInit[1]=xm[3][1];
530             fYInit[1]=ym[3][0];
531             if (fDebugLevel)
532                 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
533             chi2=CombiDoubleMathiesonFit(c);
534 //              Int_t ndf = fgNbins[0]+fgNbins[1]-6;
535 //              Float_t prob = TMath::Prob(chi2,ndf);
536 //              prob2->Fill(prob);
537 //              chi2_2->Fill(chi2);
538             if (fDebugLevel)
539                 fprintf(stderr," chi2 %f\n",chi2);
540             // store results of fit and postpone decision
541             Double_t sXFit[2],sYFit[2],sQrFit[2];
542             Float_t sChi2[2];
543             for (Int_t i=0;i<2;i++) {
544                 sXFit[i]=fXFit[i];
545                 sYFit[i]=fYFit[i];
546                 sQrFit[i]=fQrFit[i];
547                 sChi2[i]=fChi2[i];
548             }
549             fXInit[0]=xm[1][1];
550             fYInit[0]=ym[1][0];
551             fXInit[1]=xm[2][1];
552             fYInit[1]=ym[2][0];
553             if (fDebugLevel)
554                 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
555             chi2=CombiDoubleMathiesonFit(c);
556 //              ndf = fgNbins[0]+fgNbins[1]-6;
557 //              prob = TMath::Prob(chi2,ndf);
558 //              prob2->Fill(prob);
559 //              chi2_2->Fill(chi2);
560             if (fDebugLevel)
561                 fprintf(stderr," chi2 %f\n",chi2);
562             // We have all informations to perform the decision
563             // Compute the chi2 for the 2 possibilities
564             Float_t chi2fi,chi2si,chi2f,chi2s;
565
566             chi2f = (TMath::Log(fInput->TotalCharge(0)*fQrFit[0]
567                   /  (fInput->TotalCharge(1)*fQrFit[1]) )
568                   / fInput->Response()->ChargeCorrel() );
569             chi2f *=chi2f;
570             chi2fi = (TMath::Log(fInput->TotalCharge(0)*(1-fQrFit[0])
571                   /  (fInput->TotalCharge(1)*(1-fQrFit[1])) )
572                   / fInput->Response()->ChargeCorrel() );
573             chi2f += chi2fi*chi2fi;
574
575             chi2s = (TMath::Log(fInput->TotalCharge(0)*sQrFit[0]
576                   /  (fInput->TotalCharge(1)*sQrFit[1]) )
577                   / fInput->Response()->ChargeCorrel() );
578             chi2s *=chi2s;
579             chi2si = (TMath::Log(fInput->TotalCharge(0)*(1-sQrFit[0])
580                   /  (fInput->TotalCharge(1)*(1-sQrFit[1])) )
581                   / fInput->Response()->ChargeCorrel() );
582             chi2s += chi2si*chi2si;
583
584             // usefull to store the charge matching chi2 in the cluster
585             // fChi2[0]=sChi2[1]=chi2f;
586             // fChi2[1]=sChi2[0]=chi2s;
587
588             if (chi2f<=fGhostChi2Cut && chi2s<=fGhostChi2Cut)
589                 c->SetGhost(1);
590             if   (chi2f>fGhostChi2Cut && chi2s>fGhostChi2Cut) {
591                 // we keep the ghost
592                 c->SetGhost(2);
593                 chi2s=-1;
594                 chi2f=-1;
595             }
596             if (chi2f<=fGhostChi2Cut)
597                 Split(c);
598             if (chi2s<=fGhostChi2Cut) {
599                 // retreive saved values
600                 for (Int_t i=0;i<2;i++) {
601                     fXFit[i]=sXFit[i];
602                     fYFit[i]=sYFit[i];
603                     fQrFit[i]=sQrFit[i];
604                     fChi2[i]=sChi2[i];
605                 }
606                 Split(c);
607             }
608             c->SetGhost(0);
609         }
610
611     } else if (fNLocal[0]==2 &&  fNLocal[1]==1) {
612 //  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
613 //  (3) Two local maxima on cathode 1 and one maximum on cathode 2 
614 //  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
615 //
616         Float_t xm[4][2], ym[4][2];
617         Float_t dpx, dpy, dx, dy;
618         Int_t ixm[4][2], iym[4][2];
619         Int_t isec, im1, ico;
620 //
621 //  Form the 2x2 combinations
622 //  0-0, 0-1, 1-0, 1-1  
623         ico=0;
624         for (im1=0; im1<2; im1++) {
625             xm[ico][0]=fX[fIndLocal[im1][0]][0];
626             ym[ico][0]=fY[fIndLocal[im1][0]][0];
627             xm[ico][1]=fX[fIndLocal[0][1]][1];
628             ym[ico][1]=fY[fIndLocal[0][1]][1];
629             
630             ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
631             iym[ico][0]=fIy[fIndLocal[im1][0]][0];
632             ixm[ico][1]=fIx[fIndLocal[0][1]][1];
633             iym[ico][1]=fIy[fIndLocal[0][1]][1];
634             ico++;
635         }
636 // ico = 0 : first local maximum on cathodes 1 and 2
637 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
638
639 // Analyse the combinations and keep those that are possible !
640 // For each combination check consistency in x and y    
641         Int_t iacc;
642         Bool_t accepted[4];
643         iacc=0;
644         // In case of staggering maxima are displaced by exactly half the pad-size in y. 
645         // We have to take into account the numerical precision in the consistency check;
646         
647         Float_t eps = 1.e-5;
648
649         for (ico=0; ico<2; ico++) {
650             accepted[ico]=kFALSE;
651             isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
652             dpx=fSeg[0]->Dpx(isec)/2.;
653             dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
654             isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
655             dpy=fSeg[1]->Dpy(isec)/2.;
656             dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
657             if (fDebugLevel>1)
658                 printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
659             if ((dx <= dpx) && (dy <= dpy+eps)) {
660                 // consistent
661                 accepted[ico]=kTRUE;
662                 iacc++;
663             } else {
664                 // reject
665                 accepted[ico]=kFALSE;
666             }
667         }
668         
669         Float_t chi21 = 100;
670         Float_t chi22 = 100;
671         Float_t chi23 = 100;
672
673         //  Initial value for charge ratios
674         fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
675             Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
676         fQrInit[1]=fQrInit[0];
677         
678         if (accepted[0] && accepted[1]) {
679             
680             fXInit[0]=0.5*(xm[0][1]+xm[0][0]);
681             fYInit[0]=ym[0][0];
682             fXInit[1]=0.5*(xm[0][1]+xm[1][0]);
683             fYInit[1]=ym[1][0];
684             fQrInit[0]=0.5;
685             fQrInit[1]=0.5;
686             chi23=CombiDoubleMathiesonFit(c);
687             if (chi23<10) {
688                 Split(c);
689                 Float_t yst;
690                 yst = fYFit[0];
691                 fYFit[0] = fYFit[1];
692                 fYFit[1] = yst;
693                 Split(c);
694             }
695         } else if (accepted[0]) {
696             fXInit[0]=xm[0][1];
697             fYInit[0]=ym[0][0];
698             fXInit[1]=xm[1][0];
699             fYInit[1]=ym[1][0];
700             chi21=CombiDoubleMathiesonFit(c);
701 //          Int_t ndf = fgNbins[0]+fgNbins[1]-6;
702 //          Float_t prob = TMath::Prob(chi2,ndf);
703 //          prob2->Fill(prob);
704 //          chi2_2->Fill(chi21);
705             if (fDebugLevel)
706                 fprintf(stderr," chi2 %f\n",chi21);
707             if (chi21<10) Split(c);
708         } else if (accepted[1]) {
709             fXInit[0]=xm[1][1];
710             fYInit[0]=ym[1][0];
711             fXInit[1]=xm[0][0];
712             fYInit[1]=ym[0][0];
713             chi22=CombiDoubleMathiesonFit(c);
714 //          Int_t ndf = fgNbins[0]+fgNbins[1]-6;
715 //          Float_t prob = TMath::Prob(chi2,ndf);
716 //          prob2->Fill(prob);
717 //          chi2_2->Fill(chi22);
718             if (fDebugLevel)
719                 fprintf(stderr," chi2 %f\n",chi22);
720             if (chi22<10) Split(c);
721         }
722
723         if (chi21 > 10 && chi22 > 10 && chi23 > 10) {
724 // We keep only the combination found (X->cathode 2, Y->cathode 1)
725             for (Int_t ico=0; ico<2; ico++) {
726                 if (accepted[ico]) {
727                     AliMUONRawCluster cnew;
728                     Int_t cath;    
729                     for (cath=0; cath<2; cath++) {
730                         cnew.SetX(cath, Float_t(xm[ico][1]));
731                         cnew.SetY(cath, Float_t(ym[ico][0]));
732                         cnew.SetZ(cath, fZPlane);
733                         cnew.SetMultiplicity(cath, c->GetMultiplicity(cath));
734                         for (i=0; i<fMul[cath]; i++) {
735                             cnew.SetIndex(i, cath, c->GetIndex(i, cath));
736                             fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
737                         }
738                         if (fDebugLevel){
739                           fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
740                           fprintf(stderr,"mult_av %d\n",c->GetMultiplicity(cath));
741                         }
742                         FillCluster(&cnew,cath);
743                     } 
744                     cnew.SetClusterType(cnew.PhysicsContribution());
745                     AddRawCluster(cnew);
746                     fNPeaks++;
747                 }
748             }
749         }
750         
751 //  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
752 //  (3') One local maximum on cathode 1 and two maxima on cathode 2 
753 //  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
754     } else if (fNLocal[0]==1 && fNLocal[1]==2) {
755         Float_t xm[4][2], ym[4][2];
756         Float_t dpx, dpy, dx, dy;
757         Int_t ixm[4][2], iym[4][2];
758         Int_t isec, im1, ico;
759 //
760 //  Form the 2x2 combinations
761 //  0-0, 0-1, 1-0, 1-1  
762         ico=0;
763         for (im1=0; im1<2; im1++) {
764             xm[ico][0]=fX[fIndLocal[0][0]][0];
765             ym[ico][0]=fY[fIndLocal[0][0]][0];
766             xm[ico][1]=fX[fIndLocal[im1][1]][1];
767             ym[ico][1]=fY[fIndLocal[im1][1]][1];
768             
769             ixm[ico][0]=fIx[fIndLocal[0][0]][0];
770             iym[ico][0]=fIy[fIndLocal[0][0]][0];
771             ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
772             iym[ico][1]=fIy[fIndLocal[im1][1]][1];
773             ico++;
774         }
775 // ico = 0 : first local maximum on cathodes 1 and 2
776 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
777
778 // Analyse the combinations and keep those that are possible !
779 // For each combination check consistency in x and y    
780         Int_t iacc;
781         Bool_t accepted[4];
782         iacc=0;
783         // In case of staggering maxima are displaced by exactly half the pad-size in y. 
784         // We have to take into account the numerical precision in the consistency check;       
785         Float_t eps = 1.e-5;
786
787         
788         for (ico=0; ico<2; ico++) {
789             accepted[ico]=kFALSE;
790             isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
791             dpx=fSeg[0]->Dpx(isec)/2.;
792             dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
793             isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
794             dpy=fSeg[1]->Dpy(isec)/2.;
795             dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
796             if (fDebugLevel>0)
797                 printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
798             if ((dx <= dpx) && (dy <= dpy+eps)) {
799                 // consistent
800                 accepted[ico]=kTRUE;
801                 if (fDebugLevel) fprintf(stderr,"ico %d\n",ico);
802                 iacc++;
803             } else {
804                 // reject
805                 accepted[ico]=kFALSE;
806             }
807         }
808
809         Float_t chi21 = 100;
810         Float_t chi22 = 100;
811         Float_t chi23 = 100;
812
813         fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
814             Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
815         
816         fQrInit[0]=fQrInit[1];
817
818         
819         if (accepted[0] && accepted[1]) {
820             fXInit[0]=xm[0][1];
821             fYInit[0]=0.5*(ym[0][0]+ym[0][1]);
822             fXInit[1]=xm[1][1];
823             fYInit[1]=0.5*(ym[0][0]+ym[1][1]);
824             fQrInit[0]=0.5;
825             fQrInit[1]=0.5;
826             chi23=CombiDoubleMathiesonFit(c);
827             if (chi23<10) {
828                 Split(c);
829                 Float_t yst;
830                 yst = fYFit[0];
831                 fYFit[0] = fYFit[1];
832                 fYFit[1] = yst;
833                 Split(c);
834             }
835         } else if (accepted[0]) {
836             fXInit[0]=xm[0][0];
837             fYInit[0]=ym[0][1];
838             fXInit[1]=xm[1][1];
839             fYInit[1]=ym[1][1];
840             chi21=CombiDoubleMathiesonFit(c);
841 //          Int_t ndf = fgNbins[0]+fgNbins[1]-6;
842 //          Float_t prob = TMath::Prob(chi2,ndf);
843 //          prob2->Fill(prob);
844 //          chi2_2->Fill(chi21);
845             if (fDebugLevel)
846                 fprintf(stderr," chi2 %f\n",chi21);
847             if (chi21<10) Split(c);
848         } else if (accepted[1]) {
849             fXInit[0]=xm[1][0];
850             fYInit[0]=ym[1][1];
851             fXInit[1]=xm[0][1];
852             fYInit[1]=ym[0][1];
853             chi22=CombiDoubleMathiesonFit(c);
854 //          Int_t ndf = fgNbins[0]+fgNbins[1]-6;
855 //          Float_t prob = TMath::Prob(chi2,ndf);
856 //          prob2->Fill(prob);
857 //          chi2_2->Fill(chi22);
858             if (fDebugLevel)
859                 fprintf(stderr," chi2 %f\n",chi22);
860             if (chi22<10) Split(c);
861         }
862
863         if (chi21 > 10 && chi22 > 10 && chi23 > 10) {
864 //We keep only the combination found (X->cathode 2, Y->cathode 1)
865             for (Int_t ico=0; ico<2; ico++) {
866                 if (accepted[ico]) {
867                     AliMUONRawCluster cnew;
868                     Int_t cath;    
869                     for (cath=0; cath<2; cath++) {
870                         cnew.SetX(cath, Float_t(xm[ico][1]));
871                         cnew.SetY(cath, Float_t(ym[ico][0]));
872                         cnew.SetZ(cath, fZPlane);
873                         cnew.SetMultiplicity(cath, c->GetMultiplicity(cath));
874                         for (i=0; i<fMul[cath]; i++) {
875                             cnew.SetIndex(i, cath, c->GetIndex(i, cath));
876                             fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
877                         }
878                         if (fDebugLevel) {
879                           fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
880                           fprintf(stderr,"mult_av %d\n",c->GetMultiplicity(cath));
881                         }
882                         FillCluster(&cnew,cath);
883                     } 
884                     cnew.SetClusterType(cnew.PhysicsContribution());
885                     AddRawCluster(cnew);
886                     fNPeaks++;
887                 }
888             }
889         }
890
891 //  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
892 //  (4) At least three local maxima on cathode 1 or on cathode 2 
893 //  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
894     } else if (fNLocal[0]>2 || fNLocal[1]>2) {
895         Int_t param = fNLocal[0]*fNLocal[1];
896         Int_t ii;
897
898         Float_t ** xm = new Float_t * [param];
899         for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
900         Float_t ** ym = new Float_t * [param];
901         for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
902         Int_t ** ixm = new Int_t * [param];
903         for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
904         Int_t ** iym = new Int_t * [param];
905         for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
906         
907         Int_t isec, ico;
908         Float_t dpx, dpy, dx, dy;
909
910         ico=0;
911         for (Int_t im1=0; im1<fNLocal[0]; im1++) {
912             for (Int_t im2=0; im2<fNLocal[1]; im2++) {
913                 xm[ico][0]=fX[fIndLocal[im1][0]][0];
914                 ym[ico][0]=fY[fIndLocal[im1][0]][0];
915                 xm[ico][1]=fX[fIndLocal[im2][1]][1];
916                 ym[ico][1]=fY[fIndLocal[im2][1]][1];
917
918                 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
919                 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
920                 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
921                 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
922                 ico++;
923             }
924         }
925         
926         Int_t nIco = ico;
927         if (fDebugLevel)
928             fprintf(stderr,"nIco %d\n",nIco);
929         for (ico=0; ico<nIco; ico++) {
930             if (fDebugLevel)
931                 fprintf(stderr,"ico = %d\n",ico);
932             isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
933             dpx=fSeg[0]->Dpx(isec)/2.;
934             dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
935             isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
936             dpy=fSeg[1]->Dpy(isec)/2.;
937             dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
938             if (fDebugLevel) {
939                 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
940                 fprintf(stderr,"  X %f Y %f\n",xm[ico][1],ym[ico][0]);
941             }
942             if ((dx <= dpx) && (dy <= dpy)) {
943                 if (fDebugLevel)
944                     fprintf(stderr,"ok\n");
945                 Int_t cath;    
946                 AliMUONRawCluster cnew;
947                 for (cath=0; cath<2; cath++) {
948                     cnew.SetX(cath, Float_t(xm[ico][1]));
949                     cnew.SetY(cath, Float_t(ym[ico][0]));
950                     cnew.SetZ(cath, fZPlane);
951                     cnew.SetMultiplicity(cath, c->GetMultiplicity(cath));
952                     for (i=0; i<fMul[cath]; i++) {
953                         cnew.SetIndex(i, cath, c->GetIndex(i, cath));
954                         fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
955                     }
956                     FillCluster(&cnew,cath);
957                 } 
958                 cnew.SetClusterType(cnew.PhysicsContribution());
959                 AddRawCluster(cnew);
960                 fNPeaks++;
961             }
962         }
963         delete [] xm;
964         delete [] ym;
965         delete [] ixm;
966         delete [] iym;
967     }
968 }
969
970 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* /*c*/)
971 {
972 // Find all local maxima of a cluster
973     if (fDebugLevel)
974         printf("\n Find Local maxima  !");
975     
976     AliMUONDigit* digt;
977     
978     Int_t cath, cath1; // loops over cathodes
979     Int_t i;           // loops over digits
980     Int_t j;           // loops over cathodes
981 //
982 //  Find local maxima
983 //
984 //  counters for number of local maxima
985     fNLocal[0]=fNLocal[1]=0;
986 //  flags digits as local maximum
987     Bool_t isLocal[100][2];
988     for (i=0; i<100;i++) {
989         isLocal[i][0]=isLocal[i][1]=kFALSE;
990     }
991 //  number of next neighbours and arrays to store them 
992     Int_t nn;
993     Int_t x[10], y[10];
994 // loop over cathodes
995     for (cath=0; cath<2; cath++) {
996 // loop over cluster digits
997         for (i=0; i<fMul[cath]; i++) {
998 // get neighbours for that digit and assume that it is local maximum        
999             fSeg[cath]->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
1000             isLocal[i][cath]=kTRUE;
1001             Int_t isec= fSeg[cath]->Sector(fIx[i][cath], fIy[i][cath]);
1002             Float_t a0 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
1003 // loop over next neighbours, if at least one neighbour has higher charger assumption
1004 // digit is not local maximum 
1005             for (j=0; j<nn; j++) {
1006                 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
1007                 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
1008                 isec=fSeg[cath]->Sector(x[j], y[j]);
1009                 Float_t a1 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
1010                 if (digt->Signal()/a1 > fQ[i][cath]/a0) {
1011                     isLocal[i][cath]=kFALSE;
1012                     break;
1013 //
1014 // handle special case of neighbouring pads with equal signal
1015                 } else if (digt->Signal() == fQ[i][cath]) {
1016                     if (fNLocal[cath]>0) {
1017                         for (Int_t k=0; k<fNLocal[cath]; k++) {
1018                             if (x[j]==fIx[fIndLocal[k][cath]][cath] 
1019                                 && y[j]==fIy[fIndLocal[k][cath]][cath])
1020                             {
1021                                 isLocal[i][cath]=kFALSE;
1022                             } 
1023                         } // loop over local maxima
1024                     } // are there already local maxima
1025                 } // same charge ? 
1026             } // loop over next neighbours
1027             if (isLocal[i][cath]) {
1028                 fIndLocal[fNLocal[cath]][cath]=i;
1029                 fNLocal[cath]++;
1030             } 
1031         } // loop over all digits
1032     } // loop over cathodes
1033
1034     if (fDebugLevel) {
1035         printf("\n Found %d %d %d %d local Maxima\n",
1036                fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
1037         fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
1038         fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
1039     }
1040     Int_t ix, iy, isec;
1041     Float_t dpx, dpy;
1042     
1043     
1044     if (fNLocal[1]==2 &&  (fNLocal[0]==1 || fNLocal[0]==0)) {
1045         Int_t iback=fNLocal[0];
1046         
1047 //  Two local maxima on cathode 2 and one maximum on cathode 1 
1048 //  Look for local maxima considering up and down neighbours on the 1st cathode only
1049 //
1050 //  Loop over cluster digits
1051         cath=0;
1052         cath1=1;
1053         
1054         for (i=0; i<fMul[cath]; i++) {
1055             isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
1056             dpy=fSeg[cath]->Dpy(isec);
1057             dpx=fSeg[cath]->Dpx(isec);
1058             if (isLocal[i][cath]) continue;
1059 // Pad position should be consistent with position of local maxima on the opposite cathode
1060             if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) && 
1061                 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
1062                 continue;
1063
1064 // get neighbours for that digit and assume that it is local maximum        
1065             isLocal[i][cath]=kTRUE;
1066 // compare signal to that on the two neighbours on the left and on the right
1067 // iNN counts the number of neighbours with signal, it should be 1 or 2
1068             Int_t iNN=0;
1069
1070             for (fSeg[cath]
1071                      ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpy);
1072                  fSeg[cath]
1073                      ->MorePads();
1074                  fSeg[cath]
1075                      ->NextPad())
1076             {
1077                 ix = fSeg[cath]->Ix();
1078                 iy = fSeg[cath]->Iy();
1079                 // skip the current pad
1080                 if (iy == fIy[i][cath]) continue;
1081                 
1082                 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
1083                     iNN++;
1084                     digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
1085                     if (digt->Signal() > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1086                 }
1087             } // Loop over pad neighbours in y
1088             if (isLocal[i][cath] && iNN>0) {
1089                 fIndLocal[fNLocal[cath]][cath]=i;
1090                 fNLocal[cath]++;
1091             } 
1092         } // loop over all digits
1093 // if one additional maximum has been found we are happy 
1094 // if more maxima have been found restore the previous situation
1095         if (fDebugLevel) {
1096             fprintf(stderr,
1097                     "\n New search gives %d local maxima for cathode 1 \n",
1098                     fNLocal[0]);
1099             fprintf(stderr,
1100                     "                  %d local maxima for cathode 2 \n",
1101                     fNLocal[1]);
1102         }
1103         if (fNLocal[cath]>2) {
1104             fNLocal[cath]=iback;
1105         }
1106         
1107     } // 1,2 local maxima
1108     
1109     if (fNLocal[0]==2 &&  (fNLocal[1]==1 || fNLocal[1]==0)) {
1110         Int_t iback=fNLocal[1];
1111         
1112 //  Two local maxima on cathode 1 and one maximum on cathode 2 
1113 //  Look for local maxima considering left and right neighbours on the 2nd cathode only
1114         cath=1;
1115         Int_t cath1 = 0;
1116         Float_t eps = 1.e-5;
1117         
1118 //
1119 //  Loop over cluster digits
1120         for (i=0; i<fMul[cath]; i++) {
1121             isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
1122             dpx=fSeg[cath]->Dpx(isec);
1123             dpy=fSeg[cath]->Dpy(isec);
1124             if (isLocal[i][cath]) continue;
1125 // Pad position should be consistent with position of local maxima on the opposite cathode
1126             if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.+eps) && 
1127                 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.+eps))
1128                 continue;
1129             
1130 //
1131 // get neighbours for that digit and assume that it is local maximum        
1132             isLocal[i][cath]=kTRUE;
1133 // compare signal to that on the two neighbours on the left and on the right
1134
1135 // iNN counts the number of neighbours with signal, it should be 1 or 2
1136             Int_t iNN=0;
1137             for (fSeg[cath]
1138                      ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, dpx, 0.);
1139                  fSeg[cath]
1140                      ->MorePads();
1141                  fSeg[cath]
1142                      ->NextPad())
1143             {
1144
1145                 ix = fSeg[cath]->Ix();
1146                 iy = fSeg[cath]->Iy();
1147
1148                 // skip the current pad
1149                 if (ix == fIx[i][cath]) continue;
1150                 
1151                 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
1152                     iNN++;
1153                     digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
1154                     if (digt->Signal() > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1155                 }
1156             } // Loop over pad neighbours in x
1157             if (isLocal[i][cath] && iNN>0) {
1158                 fIndLocal[fNLocal[cath]][cath]=i;
1159                 fNLocal[cath]++;
1160             } 
1161         } // loop over all digits
1162 // if one additional maximum has been found we are happy 
1163 // if more maxima have been found restore the previous situation
1164         if (fDebugLevel) {
1165             fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
1166             fprintf(stderr,"\n                  %d local maxima for cathode 2 \n",fNLocal[1]);
1167             printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
1168         }
1169         if (fNLocal[cath]>2) {
1170             fNLocal[cath]=iback;
1171         }
1172     } // 2,1 local maxima
1173 }
1174
1175
1176 void  AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath) 
1177 {
1178 //
1179 //  Completes cluster information starting from list of digits
1180 //
1181     AliMUONDigit* dig;
1182     Float_t x, y, z;
1183     Int_t  ix, iy;
1184     
1185     if (cath==1) {
1186         c->SetPeakSignal(cath,c->GetPeakSignal(0));     
1187     } else {
1188         c->SetPeakSignal(cath,0);
1189     }
1190     
1191     
1192     if (flag) {
1193         c->SetX(cath,0.);
1194         c->SetY(cath,0.);
1195         c->SetCharge(cath,0);
1196     }
1197
1198     if (fDebugLevel)
1199         fprintf(stderr,"\n fPeakSignal %d\n",c->GetPeakSignal(cath));
1200     for (Int_t i=0; i<c->GetMultiplicity(cath); i++)
1201     {
1202         dig= fInput->Digit(cath,c->GetIndex(i,cath));
1203         ix=dig->PadX()+c->GetOffset(i,cath);
1204         iy=dig->PadY();
1205         Int_t q=dig->Signal();
1206         if (!flag) q=Int_t(q*c->GetContrib(i,cath));
1207 //      fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1208         if (dig->Physics() >= dig->Signal()) {
1209             c->SetPhysics(i,2);
1210         } else if (dig->Physics() == 0) {
1211             c->SetPhysics(i,0);
1212         } else  c->SetPhysics(i,1);
1213 //
1214 // 
1215         if (fDebugLevel>1)
1216             fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->GetPeakSignal(cath));
1217 // peak signal and track list
1218         if (q>c->GetPeakSignal(cath)) {
1219             c->SetPeakSignal(cath, q);
1220             c->SetTrack(0,dig->Hit());
1221             c->SetTrack(1,dig->Track(0));
1222             c->SetTrack(2,dig->Track(1));
1223 //          fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1224         }
1225 //
1226         if (flag) {
1227             fSeg[cath]->GetPadC(ix, iy, x, y, z);
1228             c->AddX(cath, q*x);
1229             c->AddY(cath, q*y);
1230             c->AddCharge(cath, q);
1231         }
1232     } // loop over digits
1233     if (fDebugLevel)
1234         fprintf(stderr," fin du cluster c\n");
1235
1236
1237     if (flag) {
1238         c->SetX(cath, c->GetX(cath)/c->GetCharge(cath));
1239 // Force on anod
1240         c->SetX(cath, fSeg[cath]->GetAnod(c->GetX(cath)));
1241         c->SetY(cath, c->GetY(cath)/c->GetCharge(cath)); 
1242 //
1243 //  apply correction to the coordinate along the anode wire
1244 //
1245         x=c->GetX(cath);   
1246         y=c->GetY(cath);
1247         fSeg[cath]->GetPadI(x, y, fZPlane, ix, iy);
1248         fSeg[cath]->GetPadC(ix, iy, x, y, z);
1249         Int_t isec=fSeg[cath]->Sector(ix,iy);
1250         TF1* cogCorr = fSeg[cath]->CorrFunc(isec-1);
1251         
1252         if (cogCorr) {
1253             Float_t yOnPad=(c->GetY(cath)-y)/fSeg[cath]->Dpy(isec);
1254             c->SetY(cath, c->GetY(cath)-cogCorr->Eval(yOnPad, 0, 0));
1255         }
1256     }
1257 }
1258
1259 void  AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath) 
1260 {
1261 //
1262 //  Completes cluster information starting from list of digits
1263 //
1264     static Float_t dr0;
1265
1266     AliMUONDigit* dig;
1267
1268     if (cath==0) {
1269         dr0 = 10000;
1270     }
1271     
1272     Float_t xpad, ypad, zpad;
1273     Float_t dx, dy, dr;
1274
1275     for (Int_t i=0; i<c->GetMultiplicity(cath); i++)
1276     {
1277         dig = fInput->Digit(cath,c->GetIndex(i,cath));
1278         fSeg[cath]->
1279         GetPadC(dig->PadX(),dig->PadY(),xpad,ypad, zpad);
1280         if (fDebugLevel)
1281             fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->GetX(0),c->GetY(0));
1282         dx = xpad - c->GetX(0);
1283         dy = ypad - c->GetY(0);
1284         dr = TMath::Sqrt(dx*dx+dy*dy);
1285
1286         if (dr < dr0) {
1287             dr0 = dr;
1288             if (fDebugLevel)
1289                 fprintf(stderr," dr %f\n",dr);
1290             Int_t q=dig->Signal();
1291             if (dig->Physics() >= dig->Signal()) {
1292                 c->SetPhysics(i,2);
1293             } else if (dig->Physics() == 0) {
1294                 c->SetPhysics(i,0);
1295             } else  c->SetPhysics(i,1);
1296             c->SetPeakSignal(cath,q);
1297             c->SetTrack(0,dig->Hit());
1298             c->SetTrack(1,dig->Track(0));
1299             c->SetTrack(2,dig->Track(1));
1300             if (fDebugLevel)
1301                 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->Hit(),
1302                     dig->Track(0));
1303         }
1304 //
1305     } // loop over digits
1306
1307 //  apply correction to the coordinate along the anode wire
1308 // Force on anod
1309     c->SetX(cath,fSeg[cath]->GetAnod(c->GetX(cath)));
1310 }
1311
1312 void  AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1313
1314
1315 //
1316 //  Find a super cluster on both cathodes
1317 //
1318 //
1319 //  Add i,j as element of the cluster
1320 //
1321     
1322     Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1323     AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1324     Int_t q=dig->Signal();
1325     Int_t theX=dig->PadX();
1326     Int_t theY=dig->PadY(); 
1327    
1328     if (q > TMath::Abs(c.GetPeakSignal(0)) && q > TMath::Abs(c.GetPeakSignal(1))) {
1329         c.SetPeakSignal(cath,q);
1330         c.SetTrack(0,dig->Hit());
1331         c.SetTrack(1,dig->Track(0));
1332         c.SetTrack(2,dig->Track(1));
1333     }
1334
1335 //
1336 //  Make sure that list of digits is ordered 
1337 // 
1338     Int_t mu=c.GetMultiplicity(cath);
1339     c.SetIndex(mu, cath, idx);
1340     
1341     if (dig->Physics() >= dig->Signal()) {
1342         c.SetPhysics(mu,2);
1343     } else if (dig->Physics() == 0) {
1344         c.SetPhysics(mu,0);
1345     } else  c.SetPhysics(mu,1);
1346
1347     
1348     if (mu > 0) {
1349         for (Int_t ind = mu-1; ind >= 0; ind--) {
1350             Int_t ist=c.GetIndex(ind,cath);
1351             Int_t ql=fInput->Digit(cath, ist)->Signal();
1352             Int_t ix=fInput->Digit(cath, ist)->PadX();
1353             Int_t iy=fInput->Digit(cath, ist)->PadY();
1354             
1355             if (q>ql || (q==ql && theX > ix && theY < iy)) {
1356                 c.SetIndex(ind, cath, idx);
1357                 c.SetIndex(ind+1, cath, ist);
1358             } else {
1359                 
1360                 break;
1361             }
1362         }
1363     }
1364
1365     c.SetMultiplicity(cath, c.GetMultiplicity(cath)+1);
1366     if (c.GetMultiplicity(cath) >= 50 ) {
1367       if (fDebugLevel)
1368         printf("FindCluster - multiplicity >50  %d \n",c.GetMultiplicity(0));
1369         c.SetMultiplicity(cath, 49);
1370     }
1371
1372 // Prepare center of gravity calculation
1373     Float_t x, y, z;
1374     fSeg[cath]->GetPadC(i, j, x, y, z);
1375     
1376     c.AddX(cath,q*x);
1377     c.AddY(cath,q*y);
1378     c.AddCharge(cath,q);
1379 //
1380 // Flag hit as "taken"  
1381     fHitMap[cath]->FlagHit(i,j);
1382 //
1383 //  Now look recursively for all neighbours and pad hit on opposite cathode
1384 //
1385 //  Loop over neighbours
1386     Int_t ix,iy;
1387     ix=iy=0;
1388     Int_t nn;
1389     Int_t xList[10], yList[10];
1390     fSeg[cath]->Neighbours(i,j,&nn,xList,yList);
1391     for (Int_t in=0; in<nn; in++) {
1392         ix=xList[in];
1393         iy=yList[in];
1394         
1395         if (fHitMap[cath]->TestHit(ix,iy)==kUnused) {
1396             if (fDebugLevel>1)
1397                 printf("\n Neighbours %d %d %d", cath, ix, iy);
1398             FindCluster(ix, iy, cath, c);
1399         }
1400         
1401    }
1402     Int_t nOpp=0;
1403     Int_t iXopp[50], iYopp[50];
1404     
1405 //  Neighbours on opposite cathode 
1406 //  Take into account that several pads can overlap with the present pad
1407     Int_t isec=fSeg[cath]->Sector(i,j);    
1408     Int_t iop;
1409     Float_t dx, dy;
1410
1411     if (cath==0) {
1412         iop = 1;
1413         dx  = (fSeg[cath]->Dpx(isec))/2.;
1414         dy  = 0.;
1415     } else {
1416         iop = 0;
1417         dx  = 0.;
1418         dy  = (fSeg[cath]->Dpy(isec))/2;
1419     }
1420 // loop over pad neighbours on opposite cathode
1421     for (fSeg[iop]->FirstPad(x, y, fZPlane, dx, dy);
1422          fSeg[iop]->MorePads();
1423          fSeg[iop]->NextPad())
1424     {
1425         
1426         ix = fSeg[iop]->Ix(); iy = fSeg[iop]->Iy();
1427         if (fDebugLevel > 1)
1428             printf("\n ix, iy: %f %f %f %d %d %d", x,y,z,ix, iy, fSector);
1429         if (fHitMap[iop]->TestHit(ix,iy)==kUnused){
1430             iXopp[nOpp]=ix;
1431             iYopp[nOpp++]=iy;
1432             if (fDebugLevel > 1)
1433                 printf("\n Opposite %d %d %d", iop, ix, iy);
1434         }
1435         
1436     } // Loop over pad neighbours
1437 //  This had to go outside the loop since recursive calls inside the iterator are not possible
1438 //
1439     Int_t jopp;
1440     for (jopp=0; jopp<nOpp; jopp++) {
1441         if (fHitMap[iop]->TestHit(iXopp[jopp],iYopp[jopp]) == kUnused) 
1442             FindCluster(iXopp[jopp], iYopp[jopp], iop, c);
1443     }
1444 }
1445
1446 //_____________________________________________________________________________
1447
1448 void AliMUONClusterFinderVS::FindRawClusters()
1449 {
1450   //
1451   // MUON cluster finder from digits -- finds neighbours on both cathodes and 
1452   // fills the tree with raw clusters
1453   //
1454
1455     ResetRawClusters();
1456 //  Return if no input datad available
1457     if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1458
1459     fSeg[0] = fInput->Segmentation(0);
1460     fSeg[1] = fInput->Segmentation(1);
1461
1462     fHitMap[0]  = new AliMUONHitMapA1(fSeg[0], fInput->Digits(0));
1463     fHitMap[1]  = new AliMUONHitMapA1(fSeg[1], fInput->Digits(1));
1464
1465  
1466     AliMUONDigit *dig;
1467
1468     Int_t ndig, cath;
1469     Int_t nskip=0;
1470     Int_t ncls=0;
1471     fHitMap[0]->FillHits();
1472     fHitMap[1]->FillHits();
1473 //
1474 //  Outer Loop over Cathodes
1475     for (cath=0; cath<2; cath++) {
1476         for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1477             dig = fInput->Digit(cath, ndig);
1478             Int_t i=dig->PadX();
1479             Int_t j=dig->PadY();
1480             if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1481                 nskip++;
1482                 continue;
1483             }
1484             if (fDebugLevel)
1485                 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1486             AliMUONRawCluster c;
1487             c.SetMultiplicity(0, 0);
1488             c.SetMultiplicity(1, 0);
1489             c.SetPeakSignal(cath,dig->Signal());
1490             c.SetTrack(0, dig->Hit());
1491             c.SetTrack(1, dig->Track(0));
1492             c.SetTrack(2, dig->Track(1));
1493             // tag the beginning of cluster list in a raw cluster
1494             c.SetNcluster(0,-1);
1495             Float_t xcu, ycu;
1496             fSeg[cath]->GetPadC(i,j,xcu, ycu, fZPlane);
1497             fSector= fSeg[cath]->Sector(i,j)/100;
1498             if (fDebugLevel)
1499                 printf("\n New Seed %d %d ", i,j);
1500         
1501             
1502             FindCluster(i,j,cath,c);
1503 //          ^^^^^^^^^^^^^^^^^^^^^^^^
1504             // center of gravity
1505             if (c.GetX(0)!=0.) c.SetX(0, c.GetX(0)/c.GetCharge(0)); // c.fX[0] /= c.fQ[0];
1506 // Force on anod
1507             c.SetX(0,fSeg[0]->GetAnod(c.GetX(0)));
1508             if (c.GetY(0)!=0.) c.SetY(0, c.GetY(0)/c.GetCharge(0)); // c.fY[0] /= c.fQ[0];
1509             
1510             if(c.GetCharge(1)!=0.) c.SetX(1, c.GetX(1)/c.GetCharge(1));  // c.fX[1] /= c.fQ[1];
1511                                         
1512            // Force on anod
1513             c.SetX(1, fSeg[0]->GetAnod(c.GetX(1)));
1514             if(c.GetCharge(1)!=0.) c.SetY(1, c.GetY(1)/c.GetCharge(1));// c.fY[1] /= c.fQ[1];
1515             
1516             c.SetZ(0, fZPlane);
1517             c.SetZ(1, fZPlane);     
1518
1519             if (fDebugLevel) {
1520                 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",
1521                         c.GetMultiplicity(0),c.GetX(0),c.GetY(0));
1522                 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",
1523                         c.GetMultiplicity(1),c.GetX(1),c.GetY(1));
1524             }
1525 //      Analyse cluster and decluster if necessary
1526 //      
1527         ncls++;
1528         c.SetNcluster(1,fNRawClusters);
1529         c.SetClusterType(c.PhysicsContribution());
1530
1531         fNPeaks=0;
1532 //
1533 //
1534         Decluster(&c);
1535 //
1536 //      reset Cluster object
1537         { // begin local scope
1538             for (int k=0;k<c.GetMultiplicity(0);k++) c.SetIndex(k, 0, 0);
1539         } // end local scope
1540
1541         { // begin local scope
1542             for (int k=0;k<c.GetMultiplicity(1);k++) c.SetIndex(k, 1, 0);
1543         } // end local scope
1544         
1545         c.SetMultiplicity(0,0);
1546         c.SetMultiplicity(1,0);
1547
1548         
1549         } // end loop ndig
1550     } // end loop cathodes
1551     delete fHitMap[0];
1552     delete fHitMap[1];
1553 }
1554
1555 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1556 {
1557 // Performs a single Mathieson fit on one cathode
1558 // 
1559     Double_t arglist[20];
1560     Int_t ierflag=0;
1561     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1562     
1563     clusterInput.Fitter()->SetFCN(fcnS1);
1564     clusterInput.Fitter()->mninit(2,10,7);
1565     clusterInput.Fitter()->SetPrintLevel(-1+fDebugLevel);
1566     arglist[0]=-1;
1567     clusterInput.Fitter()->mnexcm("SET NOW", arglist, 0, ierflag);
1568 // Set starting values 
1569     static Double_t vstart[2];
1570     vstart[0]=c->GetX(1);
1571     vstart[1]=c->GetY(0);
1572     
1573     
1574 // lower and upper limits
1575     static Double_t lower[2], upper[2];
1576     Int_t ix,iy;
1577     fSeg[cath]->GetPadI(c->GetX(cath), c->GetY(cath), fZPlane, ix, iy);
1578     Int_t isec=fSeg[cath]->Sector(ix, iy);
1579     lower[0]=vstart[0]-fSeg[cath]->Dpx(isec)/2;
1580     lower[1]=vstart[1]-fSeg[cath]->Dpy(isec)/2;
1581     
1582     upper[0]=lower[0]+fSeg[cath]->Dpx(isec);
1583     upper[1]=lower[1]+fSeg[cath]->Dpy(isec);
1584     
1585 // step sizes
1586     static Double_t step[2]={0.0005, 0.0005};
1587     
1588     clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1589     clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1590 // ready for minimisation       
1591     arglist[0]= -1;
1592     arglist[1]= 0;
1593     
1594     clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1595     clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1596     //    clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1597     Double_t fmin, fedm, errdef;
1598     Int_t   npari, nparx, istat;
1599       
1600     clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);  
1601     fFitStat=istat;
1602     
1603 // Print results
1604 // Get fitted parameters
1605     Double_t xrec, yrec;
1606     TString chname;
1607     Double_t epxz, b1, b2;
1608     Int_t ierflg;
1609     clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);       
1610     clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);       
1611     fXFit[cath]=xrec;
1612     fYFit[cath]=yrec;
1613     return fmin;
1614 }
1615
1616 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster * /*c*/)
1617 {
1618 // Perform combined Mathieson fit on both cathode planes
1619 //
1620     Double_t arglist[20];
1621     Int_t ierflag=0;
1622     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1623     clusterInput.Fitter()->SetFCN(fcnCombiS1);
1624     clusterInput.Fitter()->mninit(2,10,7);
1625     clusterInput.Fitter()->SetPrintLevel(-1+fDebugLevel);
1626     arglist[0]=-1;
1627     clusterInput.Fitter()->mnexcm("SET NOW", arglist, 0, ierflag);
1628     static Double_t vstart[2];
1629     vstart[0]=fXInit[0];
1630     vstart[1]=fYInit[0];
1631     
1632     
1633 // lower and upper limits
1634     static Float_t lower[2], upper[2];
1635     Int_t ix,iy,isec;
1636     fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1637     isec=fSeg[0]->Sector(ix, iy);
1638     Float_t dpy=fSeg[0]->Dpy(isec);
1639     fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1640     isec=fSeg[1]->Sector(ix, iy);
1641     Float_t dpx=fSeg[1]->Dpx(isec);
1642
1643     Int_t icount;
1644     Float_t xdum, ydum, zdum;
1645
1646 //  Find save upper and lower limits    
1647     
1648     icount = 0;
1649     
1650     for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.); 
1651          fSeg[1]->MorePads(); fSeg[1]->NextPad())
1652     {
1653         ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1654         fSeg[1]->GetPadC(ix,iy, upper[0], ydum, zdum);  
1655         if (icount ==0) lower[0]=upper[0];
1656         icount++;
1657     }
1658
1659     if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1660         
1661     icount=0;
1662     if (fDebugLevel)
1663         printf("\n single y %f %f", fXInit[0], fYInit[0]);
1664     
1665     for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy); 
1666          fSeg[0]->MorePads(); fSeg[0]->NextPad())
1667     {
1668         ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1669         fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);     
1670         if (icount ==0) lower[1]=upper[1];
1671         icount++;
1672         if (fDebugLevel)
1673             printf("\n upper lower %d %f %f", icount, upper[1], lower[1]);
1674     }
1675     
1676     if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1677
1678 // step sizes
1679     static Double_t step[2]={0.00001, 0.0001};
1680     
1681     clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1682     clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1683 // ready for minimisation       
1684     arglist[0]= -1;
1685     arglist[1]= 0;
1686     
1687     clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1688     clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1689     //    clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1690     Double_t fmin, fedm, errdef;
1691     Int_t   npari, nparx, istat;
1692       
1693     clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);  
1694     fFitStat=istat;
1695     
1696 // Print results
1697 // Get fitted parameters
1698     Double_t xrec, yrec;
1699     TString chname;
1700     Double_t epxz, b1, b2;
1701     Int_t ierflg;
1702     clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);       
1703     clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);       
1704     fXFit[0]=xrec;
1705     fYFit[0]=yrec;
1706     return fmin;
1707 }
1708
1709 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster * /*c*/, Int_t cath)
1710 {
1711 // Performs a double Mathieson fit on one cathode
1712 // 
1713
1714 //
1715 //  Initialise global variables for fit
1716     Double_t arglist[20];
1717     Int_t ierflag=0;
1718     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1719     clusterInput.Fitter()->SetFCN(fcnS2);
1720     clusterInput.Fitter()->mninit(5,10,7);
1721     clusterInput.Fitter()->SetPrintLevel(-1+fDebugLevel);
1722     arglist[0]=-1;
1723     clusterInput.Fitter()->mnexcm("SET NOW", arglist, 0, ierflag);
1724 // Set starting values 
1725     static Double_t vstart[5];
1726     vstart[0]=fX[fIndLocal[0][cath]][cath];
1727     vstart[1]=fY[fIndLocal[0][cath]][cath];     
1728     vstart[2]=fX[fIndLocal[1][cath]][cath];
1729     vstart[3]=fY[fIndLocal[1][cath]][cath];     
1730     vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1731         Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1732 // lower and upper limits
1733     static Float_t lower[5], upper[5];
1734     Int_t isec=fSeg[cath]->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1735     lower[0]=vstart[0]-fSeg[cath]->Dpx(isec);
1736     lower[1]=vstart[1]-fSeg[cath]->Dpy(isec);
1737     
1738     upper[0]=lower[0]+2.*fSeg[cath]->Dpx(isec);
1739     upper[1]=lower[1]+2.*fSeg[cath]->Dpy(isec);
1740     
1741     isec=fSeg[cath]->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1742     lower[2]=vstart[2]-fSeg[cath]->Dpx(isec)/2;
1743     lower[3]=vstart[3]-fSeg[cath]->Dpy(isec)/2;
1744     
1745     upper[2]=lower[2]+fSeg[cath]->Dpx(isec);
1746     upper[3]=lower[3]+fSeg[cath]->Dpy(isec);
1747     
1748     lower[4]=0.;
1749     upper[4]=1.;
1750 // step sizes
1751     static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1752     
1753     clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1754     clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1755     clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1756     clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1757     clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1758 // ready for minimisation       
1759     arglist[0]= -1;
1760     arglist[1]= 0;
1761     
1762     clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1763     clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1764     //    clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1765 // Get fitted parameters
1766     Double_t xrec[2], yrec[2], qfrac;
1767     TString chname;
1768     Double_t epxz, b1, b2;
1769     Int_t ierflg;
1770     clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);    
1771     clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);    
1772     clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);    
1773     clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);    
1774     clusterInput.Fitter()->mnpout(4, chname, qfrac,   epxz, b1, b2, ierflg);    
1775
1776     Double_t fmin, fedm, errdef;
1777     Int_t   npari, nparx, istat;
1778       
1779     clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);  
1780     fFitStat=istat;
1781     return kTRUE;
1782 }
1783
1784 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster * /*c*/)
1785 {
1786 //
1787 // Perform combined double Mathieson fit on both cathode planes
1788 //
1789     Double_t arglist[20];
1790     Int_t ierflag=0;
1791     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1792     clusterInput.Fitter()->SetFCN(fcnCombiS2);
1793     clusterInput.Fitter()->mninit(6,10,7);
1794     clusterInput.Fitter()->SetPrintLevel(-1+fDebugLevel);
1795     arglist[0]=-1;
1796     clusterInput.Fitter()->mnexcm("SET NOW", arglist, 0, ierflag);
1797 // Set starting values 
1798     static Double_t vstart[6];
1799     vstart[0]=fXInit[0];
1800     vstart[1]=fYInit[0];
1801     vstart[2]=fXInit[1];
1802     vstart[3]=fYInit[1];
1803     vstart[4]=fQrInit[0];
1804     vstart[5]=fQrInit[1];
1805 // lower and upper limits
1806     static Float_t lower[6], upper[6];
1807     Int_t ix,iy,isec;
1808     Float_t dpx, dpy;
1809     
1810     fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1811     isec=fSeg[1]->Sector(ix, iy);
1812     dpx=fSeg[1]->Dpx(isec);
1813
1814     fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1815     isec=fSeg[0]->Sector(ix, iy);
1816     dpy=fSeg[0]->Dpy(isec);
1817
1818
1819     Int_t icount;
1820     Float_t xdum, ydum, zdum;
1821     if (fDebugLevel)
1822         printf("\n Cluster Finder: %f %f %f %f  ", fXInit[0], fXInit[1],fYInit[0], fYInit[1] );
1823     
1824 //  Find save upper and lower limits    
1825     icount = 0;
1826     
1827     for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.); 
1828          fSeg[1]->MorePads(); fSeg[1]->NextPad())
1829     {
1830         ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1831 //      if (fHitMap[1]->TestHit(ix, iy) == kEmpty) continue;
1832         fSeg[1]->GetPadC(ix,iy,upper[0],ydum,zdum);     
1833         if (icount ==0) lower[0]=upper[0];
1834         icount++;
1835     }
1836     if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}    
1837 //    vstart[0] = 0.5*(lower[0]+upper[0]);
1838
1839     
1840     icount=0;
1841     
1842     for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy); 
1843          fSeg[0]->MorePads(); fSeg[0]->NextPad())
1844     {
1845         ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1846 //      if (fHitMap[0]->TestHit(ix, iy) == kEmpty) continue;
1847         fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);     
1848         if (icount ==0) lower[1]=upper[1];
1849         icount++;
1850     }
1851     
1852     if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}    
1853 //     vstart[1] = 0.5*(lower[1]+upper[1]);
1854
1855
1856     fSeg[1]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1857     isec=fSeg[1]->Sector(ix, iy);
1858     dpx=fSeg[1]->Dpx(isec);
1859     fSeg[0]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1860     isec=fSeg[0]->Sector(ix, iy);
1861     dpy=fSeg[0]->Dpy(isec);
1862
1863
1864 //  Find save upper and lower limits    
1865
1866     icount=0;
1867     
1868     for (fSeg[1]->FirstPad(fXInit[1], fYInit[1], fZPlane, dpx, 0); 
1869          fSeg[1]->MorePads(); fSeg[1]->NextPad())
1870     {
1871         ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1872 //      if (fHitMap[1]->TestHit(ix, iy) == kEmpty) continue;
1873         fSeg[1]->GetPadC(ix,iy,upper[2],ydum,zdum);     
1874         if (icount ==0) lower[2]=upper[2];
1875         icount++;
1876     }
1877     if (lower[2]>upper[2]) {xdum=lower[2]; lower[2]=upper[2]; upper[2]=xdum;}    
1878     //    vstart[2] = 0.5*(lower[2]+upper[2]);
1879
1880     icount=0;
1881     
1882     for (fSeg[0]->FirstPad(fXInit[1], fYInit[1], fZPlane, 0, dpy); 
1883          fSeg[0]-> MorePads(); fSeg[0]->NextPad())
1884     {
1885         ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1886 //      if (fHitMap[0]->TestHit(ix, iy) != kEmpty) continue;
1887         
1888         fSeg[0]->GetPadC(ix,iy,xdum,upper[3],zdum);     
1889         if (icount ==0) lower[3]=upper[3];
1890         icount++;
1891
1892     }
1893     if (lower[3]>upper[3]) {xdum=lower[3]; lower[3]=upper[3]; upper[3]=xdum;}    
1894     
1895 //     vstart[3] = 0.5*(lower[3]+upper[3]);
1896     
1897     lower[4]=0.;
1898     upper[4]=1.;
1899     lower[5]=0.;
1900     upper[5]=1.;
1901
1902 // step sizes
1903     static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1904     clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1905     clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1906     clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1907     clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1908     clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1909     clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1910 // ready for minimisation       
1911     arglist[0]= -1;
1912     arglist[1]= 0;
1913     
1914     clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1915     clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1916     //    clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1917 // Get fitted parameters
1918     TString chname;
1919     Double_t epxz, b1, b2;
1920     Int_t ierflg;
1921     clusterInput.Fitter()->mnpout(0, chname, fXFit[0],  epxz, b1, b2, ierflg);  
1922     clusterInput.Fitter()->mnpout(1, chname, fYFit[0],  epxz, b1, b2, ierflg);  
1923     clusterInput.Fitter()->mnpout(2, chname, fXFit[1],  epxz, b1, b2, ierflg);  
1924     clusterInput.Fitter()->mnpout(3, chname, fYFit[1],  epxz, b1, b2, ierflg);  
1925     clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);  
1926     clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);  
1927
1928     Double_t fmin, fedm, errdef;
1929     Int_t   npari, nparx, istat;
1930       
1931     clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);  
1932     fFitStat=istat;
1933     
1934     fChi2[0]=fmin;
1935     fChi2[1]=fmin;
1936     return fmin;
1937 }
1938
1939 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1940 {
1941 //
1942 // One cluster for each maximum
1943 //
1944     Int_t i, j, cath;
1945     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1946     for (j=0; j<2; j++) {
1947         AliMUONRawCluster cnew;
1948         cnew.SetGhost(c->GetGhost());
1949         for (cath=0; cath<2; cath++) {
1950             cnew.SetChi2(cath,fChi2[0]);
1951             // ?? why not cnew.fChi2[cath]=fChi2[cath];
1952             
1953             if (fNPeaks == 0) {
1954                 cnew.SetNcluster(0,-1);
1955                 cnew.SetNcluster(1,fNRawClusters);
1956             } else {
1957                 cnew.SetNcluster(0,fNPeaks);
1958                 cnew.SetNcluster(1,0);
1959             }
1960             cnew.SetMultiplicity(cath,0);
1961             cnew.SetX(cath, Float_t(fXFit[j]));
1962             cnew.SetY(cath, Float_t(fYFit[j]));
1963             cnew.SetZ(cath, fZPlane);
1964             if (j==0) {
1965                 cnew.SetCharge(cath, Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]));
1966             } else {
1967                 cnew.SetCharge(cath, Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath])));
1968             }
1969             fSeg[cath]->SetHit(fXFit[j],fYFit[j],fZPlane);
1970             for (i=0; i<fMul[cath]; i++) {
1971                 cnew.SetIndex(cnew.GetMultiplicity(cath), cath, c->GetIndex(i,cath));
1972                 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
1973                 Float_t q1=fInput->Response()->IntXY(fSeg[cath]);
1974                 cnew.SetContrib(i, cath, q1*Float_t(cnew.GetCharge(cath))/Float_t(fQ[i][cath]));
1975                 cnew.SetMultiplicity(cath, cnew.GetMultiplicity(cath)+1 );
1976             }
1977             FillCluster(&cnew,0,cath);
1978         } // cathode loop
1979         
1980         cnew.SetClusterType(cnew.PhysicsContribution());
1981         if (cnew.GetCharge(0)>0 && cnew.GetCharge(1)>0) AddRawCluster(cnew);
1982         fNPeaks++;
1983     }
1984 }
1985
1986
1987 //
1988 // Minimisation functions
1989 // Single Mathieson
1990 void fcnS1(Int_t & /*npar*/, Double_t * /*gin*/, Double_t &f, Double_t *par, Int_t /*iflag*/)
1991 {
1992     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());    
1993     Int_t i;
1994     Float_t delta;
1995     Float_t chisq=0;
1996     Float_t qcont=0;
1997     Float_t qtot=0;
1998
1999     for (i=0; i<clusterInput.Nmul(0); i++) {
2000         Float_t q0=clusterInput.Charge(i,0);
2001         Float_t q1=clusterInput.DiscrChargeS1(i,par);
2002         delta=(q0-q1)/q0;
2003         chisq+=delta*delta;
2004         qcont+=q1;
2005         qtot+=q0;
2006     }
2007     f=chisq;
2008 }
2009
2010 void fcnCombiS1(Int_t & /*npar*/, Double_t * /*gin*/, Double_t &f, Double_t *par, Int_t /*iflag*/)
2011 {
2012     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());    
2013     Int_t i, cath;
2014     Float_t delta;
2015     Float_t chisq=0;
2016     Float_t qcont=0;
2017     Float_t qtot=0;
2018
2019     for (cath=0; cath<2; cath++) {
2020         for (i=0; i<clusterInput.Nmul(cath); i++) {
2021             Float_t q0=clusterInput.Charge(i,cath);
2022             Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
2023             delta=(q0-q1)/q0;
2024             chisq+=delta*delta;
2025             qcont+=q1;
2026             qtot+=q0;
2027         }
2028     }
2029     f=chisq;
2030 }
2031
2032 // Double Mathieson
2033 void fcnS2(Int_t & /*npar*/, Double_t * /*gin*/, Double_t &f, Double_t *par, Int_t /*iflag*/)
2034 {
2035     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());    
2036     Int_t i;
2037     Float_t delta;
2038     Float_t chisq=0;
2039     Float_t qcont=0;
2040     Float_t qtot=0;
2041     
2042     for (i=0; i<clusterInput.Nmul(0); i++) {
2043
2044         Float_t q0=clusterInput.Charge(i,0);
2045         Float_t q1=clusterInput.DiscrChargeS2(i,par);
2046         delta=(q0-q1)/q0;
2047         chisq+=delta*delta;
2048         qcont+=q1;
2049         qtot+=q0;
2050     }
2051     f=chisq;
2052 }
2053
2054 // Double Mathieson
2055 void fcnCombiS2(Int_t & /*npar*/, Double_t * /*gin*/, Double_t &f, Double_t *par, Int_t /*iflag*/)
2056 {
2057     AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());    
2058     Int_t i, cath;
2059     Float_t delta;
2060     Float_t chisq=0;
2061     Float_t qcont=0;
2062     Float_t qtot=0;
2063     for (cath=0; cath<2; cath++) {
2064         for (i=0; i<clusterInput.Nmul(cath); i++) {
2065             Float_t q0=clusterInput.Charge(i,cath);
2066             Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
2067             delta=(q0-q1)/q0;
2068             chisq+=delta*delta;
2069             qcont+=q1;
2070             qtot+=q0;
2071         }
2072     }
2073     f=chisq;
2074 }
2075
2076 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster& c)
2077 {
2078   //
2079   // Add a raw cluster copy to the list
2080   //
2081
2082 //     AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
2083 //     pMUON->GetMUONData()->AddRawCluster(fInput->Chamber(),c); 
2084 //     fNRawClusters++;
2085
2086   
2087     TClonesArray &lrawcl = *fRawClusters;
2088     new(lrawcl[fNRawClusters++]) AliMUONRawCluster(c);
2089     if (fDebugLevel)
2090         fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
2091 }
2092
2093 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) const {
2094 // Test if track was user selected
2095     if (fTrack[0]==-1 || fTrack[1]==-1) {
2096         return kTRUE;
2097     } else if (t==fTrack[0] || t==fTrack[1]) {
2098         return kTRUE;
2099     } else {
2100         return kFALSE;
2101     }
2102 }
2103
2104 AliMUONClusterFinderVS& AliMUONClusterFinderVS
2105 ::operator = (const AliMUONClusterFinderVS& rhs)
2106 {
2107 // Protected assignement operator
2108
2109   if (this == &rhs) return *this;
2110
2111   Fatal("operator=", "Not implemented.");
2112     
2113   return *this;  
2114 }
2115
2116
2117
2118
2119
2120
2121
2122
2123