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