1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
17 Revision 1.12 2000/10/18 11:42:06 morsch
18 - AliMUONRawCluster contains z-position.
19 - Some clean-up of useless print statements during initialisations.
21 Revision 1.11 2000/10/06 09:04:05 morsch
22 - Dummy z-arguments in GetPadI, SetHit, FirstPad replaced by real z-coordinate
23 to make code work with slat chambers (AM)
24 - Replace GetPadI calls with unchecked x,y coordinates by pad iterator calls wherever possible.
26 Revision 1.10 2000/10/03 13:51:57 egangler
27 Removal of useless dependencies via forward declarations
29 Revision 1.9 2000/10/02 16:58:29 egangler
30 Cleaning of the code :
33 -> some useless includes removed or replaced by "class" statement
35 Revision 1.8 2000/07/03 11:54:57 morsch
36 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
37 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
39 Revision 1.7 2000/06/28 15:16:35 morsch
40 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
41 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
42 framework. The changes should have no side effects (mostly dummy arguments).
43 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
44 of chambers with overlapping modules (MakePadHits, Disintegration).
46 Revision 1.6 2000/06/28 12:19:18 morsch
47 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
48 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
49 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
50 It requires two cathode planes. Small modifications in the code will make it usable for
51 one cathode plane and, hence, more general (for test beam data).
52 AliMUONClusterFinder is now obsolete.
54 Revision 1.5 2000/06/28 08:06:10 morsch
55 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
56 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
57 It also naturally takes care of the TMinuit instance.
59 Revision 1.4 2000/06/27 16:18:47 gosset
60 Finally correct implementation of xm, ym, ixm, iym sizes
61 when at least three local maxima on cathode 1 or on cathode 2
63 Revision 1.3 2000/06/22 14:02:45 morsch
64 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
65 Some HP scope problems corrected (PH)
67 Revision 1.2 2000/06/15 07:58:48 morsch
68 Code from MUON-dev joined
70 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
71 Most coding rule violations corrected.
73 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
74 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
75 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
76 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
77 - For clusters with more than 2 maxima on one of the cathode planes all valid
78 combinations of maxima on the two cathodes are preserved. The position of the maxima is
79 taken as the hit position.
80 - New FillCluster method with 2 arguments to find tracks associated to the clusters
81 defined above added. (Method destinction by argument list not very elegant in this case,
82 should be revides (A.M.)
83 - Bug in if-statement to handle maximum 1 maximum per plane corrected
84 - Two cluster per cathode but only 1 combination valid is handled.
85 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
89 #include "AliMUONClusterFinderVS.h"
90 #include "AliMUONDigit.h"
91 #include "AliMUONRawCluster.h"
92 #include "AliSegmentation.h"
93 #include "AliMUONResponse.h"
94 #include "AliMUONClusterInput.h"
95 #include "AliMUONHitMapA1.h"
104 #include <TPostScript.h>
109 #include <iostream.h>
111 //_____________________________________________________________________
112 // This function is minimized in the double-Mathieson fit
113 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
114 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
115 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
116 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
118 ClassImp(AliMUONClusterFinderVS)
120 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
122 // Default constructor
123 fInput=AliMUONClusterInput::Instance();
126 fTrack[0]=fTrack[1]=-1;
129 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
130 const AliMUONClusterFinderVS & clusterFinder)
132 // Dummy copy Constructor
136 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
138 // Decluster by local maxima
139 SplitByLocalMaxima(cluster);
142 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
144 // Split complex cluster by local maxima
147 fInput->SetCluster(c);
149 fMul[0]=c->fMultiplicity[0];
150 fMul[1]=c->fMultiplicity[1];
153 // dump digit information into arrays
158 for (cath=0; cath<2; cath++) {
160 for (i=0; i<fMul[cath]; i++)
163 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
165 fIx[i][cath]= fDig[i][cath]->fPadX;
166 fIy[i][cath]= fDig[i][cath]->fPadY;
168 fQ[i][cath] = fDig[i][cath]->fSignal;
169 // pad centre coordinates
171 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], fZ[i][cath]);
172 } // loop over cluster digits
173 } // loop over cathodes
179 // Initialise and perform mathieson fits
180 Float_t chi2, oldchi2;
181 // ++++++++++++++++++*************+++++++++++++++++++++
182 // (1) No more than one local maximum per cathode plane
183 // +++++++++++++++++++++++++++++++*************++++++++
184 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
185 (fNLocal[0]==0 && fNLocal[1]==1)) {
187 // Perform combined single Mathieson fit
188 // Initial values for coordinates (x,y)
190 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
191 if (fNLocal[0]==1 && fNLocal[1]==1) {
194 // One local maximum on cathode 1 (X,Y->cathode 1)
195 } else if (fNLocal[0]==1) {
198 // One local maximum on cathode 2 (X,Y->cathode 2)
203 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
204 chi2=CombiSingleMathiesonFit(c);
205 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
206 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
207 // prob1->Fill(prob);
208 // chi2_1->Fill(chi2);
210 fprintf(stderr," chi2 %f ",chi2);
219 c->fX[0]=fSeg[0]->GetAnod(c->fX[0]);
220 c->fX[1]=fSeg[1]->GetAnod(c->fX[1]);
222 // If reasonable chi^2 add result to the list of rawclusters
226 // If not try combined double Mathieson Fit
228 fprintf(stderr," MAUVAIS CHI2 !!!\n");
229 if (fNLocal[0]==1 && fNLocal[1]==1) {
230 fXInit[0]=fX[fIndLocal[0][1]][1];
231 fYInit[0]=fY[fIndLocal[0][0]][0];
232 fXInit[1]=fX[fIndLocal[0][1]][1];
233 fYInit[1]=fY[fIndLocal[0][0]][0];
234 } else if (fNLocal[0]==1) {
235 fXInit[0]=fX[fIndLocal[0][0]][0];
236 fYInit[0]=fY[fIndLocal[0][0]][0];
237 fXInit[1]=fX[fIndLocal[0][0]][0];
238 fYInit[1]=fY[fIndLocal[0][0]][0];
240 fXInit[0]=fX[fIndLocal[0][1]][1];
241 fYInit[0]=fY[fIndLocal[0][1]][1];
242 fXInit[1]=fX[fIndLocal[0][1]][1];
243 fYInit[1]=fY[fIndLocal[0][1]][1];
246 // Initial value for charge ratios
249 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
250 chi2=CombiDoubleMathiesonFit(c);
251 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
252 // Float_t prob = TMath::Prob(chi2,ndf);
253 // prob2->Fill(prob);
254 // chi2_2->Fill(chi2);
256 // Was this any better ??
257 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
258 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
259 fprintf(stderr," Split\n");
260 // Split cluster into two according to fit result
263 fprintf(stderr," Don't Split\n");
269 // +++++++++++++++++++++++++++++++++++++++
270 // (2) Two local maxima per cathode plane
271 // +++++++++++++++++++++++++++++++++++++++
272 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
274 // Let's look for ghosts first
276 Float_t xm[4][2], ym[4][2];
277 Float_t dpx, dpy, dx, dy;
278 Int_t ixm[4][2], iym[4][2];
279 Int_t isec, im1, im2, ico;
281 // Form the 2x2 combinations
282 // 0-0, 0-1, 1-0, 1-1
284 for (im1=0; im1<2; im1++) {
285 for (im2=0; im2<2; im2++) {
286 xm[ico][0]=fX[fIndLocal[im1][0]][0];
287 ym[ico][0]=fY[fIndLocal[im1][0]][0];
288 xm[ico][1]=fX[fIndLocal[im2][1]][1];
289 ym[ico][1]=fY[fIndLocal[im2][1]][1];
291 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
292 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
293 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
294 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
298 // ico = 0 : first local maximum on cathodes 1 and 2
299 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
300 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
301 // ico = 3 : second local maximum on cathodes 1 and 2
303 // Analyse the combinations and keep those that are possible !
304 // For each combination check consistency in x and y
309 for (ico=0; ico<4; ico++) {
310 accepted[ico]=kFALSE;
311 // cathode one: x-coordinate
312 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
313 dpx=fSeg[0]->Dpx(isec)/2.;
314 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
315 // cathode two: y-coordinate
316 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
317 dpy=fSeg[1]->Dpy(isec)/2.;
318 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
319 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
320 if ((dx <= dpx) && (dy <= dpy)) {
326 accepted[ico]=kFALSE;
331 fprintf(stderr,"\n iacc=2: No problem ! \n");
332 } else if (iacc==4) {
333 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
334 } else if (iacc==0) {
335 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
338 // Initial value for charge ratios
339 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
340 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
341 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
342 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
344 // ******* iacc = 0 *******
345 // No combinations found between the 2 cathodes
346 // We keep the center of gravity of the cluster
351 // ******* iacc = 1 *******
352 // Only one combination found between the 2 cathodes
355 // Initial values for the 2 maxima (x,y)
357 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
358 // 1 maximum is initialised with the other maximum of the first cathode
360 fprintf(stderr,"ico=0\n");
365 } else if (accepted[1]){
366 fprintf(stderr,"ico=1\n");
371 } else if (accepted[2]){
372 fprintf(stderr,"ico=2\n");
377 } else if (accepted[3]){
378 fprintf(stderr,"ico=3\n");
384 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
385 chi2=CombiDoubleMathiesonFit(c);
386 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
387 // Float_t prob = TMath::Prob(chi2,ndf);
388 // prob2->Fill(prob);
389 // chi2_2->Fill(chi2);
390 fprintf(stderr," chi2 %f\n",chi2);
392 // If reasonable chi^2 add result to the list of rawclusters
397 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
398 // 1 maximum is initialised with the other maximum of the second cathode
400 fprintf(stderr,"ico=0\n");
405 } else if (accepted[1]){
406 fprintf(stderr,"ico=1\n");
411 } else if (accepted[2]){
412 fprintf(stderr,"ico=2\n");
417 } else if (accepted[3]){
418 fprintf(stderr,"ico=3\n");
424 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
425 chi2=CombiDoubleMathiesonFit(c);
426 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
427 // Float_t prob = TMath::Prob(chi2,ndf);
428 // prob2->Fill(prob);
429 // chi2_2->Fill(chi2);
430 fprintf(stderr," chi2 %f\n",chi2);
432 // If reasonable chi^2 add result to the list of rawclusters
436 //We keep only the combination found (X->cathode 2, Y->cathode 1)
437 for (Int_t ico=0; ico<2; ico++) {
439 AliMUONRawCluster cnew;
441 for (cath=0; cath<2; cath++) {
442 cnew.fX[cath]=Float_t(xm[ico][1]);
443 cnew.fY[cath]=Float_t(ym[ico][0]);
444 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
445 for (i=0; i<fMul[cath]; i++) {
446 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
447 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
449 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
450 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
451 FillCluster(&cnew,cath);
453 cnew.fClusterType=cnew.PhysicsContribution();
462 // ******* iacc = 2 *******
463 // Two combinations found between the 2 cathodes
466 // Was the same maximum taken twice
467 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
468 fprintf(stderr,"\n Maximum taken twice !!!\n");
470 // Have a try !! with that
471 if (accepted[0]&&accepted[3]) {
482 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
483 chi2=CombiDoubleMathiesonFit(c);
484 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
485 // Float_t prob = TMath::Prob(chi2,ndf);
486 // prob2->Fill(prob);
487 // chi2_2->Fill(chi2);
491 // No ghosts ! No Problems ! - Perform one fit only !
492 if (accepted[0]&&accepted[3]) {
503 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
504 chi2=CombiDoubleMathiesonFit(c);
505 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
506 // Float_t prob = TMath::Prob(chi2,ndf);
507 // prob2->Fill(prob);
508 // chi2_2->Fill(chi2);
509 fprintf(stderr," chi2 %f\n",chi2);
513 // ******* iacc = 4 *******
514 // Four combinations found between the 2 cathodes
516 } else if (iacc==4) {
517 // Perform fits for the two possibilities !!
522 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
523 chi2=CombiDoubleMathiesonFit(c);
524 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
525 // Float_t prob = TMath::Prob(chi2,ndf);
526 // prob2->Fill(prob);
527 // chi2_2->Fill(chi2);
528 fprintf(stderr," chi2 %f\n",chi2);
534 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
535 chi2=CombiDoubleMathiesonFit(c);
536 // ndf = fgNbins[0]+fgNbins[1]-6;
537 // prob = TMath::Prob(chi2,ndf);
538 // prob2->Fill(prob);
539 // chi2_2->Fill(chi2);
540 fprintf(stderr," chi2 %f\n",chi2);
544 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
545 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
546 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
547 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
549 Float_t xm[4][2], ym[4][2];
550 Float_t dpx, dpy, dx, dy;
551 Int_t ixm[4][2], iym[4][2];
552 Int_t isec, im1, ico;
554 // Form the 2x2 combinations
555 // 0-0, 0-1, 1-0, 1-1
557 for (im1=0; im1<2; im1++) {
558 xm[ico][0]=fX[fIndLocal[im1][0]][0];
559 ym[ico][0]=fY[fIndLocal[im1][0]][0];
560 xm[ico][1]=fX[fIndLocal[0][1]][1];
561 ym[ico][1]=fY[fIndLocal[0][1]][1];
563 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
564 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
565 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
566 iym[ico][1]=fIy[fIndLocal[0][1]][1];
569 // ico = 0 : first local maximum on cathodes 1 and 2
570 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
572 // Analyse the combinations and keep those that are possible !
573 // For each combination check consistency in x and y
578 for (ico=0; ico<2; ico++) {
579 accepted[ico]=kFALSE;
580 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
581 dpx=fSeg[0]->Dpx(isec)/2.;
582 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
583 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
584 dpy=fSeg[1]->Dpy(isec)/2.;
585 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
586 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
587 if ((dx <= dpx) && (dy <= dpy)) {
593 accepted[ico]=kFALSE;
605 chi21=CombiDoubleMathiesonFit(c);
606 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
607 // Float_t prob = TMath::Prob(chi2,ndf);
608 // prob2->Fill(prob);
609 // chi2_2->Fill(chi21);
610 fprintf(stderr," chi2 %f\n",chi21);
611 if (chi21<10) Split(c);
612 } else if (accepted[1]) {
617 chi22=CombiDoubleMathiesonFit(c);
618 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
619 // Float_t prob = TMath::Prob(chi2,ndf);
620 // prob2->Fill(prob);
621 // chi2_2->Fill(chi22);
622 fprintf(stderr," chi2 %f\n",chi22);
623 if (chi22<10) Split(c);
626 if (chi21 > 10 && chi22 > 10) {
627 // We keep only the combination found (X->cathode 2, Y->cathode 1)
628 for (Int_t ico=0; ico<2; ico++) {
630 AliMUONRawCluster cnew;
632 for (cath=0; cath<2; cath++) {
633 cnew.fX[cath]=Float_t(xm[ico][1]);
634 cnew.fY[cath]=Float_t(ym[ico][0]);
635 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
636 for (i=0; i<fMul[cath]; i++) {
637 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
638 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
640 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
641 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
642 FillCluster(&cnew,cath);
644 cnew.fClusterType=cnew.PhysicsContribution();
651 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
652 // (3') One local maximum on cathode 1 and two maxima on cathode 2
653 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
654 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
656 Float_t xm[4][2], ym[4][2];
657 Float_t dpx, dpy, dx, dy;
658 Int_t ixm[4][2], iym[4][2];
659 Int_t isec, im1, ico;
661 // Form the 2x2 combinations
662 // 0-0, 0-1, 1-0, 1-1
664 for (im1=0; im1<2; im1++) {
665 xm[ico][0]=fX[fIndLocal[0][0]][0];
666 ym[ico][0]=fY[fIndLocal[0][0]][0];
667 xm[ico][1]=fX[fIndLocal[im1][1]][1];
668 ym[ico][1]=fY[fIndLocal[im1][1]][1];
670 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
671 iym[ico][0]=fIy[fIndLocal[0][0]][0];
672 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
673 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
676 // ico = 0 : first local maximum on cathodes 1 and 2
677 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
679 // Analyse the combinations and keep those that are possible !
680 // For each combination check consistency in x and y
685 for (ico=0; ico<2; ico++) {
686 accepted[ico]=kFALSE;
687 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
688 dpx=fSeg[0]->Dpx(isec)/2.;
689 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
690 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
691 dpy=fSeg[1]->Dpy(isec)/2.;
692 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
693 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
694 if ((dx <= dpx) && (dy <= dpy)) {
697 fprintf(stderr,"ico %d\n",ico);
701 accepted[ico]=kFALSE;
713 chi21=CombiDoubleMathiesonFit(c);
714 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
715 // Float_t prob = TMath::Prob(chi2,ndf);
716 // prob2->Fill(prob);
717 // chi2_2->Fill(chi21);
718 fprintf(stderr," chi2 %f\n",chi21);
719 if (chi21<10) Split(c);
720 } else if (accepted[1]) {
725 chi22=CombiDoubleMathiesonFit(c);
726 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
727 // Float_t prob = TMath::Prob(chi2,ndf);
728 // prob2->Fill(prob);
729 // chi2_2->Fill(chi22);
730 fprintf(stderr," chi2 %f\n",chi22);
731 if (chi22<10) Split(c);
734 if (chi21 > 10 && chi22 > 10) {
735 //We keep only the combination found (X->cathode 2, Y->cathode 1)
736 for (Int_t ico=0; ico<2; ico++) {
738 AliMUONRawCluster cnew;
740 for (cath=0; cath<2; cath++) {
741 cnew.fX[cath]=Float_t(xm[ico][1]);
742 cnew.fY[cath]=Float_t(ym[ico][0]);
743 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
744 for (i=0; i<fMul[cath]; i++) {
745 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
746 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
748 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
749 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
750 FillCluster(&cnew,cath);
752 cnew.fClusterType=cnew.PhysicsContribution();
759 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
760 // (4) At least three local maxima on cathode 1 or on cathode 2
761 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
762 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
764 Int_t param = fNLocal[0]*fNLocal[1];
767 Float_t ** xm = new Float_t * [param];
768 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
769 Float_t ** ym = new Float_t * [param];
770 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
771 Int_t ** ixm = new Int_t * [param];
772 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
773 Int_t ** iym = new Int_t * [param];
774 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
777 Float_t dpx, dpy, dx, dy;
780 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
781 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
782 xm[ico][0]=fX[fIndLocal[im1][0]][0];
783 ym[ico][0]=fY[fIndLocal[im1][0]][0];
784 xm[ico][1]=fX[fIndLocal[im2][1]][1];
785 ym[ico][1]=fY[fIndLocal[im2][1]][1];
787 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
788 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
789 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
790 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
797 fprintf(stderr,"nIco %d\n",nIco);
798 for (ico=0; ico<nIco; ico++) {
799 fprintf(stderr,"ico = %d\n",ico);
800 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
801 dpx=fSeg[0]->Dpx(isec)/2.;
802 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
803 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
804 dpy=fSeg[1]->Dpy(isec)/2.;
805 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
807 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
808 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
809 if ((dx <= dpx) && (dy <= dpy)) {
810 fprintf(stderr,"ok\n");
812 AliMUONRawCluster cnew;
813 for (cath=0; cath<2; cath++) {
814 cnew.fX[cath]=Float_t(xm[ico][1]);
815 cnew.fY[cath]=Float_t(ym[ico][0]);
816 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
817 for (i=0; i<fMul[cath]; i++) {
818 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
819 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
821 FillCluster(&cnew,cath);
823 cnew.fClusterType=cnew.PhysicsContribution();
835 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
837 // Find all local maxima of a cluster
838 printf("\n Find Local maxima !");
842 Int_t cath, cath1; // loops over cathodes
843 Int_t i; // loops over digits
844 Int_t j; // loops over cathodes
848 // counters for number of local maxima
849 fNLocal[0]=fNLocal[1]=0;
850 // flags digits as local maximum
851 Bool_t isLocal[100][2];
852 for (i=0; i<100;i++) {
853 isLocal[i][0]=isLocal[i][1]=kFALSE;
855 // number of next neighbours and arrays to store them
858 // loop over cathodes
859 for (cath=0; cath<2; cath++) {
860 // loop over cluster digits
861 for (i=0; i<fMul[cath]; i++) {
862 // get neighbours for that digit and assume that it is local maximum
863 fSeg[cath]->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
864 isLocal[i][cath]=kTRUE;
865 Int_t isec= fSeg[cath]->Sector(fIx[i][cath], fIy[i][cath]);
866 Float_t a0 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
867 // loop over next neighbours, if at least one neighbour has higher charger assumption
868 // digit is not local maximum
869 for (j=0; j<nn; j++) {
870 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
871 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
872 isec=fSeg[cath]->Sector(x[j], y[j]);
873 Float_t a1 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
874 if (digt->fSignal/a1 > fQ[i][cath]/a0) {
875 isLocal[i][cath]=kFALSE;
878 // handle special case of neighbouring pads with equal signal
879 } else if (digt->fSignal == fQ[i][cath]) {
880 if (fNLocal[cath]>0) {
881 for (Int_t k=0; k<fNLocal[cath]; k++) {
882 if (x[j]==fIx[fIndLocal[k][cath]][cath]
883 && y[j]==fIy[fIndLocal[k][cath]][cath])
885 isLocal[i][cath]=kFALSE;
887 } // loop over local maxima
888 } // are there already local maxima
890 } // loop over next neighbours
891 if (isLocal[i][cath]) {
892 fIndLocal[fNLocal[cath]][cath]=i;
895 } // loop over all digits
896 } // loop over cathodes
898 printf("\n Found %d %d %d %d local Maxima\n",
899 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
900 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
901 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
906 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
907 Int_t iback=fNLocal[0];
909 // Two local maxima on cathode 2 and one maximum on cathode 1
910 // Look for local maxima considering up and down neighbours on the 1st cathode only
912 // Loop over cluster digits
916 for (i=0; i<fMul[cath]; i++) {
917 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
918 dpy=fSeg[cath]->Dpy(isec);
919 dpx=fSeg[cath]->Dpx(isec);
920 if (isLocal[i][cath]) continue;
921 // Pad position should be consistent with position of local maxima on the opposite cathode
922 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
923 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
926 // get neighbours for that digit and assume that it is local maximum
927 isLocal[i][cath]=kTRUE;
928 // compare signal to that on the two neighbours on the left and on the right
929 // iNN counts the number of neighbours with signal, it should be 1 or 2
933 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpy);
939 ix = fSeg[cath]->Ix();
940 iy = fSeg[cath]->Iy();
941 // skip the current pad
942 if (iy == fIy[i][cath]) continue;
944 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
946 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
947 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
949 } // Loop over pad neighbours in y
950 if (isLocal[i][cath] && iNN>0) {
951 fIndLocal[fNLocal[cath]][cath]=i;
954 } // loop over all digits
955 // if one additional maximum has been found we are happy
956 // if more maxima have been found restore the previous situation
958 "\n New search gives %d local maxima for cathode 1 \n",
961 " %d local maxima for cathode 2 \n",
963 if (fNLocal[cath]>2) {
967 } // 1,2 local maxima
969 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
970 Int_t iback=fNLocal[1];
972 // Two local maxima on cathode 1 and one maximum on cathode 2
973 // Look for local maxima considering left and right neighbours on the 2nd cathode only
977 // Loop over cluster digits
978 for (i=0; i<fMul[cath]; i++) {
979 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
980 dpx=fSeg[cath]->Dpx(isec);
981 dpy=fSeg[cath]->Dpy(isec);
982 if (isLocal[i][cath]) continue;
983 // Pad position should be consistent with position of local maxima on the opposite cathode
984 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
985 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.))
988 // get neighbours for that digit and assume that it is local maximum
989 isLocal[i][cath]=kTRUE;
990 // compare signal to that on the two neighbours on the left and on the right
992 // iNN counts the number of neighbours with signal, it should be 1 or 2
995 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpx);
1001 ix = fSeg[cath]->Ix();
1002 iy = fSeg[cath]->Iy();
1004 // skip the current pad
1005 if (ix == fIx[i][cath]) continue;
1007 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
1009 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
1010 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1012 } // Loop over pad neighbours in x
1013 if (isLocal[i][cath] && iNN>0) {
1014 fIndLocal[fNLocal[cath]][cath]=i;
1017 } // loop over all digits
1018 // if one additional maximum has been found we are happy
1019 // if more maxima have been found restore the previous situation
1020 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
1021 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
1022 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
1023 if (fNLocal[cath]>2) {
1024 fNLocal[cath]=iback;
1026 } // 2,1 local maxima
1030 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
1033 // Completes cluster information starting from list of digits
1040 c->fPeakSignal[cath]=c->fPeakSignal[0];
1042 c->fPeakSignal[cath]=0;
1052 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1053 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1055 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1056 ix=dig->fPadX+c->fOffsetMap[i][cath];
1058 Int_t q=dig->fSignal;
1059 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1060 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1061 if (dig->fPhysics >= dig->fSignal) {
1062 c->fPhysicsMap[i]=2;
1063 } else if (dig->fPhysics == 0) {
1064 c->fPhysicsMap[i]=0;
1065 } else c->fPhysicsMap[i]=1;
1068 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1069 // peak signal and track list
1070 if (q>c->fPeakSignal[cath]) {
1071 c->fPeakSignal[cath]=q;
1072 c->fTracks[0]=dig->fHit;
1073 c->fTracks[1]=dig->fTracks[0];
1074 c->fTracks[2]=dig->fTracks[1];
1075 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1079 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1084 } // loop over digits
1085 // fprintf(stderr," fin du cluster c\n");
1089 c->fX[cath]/=c->fQ[cath];
1090 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1091 c->fY[cath]/=c->fQ[cath];
1093 // apply correction to the coordinate along the anode wire
1097 fSeg[cath]->GetPadI(x, y, fZPlane, ix, iy);
1098 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1099 Int_t isec=fSeg[cath]->Sector(ix,iy);
1100 TF1* cogCorr = fSeg[cath]->CorrFunc(isec-1);
1103 Float_t yOnPad=(c->fY[cath]-y)/fSeg[cath]->Dpy(isec);
1104 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1109 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1112 // Completes cluster information starting from list of digits
1122 Float_t xpad, ypad, zpad;
1125 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1127 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1129 GetPadC(dig->fPadX,dig->fPadY,xpad,ypad, zpad);
1130 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1131 dx = xpad - c->fX[0];
1132 dy = ypad - c->fY[0];
1133 dr = TMath::Sqrt(dx*dx+dy*dy);
1137 fprintf(stderr," dr %f\n",dr);
1138 Int_t q=dig->fSignal;
1139 if (dig->fPhysics >= dig->fSignal) {
1140 c->fPhysicsMap[i]=2;
1141 } else if (dig->fPhysics == 0) {
1142 c->fPhysicsMap[i]=0;
1143 } else c->fPhysicsMap[i]=1;
1144 c->fPeakSignal[cath]=q;
1145 c->fTracks[0]=dig->fHit;
1146 c->fTracks[1]=dig->fTracks[0];
1147 c->fTracks[2]=dig->fTracks[1];
1148 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1151 } // loop over digits
1153 // apply correction to the coordinate along the anode wire
1154 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1157 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1161 // Find a super cluster on both cathodes
1164 // Add i,j as element of the cluster
1167 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1168 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1169 Int_t q=dig->fSignal;
1170 Int_t theX=dig->fPadX;
1171 Int_t theY=dig->fPadY;
1173 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1174 c.fPeakSignal[cath]=q;
1175 c.fTracks[0]=dig->fHit;
1176 c.fTracks[1]=dig->fTracks[0];
1177 c.fTracks[2]=dig->fTracks[1];
1181 // Make sure that list of digits is ordered
1183 Int_t mu=c.fMultiplicity[cath];
1184 c.fIndexMap[mu][cath]=idx;
1186 if (dig->fPhysics >= dig->fSignal) {
1187 c.fPhysicsMap[mu]=2;
1188 } else if (dig->fPhysics == 0) {
1189 c.fPhysicsMap[mu]=0;
1190 } else c.fPhysicsMap[mu]=1;
1194 for (Int_t ind = mu-1; ind >= 0; ind--) {
1195 Int_t ist=(c.fIndexMap)[ind][cath];
1196 Int_t ql=fInput->Digit(cath, ist)->fSignal;
1197 Int_t ix=fInput->Digit(cath, ist)->fPadX;
1198 Int_t iy=fInput->Digit(cath, ist)->fPadY;
1200 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1201 c.fIndexMap[ind][cath]=idx;
1202 c.fIndexMap[ind+1][cath]=ist;
1210 c.fMultiplicity[cath]++;
1211 if (c.fMultiplicity[cath] >= 50 ) {
1212 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1213 c.fMultiplicity[cath]=49;
1216 // Prepare center of gravity calculation
1218 fSeg[cath]->GetPadC(i, j, x, y, z);
1224 // Flag hit as "taken"
1225 fHitMap[cath]->FlagHit(i,j);
1227 // Now look recursively for all neighbours and pad hit on opposite cathode
1229 // Loop over neighbours
1233 Int_t xList[10], yList[10];
1234 fSeg[cath]->Neighbours(i,j,&nn,xList,yList);
1235 for (Int_t in=0; in<nn; in++) {
1239 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) {
1240 // printf("\n Neighbours %d %d %d", cath, ix, iy);
1241 FindCluster(ix, iy, cath, c);
1246 Int_t iXopp[50], iYopp[50];
1248 // Neighbours on opposite cathode
1249 // Take into account that several pads can overlap with the present pad
1250 Int_t isec=fSeg[cath]->Sector(i,j);
1256 dx = (fSeg[cath]->Dpx(isec))/2.;
1261 dy = (fSeg[cath]->Dpy(isec))/2;
1263 // loop over pad neighbours on opposite cathode
1264 for (fSeg[iop]->FirstPad(x, y, fZPlane, dx, dy);
1265 fSeg[iop]->MorePads();
1266 fSeg[iop]->NextPad())
1269 ix = fSeg[iop]->Ix(); iy = fSeg[iop]->Iy();
1270 // printf("\n ix, iy: %f %f %f %d %d %d", x,y,z,ix, iy, fSector);
1271 if (fHitMap[iop]->TestHit(ix,iy)==kUnused){
1274 // printf("\n Opposite %d %d %d", iop, ix, iy);
1277 } // Loop over pad neighbours
1278 // This had to go outside the loop since recursive calls inside the iterator are not possible
1281 for (jopp=0; jopp<nOpp; jopp++) {
1282 if (fHitMap[iop]->TestHit(iXopp[jopp],iYopp[jopp]) == kUnused)
1283 FindCluster(iXopp[jopp], iYopp[jopp], iop, c);
1287 //_____________________________________________________________________________
1289 void AliMUONClusterFinderVS::FindRawClusters()
1292 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1293 // fills the tree with raw clusters
1296 // Return if no input datad available
1297 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1299 fSeg[0] = fInput->Segmentation(0);
1300 fSeg[1] = fInput->Segmentation(1);
1302 fHitMap[0] = new AliMUONHitMapA1(fSeg[0], fInput->Digits(0));
1303 fHitMap[1] = new AliMUONHitMapA1(fSeg[1], fInput->Digits(1));
1311 fHitMap[0]->FillHits();
1312 fHitMap[1]->FillHits();
1314 // Outer Loop over Cathodes
1315 for (cath=0; cath<2; cath++) {
1316 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1317 dig = fInput->Digit(cath, ndig);
1320 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1324 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1325 AliMUONRawCluster c;
1326 c.fMultiplicity[0]=0;
1327 c.fMultiplicity[1]=0;
1328 c.fPeakSignal[cath]=dig->fSignal;
1329 c.fTracks[0]=dig->fHit;
1330 c.fTracks[1]=dig->fTracks[0];
1331 c.fTracks[2]=dig->fTracks[1];
1332 // tag the beginning of cluster list in a raw cluster
1335 fSeg[cath]->GetPadC(i,j,xcu, ycu, fZPlane);
1336 fSector= fSeg[cath]->Sector(i,j)/100;
1337 // printf("\n New Seed %d %d ", i,j);
1339 FindCluster(i,j,cath,c);
1340 // ^^^^^^^^^^^^^^^^^^^^^^^^
1341 // center of gravity
1343 c.fX[0]=fSeg[0]->GetAnod(c.fX[0]);
1346 c.fX[1]=fSeg[0]->GetAnod(c.fX[1]);
1352 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",
1353 c.fMultiplicity[0],c.fX[0],c.fY[0]);
1354 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",
1355 c.fMultiplicity[1],c.fX[1],c.fY[1]);
1357 // Analyse cluster and decluster if necessary
1360 c.fNcluster[1]=fNRawClusters;
1361 c.fClusterType=c.PhysicsContribution();
1368 // reset Cluster object
1369 { // begin local scope
1370 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1371 } // end local scope
1373 { // begin local scope
1374 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1375 } // end local scope
1377 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1381 } // end loop cathodes
1386 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1388 // Performs a single Mathieson fit on one cathode
1390 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1392 clusterInput.Fitter()->SetFCN(fcnS1);
1393 clusterInput.Fitter()->mninit(2,10,7);
1394 Double_t arglist[20];
1397 // Set starting values
1398 static Double_t vstart[2];
1403 // lower and upper limits
1404 static Double_t lower[2], upper[2];
1406 fSeg[cath]->GetPadI(c->fX[cath], c->fY[cath], fZPlane, ix, iy);
1407 Int_t isec=fSeg[cath]->Sector(ix, iy);
1408 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec)/2;
1409 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec)/2;
1411 upper[0]=lower[0]+fSeg[cath]->Dpx(isec);
1412 upper[1]=lower[1]+fSeg[cath]->Dpy(isec);
1415 static Double_t step[2]={0.0005, 0.0005};
1417 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1418 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1419 // ready for minimisation
1420 clusterInput.Fitter()->SetPrintLevel(1);
1421 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1425 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1426 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1427 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1428 Double_t fmin, fedm, errdef;
1429 Int_t npari, nparx, istat;
1431 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1435 // Get fitted parameters
1436 Double_t xrec, yrec;
1438 Double_t epxz, b1, b2;
1440 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1441 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1447 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1449 // Perform combined Mathieson fit on both cathode planes
1451 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1452 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1453 clusterInput.Fitter()->mninit(2,10,7);
1454 Double_t arglist[20];
1457 static Double_t vstart[2];
1458 vstart[0]=fXInit[0];
1459 vstart[1]=fYInit[0];
1462 // lower and upper limits
1463 static Float_t lower[2], upper[2];
1465 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1466 isec=fSeg[0]->Sector(ix, iy);
1467 Float_t dpy=fSeg[0]->Dpy(isec);
1468 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1469 isec=fSeg[1]->Sector(ix, iy);
1470 Float_t dpx=fSeg[1]->Dpx(isec);
1473 Float_t xdum, ydum, zdum;
1475 // Find save upper and lower limits
1479 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1480 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1482 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1483 fSeg[1]->GetPadC(ix,iy, upper[0], ydum, zdum);
1484 if (icount ==0) lower[0]=upper[0];
1488 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1491 printf("\n single y %f %f", fXInit[0], fYInit[0]);
1493 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1494 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1496 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1497 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1498 if (icount ==0) lower[1]=upper[1];
1500 printf("\n upper lower %d %f %f", icount, upper[1], lower[1]);
1503 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1506 static Double_t step[2]={0.00001, 0.0001};
1508 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1509 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1510 // ready for minimisation
1511 clusterInput.Fitter()->SetPrintLevel(1);
1512 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1516 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1517 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1518 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1519 Double_t fmin, fedm, errdef;
1520 Int_t npari, nparx, istat;
1522 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1526 // Get fitted parameters
1527 Double_t xrec, yrec;
1529 Double_t epxz, b1, b2;
1531 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1532 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1538 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1540 // Performs a double Mathieson fit on one cathode
1544 // Initialise global variables for fit
1545 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1546 clusterInput.Fitter()->SetFCN(fcnS2);
1547 clusterInput.Fitter()->mninit(5,10,7);
1548 Double_t arglist[20];
1551 // Set starting values
1552 static Double_t vstart[5];
1553 vstart[0]=fX[fIndLocal[0][cath]][cath];
1554 vstart[1]=fY[fIndLocal[0][cath]][cath];
1555 vstart[2]=fX[fIndLocal[1][cath]][cath];
1556 vstart[3]=fY[fIndLocal[1][cath]][cath];
1557 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1558 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1559 // lower and upper limits
1560 static Float_t lower[5], upper[5];
1561 Int_t isec=fSeg[cath]->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1562 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec);
1563 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec);
1565 upper[0]=lower[0]+2.*fSeg[cath]->Dpx(isec);
1566 upper[1]=lower[1]+2.*fSeg[cath]->Dpy(isec);
1568 isec=fSeg[cath]->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1569 lower[2]=vstart[2]-fSeg[cath]->Dpx(isec)/2;
1570 lower[3]=vstart[3]-fSeg[cath]->Dpy(isec)/2;
1572 upper[2]=lower[2]+fSeg[cath]->Dpx(isec);
1573 upper[3]=lower[3]+fSeg[cath]->Dpy(isec);
1578 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1580 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1581 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1582 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1583 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1584 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1585 // ready for minimisation
1586 clusterInput.Fitter()->SetPrintLevel(-1);
1587 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1591 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1592 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1593 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1594 // Get fitted parameters
1595 Double_t xrec[2], yrec[2], qfrac;
1597 Double_t epxz, b1, b2;
1599 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1600 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1601 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1602 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1603 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1605 Double_t fmin, fedm, errdef;
1606 Int_t npari, nparx, istat;
1608 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1613 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1616 // Perform combined double Mathieson fit on both cathode planes
1618 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1619 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1620 clusterInput.Fitter()->mninit(6,10,7);
1621 Double_t arglist[20];
1624 // Set starting values
1625 static Double_t vstart[6];
1626 vstart[0]=fXInit[0];
1627 vstart[1]=fYInit[0];
1628 vstart[2]=fXInit[1];
1629 vstart[3]=fYInit[1];
1630 vstart[4]=fQrInit[0];
1631 vstart[5]=fQrInit[1];
1632 // lower and upper limits
1633 static Float_t lower[6], upper[6];
1637 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1638 isec=fSeg[1]->Sector(ix, iy);
1639 dpx=fSeg[1]->Dpx(isec);
1641 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1642 isec=fSeg[0]->Sector(ix, iy);
1643 dpy=fSeg[0]->Dpy(isec);
1647 Float_t xdum, ydum, zdum;
1648 // printf("\n Cluster Finder: %f %f %f %f ", fXInit[0], fXInit[1],fYInit[0], fYInit[1] );
1650 // Find save upper and lower limits
1653 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1654 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1656 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1657 fSeg[1]->GetPadC(ix,iy,upper[0],ydum,zdum);
1658 if (icount ==0) lower[0]=upper[0];
1661 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1664 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1665 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1667 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1668 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1669 if (icount ==0) lower[1]=upper[1];
1672 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1674 fSeg[1]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1675 isec=fSeg[1]->Sector(ix, iy);
1676 dpx=fSeg[1]->Dpx(isec);
1677 fSeg[0]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1678 isec=fSeg[0]->Sector(ix, iy);
1679 dpy=fSeg[0]->Dpy(isec);
1682 // Find save upper and lower limits
1686 for (fSeg[1]->FirstPad(fXInit[1], fYInit[1], fZPlane, dpx, 0);
1687 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1689 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1690 fSeg[1]->GetPadC(ix,iy,upper[2],ydum,zdum);
1691 if (icount ==0) lower[2]=upper[2];
1694 if (lower[2]>upper[2]) {xdum=lower[2]; lower[2]=upper[2]; upper[2]=xdum;}
1698 for (fSeg[0]->FirstPad(fXInit[1], fYInit[1], fZPlane, 0, dpy);
1699 fSeg[0]-> MorePads(); fSeg[0]->NextPad())
1701 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1702 fSeg[0]->GetPadC(ix,iy,xdum,upper[3],zdum);
1703 if (icount ==0) lower[3]=upper[3];
1706 if (lower[3]>upper[3]) {xdum=lower[3]; lower[3]=upper[3]; upper[3]=xdum;}
1714 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1715 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1716 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1717 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1718 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1719 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1720 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1721 // ready for minimisation
1722 clusterInput.Fitter()->SetPrintLevel(-1);
1723 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1727 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1728 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1729 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1730 // Get fitted parameters
1732 Double_t epxz, b1, b2;
1734 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1735 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1736 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1737 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1738 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1739 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1741 Double_t fmin, fedm, errdef;
1742 Int_t npari, nparx, istat;
1744 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1752 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1755 // One cluster for each maximum
1758 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1759 for (j=0; j<2; j++) {
1760 AliMUONRawCluster cnew;
1761 for (cath=0; cath<2; cath++) {
1762 cnew.fChi2[cath]=fChi2[0];
1765 cnew.fNcluster[0]=-1;
1766 cnew.fNcluster[1]=fNRawClusters;
1768 cnew.fNcluster[0]=fNPeaks;
1769 cnew.fNcluster[1]=0;
1771 cnew.fMultiplicity[cath]=0;
1772 cnew.fX[cath]=Float_t(fXFit[j]);
1773 cnew.fY[cath]=Float_t(fYFit[j]);
1774 cnew.fZ[cath]=fZPlane;
1776 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
1778 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
1780 fSeg[cath]->SetHit(fXFit[j],fYFit[j],fZPlane);
1781 for (i=0; i<fMul[cath]; i++) {
1782 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1783 c->fIndexMap[i][cath];
1784 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
1785 Float_t q1=fInput->Response()->IntXY(fSeg[cath]);
1786 cnew.fContMap[i][cath]
1787 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1788 cnew.fMultiplicity[cath]++;
1790 FillCluster(&cnew,0,cath);
1793 cnew.fClusterType=cnew.PhysicsContribution();
1794 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1801 // Minimisation functions
1803 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1805 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1812 for (i=0; i<clusterInput.Nmul(0); i++) {
1813 Float_t q0=clusterInput.Charge(i,0);
1814 Float_t q1=clusterInput.DiscrChargeS1(i,par);
1823 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1825 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1832 for (cath=0; cath<2; cath++) {
1833 for (i=0; i<clusterInput.Nmul(cath); i++) {
1834 Float_t q0=clusterInput.Charge(i,cath);
1835 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
1846 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1848 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1855 for (i=0; i<clusterInput.Nmul(0); i++) {
1857 Float_t q0=clusterInput.Charge(i,0);
1858 Float_t q1=clusterInput.DiscrChargeS2(i,par);
1868 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1870 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1876 for (cath=0; cath<2; cath++) {
1877 for (i=0; i<clusterInput.Nmul(cath); i++) {
1878 Float_t q0=clusterInput.Charge(i,cath);
1879 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
1889 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1892 // Add a raw cluster copy to the list
1894 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1895 pMUON->AddRawCluster(fInput->Chamber(),c);
1897 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1900 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
1901 if (fTrack[0]==-1 || fTrack[1]==-1) {
1903 } else if (t==fTrack[0] || t==fTrack[1]) {
1910 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1911 ::operator = (const AliMUONClusterFinderVS& rhs)
1913 // Dummy assignment operator