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