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