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.13 2000/10/23 13:38:23 morsch
18 Set correct z-coordinate when cluster is split.
20 Revision 1.12 2000/10/18 11:42:06 morsch
21 - AliMUONRawCluster contains z-position.
22 - Some clean-up of useless print statements during initialisations.
24 Revision 1.11 2000/10/06 09:04:05 morsch
25 - Dummy z-arguments in GetPadI, SetHit, FirstPad replaced by real z-coordinate
26 to make code work with slat chambers (AM)
27 - Replace GetPadI calls with unchecked x,y coordinates by pad iterator calls wherever possible.
29 Revision 1.10 2000/10/03 13:51:57 egangler
30 Removal of useless dependencies via forward declarations
32 Revision 1.9 2000/10/02 16:58:29 egangler
33 Cleaning of the code :
36 -> some useless includes removed or replaced by "class" statement
38 Revision 1.8 2000/07/03 11:54:57 morsch
39 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
40 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
42 Revision 1.7 2000/06/28 15:16:35 morsch
43 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
44 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
45 framework. The changes should have no side effects (mostly dummy arguments).
46 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
47 of chambers with overlapping modules (MakePadHits, Disintegration).
49 Revision 1.6 2000/06/28 12:19:18 morsch
50 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
51 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
52 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
53 It requires two cathode planes. Small modifications in the code will make it usable for
54 one cathode plane and, hence, more general (for test beam data).
55 AliMUONClusterFinder is now obsolete.
57 Revision 1.5 2000/06/28 08:06:10 morsch
58 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
59 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
60 It also naturally takes care of the TMinuit instance.
62 Revision 1.4 2000/06/27 16:18:47 gosset
63 Finally correct implementation of xm, ym, ixm, iym sizes
64 when at least three local maxima on cathode 1 or on cathode 2
66 Revision 1.3 2000/06/22 14:02:45 morsch
67 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
68 Some HP scope problems corrected (PH)
70 Revision 1.2 2000/06/15 07:58:48 morsch
71 Code from MUON-dev joined
73 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
74 Most coding rule violations corrected.
76 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
77 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
78 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
79 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
80 - For clusters with more than 2 maxima on one of the cathode planes all valid
81 combinations of maxima on the two cathodes are preserved. The position of the maxima is
82 taken as the hit position.
83 - New FillCluster method with 2 arguments to find tracks associated to the clusters
84 defined above added. (Method destinction by argument list not very elegant in this case,
85 should be revides (A.M.)
86 - Bug in if-statement to handle maximum 1 maximum per plane corrected
87 - Two cluster per cathode but only 1 combination valid is handled.
88 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
92 #include "AliMUONClusterFinderVS.h"
93 #include "AliMUONDigit.h"
94 #include "AliMUONRawCluster.h"
95 #include "AliSegmentation.h"
96 #include "AliMUONResponse.h"
97 #include "AliMUONClusterInput.h"
98 #include "AliMUONHitMapA1.h"
107 #include <TPostScript.h>
112 #include <iostream.h>
114 //_____________________________________________________________________
115 // This function is minimized in the double-Mathieson fit
116 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
117 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
118 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
119 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
121 ClassImp(AliMUONClusterFinderVS)
123 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
125 // Default constructor
126 fInput=AliMUONClusterInput::Instance();
129 fTrack[0]=fTrack[1]=-1;
132 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
133 const AliMUONClusterFinderVS & clusterFinder)
135 // Dummy copy Constructor
139 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
141 // Decluster by local maxima
142 SplitByLocalMaxima(cluster);
145 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
147 // Split complex cluster by local maxima
150 fInput->SetCluster(c);
152 fMul[0]=c->fMultiplicity[0];
153 fMul[1]=c->fMultiplicity[1];
156 // dump digit information into arrays
161 for (cath=0; cath<2; cath++) {
163 for (i=0; i<fMul[cath]; i++)
166 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
168 fIx[i][cath]= fDig[i][cath]->fPadX;
169 fIy[i][cath]= fDig[i][cath]->fPadY;
171 fQ[i][cath] = fDig[i][cath]->fSignal;
172 // pad centre coordinates
174 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], fZ[i][cath]);
175 } // loop over cluster digits
176 } // loop over cathodes
182 // Initialise and perform mathieson fits
183 Float_t chi2, oldchi2;
184 // ++++++++++++++++++*************+++++++++++++++++++++
185 // (1) No more than one local maximum per cathode plane
186 // +++++++++++++++++++++++++++++++*************++++++++
187 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
188 (fNLocal[0]==0 && fNLocal[1]==1)) {
190 // Perform combined single Mathieson fit
191 // Initial values for coordinates (x,y)
193 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
194 if (fNLocal[0]==1 && fNLocal[1]==1) {
197 // One local maximum on cathode 1 (X,Y->cathode 1)
198 } else if (fNLocal[0]==1) {
201 // One local maximum on cathode 2 (X,Y->cathode 2)
206 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
207 chi2=CombiSingleMathiesonFit(c);
208 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
209 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
210 // prob1->Fill(prob);
211 // chi2_1->Fill(chi2);
213 fprintf(stderr," chi2 %f ",chi2);
222 c->fX[0]=fSeg[0]->GetAnod(c->fX[0]);
223 c->fX[1]=fSeg[1]->GetAnod(c->fX[1]);
225 // If reasonable chi^2 add result to the list of rawclusters
229 // If not try combined double Mathieson Fit
231 fprintf(stderr," MAUVAIS CHI2 !!!\n");
232 if (fNLocal[0]==1 && fNLocal[1]==1) {
233 fXInit[0]=fX[fIndLocal[0][1]][1];
234 fYInit[0]=fY[fIndLocal[0][0]][0];
235 fXInit[1]=fX[fIndLocal[0][1]][1];
236 fYInit[1]=fY[fIndLocal[0][0]][0];
237 } else if (fNLocal[0]==1) {
238 fXInit[0]=fX[fIndLocal[0][0]][0];
239 fYInit[0]=fY[fIndLocal[0][0]][0];
240 fXInit[1]=fX[fIndLocal[0][0]][0];
241 fYInit[1]=fY[fIndLocal[0][0]][0];
243 fXInit[0]=fX[fIndLocal[0][1]][1];
244 fYInit[0]=fY[fIndLocal[0][1]][1];
245 fXInit[1]=fX[fIndLocal[0][1]][1];
246 fYInit[1]=fY[fIndLocal[0][1]][1];
249 // Initial value for charge ratios
252 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
253 chi2=CombiDoubleMathiesonFit(c);
254 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
255 // Float_t prob = TMath::Prob(chi2,ndf);
256 // prob2->Fill(prob);
257 // chi2_2->Fill(chi2);
259 // Was this any better ??
260 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
261 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
262 fprintf(stderr," Split\n");
263 // Split cluster into two according to fit result
266 fprintf(stderr," Don't Split\n");
272 // +++++++++++++++++++++++++++++++++++++++
273 // (2) Two local maxima per cathode plane
274 // +++++++++++++++++++++++++++++++++++++++
275 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
277 // Let's look for ghosts first
279 Float_t xm[4][2], ym[4][2];
280 Float_t dpx, dpy, dx, dy;
281 Int_t ixm[4][2], iym[4][2];
282 Int_t isec, im1, im2, ico;
284 // Form the 2x2 combinations
285 // 0-0, 0-1, 1-0, 1-1
287 for (im1=0; im1<2; im1++) {
288 for (im2=0; im2<2; im2++) {
289 xm[ico][0]=fX[fIndLocal[im1][0]][0];
290 ym[ico][0]=fY[fIndLocal[im1][0]][0];
291 xm[ico][1]=fX[fIndLocal[im2][1]][1];
292 ym[ico][1]=fY[fIndLocal[im2][1]][1];
294 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
295 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
296 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
297 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
301 // ico = 0 : first local maximum on cathodes 1 and 2
302 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
303 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
304 // ico = 3 : second local maximum on cathodes 1 and 2
306 // Analyse the combinations and keep those that are possible !
307 // For each combination check consistency in x and y
312 for (ico=0; ico<4; ico++) {
313 accepted[ico]=kFALSE;
314 // cathode one: x-coordinate
315 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
316 dpx=fSeg[0]->Dpx(isec)/2.;
317 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
318 // cathode two: y-coordinate
319 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
320 dpy=fSeg[1]->Dpy(isec)/2.;
321 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
322 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
323 if ((dx <= dpx) && (dy <= dpy)) {
329 accepted[ico]=kFALSE;
334 fprintf(stderr,"\n iacc=2: No problem ! \n");
335 } else if (iacc==4) {
336 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
337 } else if (iacc==0) {
338 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
341 // Initial value for charge ratios
342 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
343 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
344 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
345 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
347 // ******* iacc = 0 *******
348 // No combinations found between the 2 cathodes
349 // We keep the center of gravity of the cluster
354 // ******* iacc = 1 *******
355 // Only one combination found between the 2 cathodes
358 // Initial values for the 2 maxima (x,y)
360 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
361 // 1 maximum is initialised with the other maximum of the first cathode
363 fprintf(stderr,"ico=0\n");
368 } else if (accepted[1]){
369 fprintf(stderr,"ico=1\n");
374 } else if (accepted[2]){
375 fprintf(stderr,"ico=2\n");
380 } else if (accepted[3]){
381 fprintf(stderr,"ico=3\n");
387 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
388 chi2=CombiDoubleMathiesonFit(c);
389 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
390 // Float_t prob = TMath::Prob(chi2,ndf);
391 // prob2->Fill(prob);
392 // chi2_2->Fill(chi2);
393 fprintf(stderr," chi2 %f\n",chi2);
395 // If reasonable chi^2 add result to the list of rawclusters
400 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
401 // 1 maximum is initialised with the other maximum of the second cathode
403 fprintf(stderr,"ico=0\n");
408 } else if (accepted[1]){
409 fprintf(stderr,"ico=1\n");
414 } else if (accepted[2]){
415 fprintf(stderr,"ico=2\n");
420 } else if (accepted[3]){
421 fprintf(stderr,"ico=3\n");
427 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
428 chi2=CombiDoubleMathiesonFit(c);
429 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
430 // Float_t prob = TMath::Prob(chi2,ndf);
431 // prob2->Fill(prob);
432 // chi2_2->Fill(chi2);
433 fprintf(stderr," chi2 %f\n",chi2);
435 // If reasonable chi^2 add result to the list of rawclusters
439 //We keep only the combination found (X->cathode 2, Y->cathode 1)
440 for (Int_t ico=0; ico<2; ico++) {
442 AliMUONRawCluster cnew;
444 for (cath=0; cath<2; cath++) {
445 cnew.fX[cath]=Float_t(xm[ico][1]);
446 cnew.fY[cath]=Float_t(ym[ico][0]);
447 cnew.fZ[cath]=fZPlane;
449 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
450 for (i=0; i<fMul[cath]; i++) {
451 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
452 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
454 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
455 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
456 FillCluster(&cnew,cath);
458 cnew.fClusterType=cnew.PhysicsContribution();
467 // ******* iacc = 2 *******
468 // Two combinations found between the 2 cathodes
471 // Was the same maximum taken twice
472 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
473 fprintf(stderr,"\n Maximum taken twice !!!\n");
475 // Have a try !! with that
476 if (accepted[0]&&accepted[3]) {
487 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
488 chi2=CombiDoubleMathiesonFit(c);
489 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
490 // Float_t prob = TMath::Prob(chi2,ndf);
491 // prob2->Fill(prob);
492 // chi2_2->Fill(chi2);
496 // No ghosts ! No Problems ! - Perform one fit only !
497 if (accepted[0]&&accepted[3]) {
508 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
509 chi2=CombiDoubleMathiesonFit(c);
510 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
511 // Float_t prob = TMath::Prob(chi2,ndf);
512 // prob2->Fill(prob);
513 // chi2_2->Fill(chi2);
514 fprintf(stderr," chi2 %f\n",chi2);
518 // ******* iacc = 4 *******
519 // Four combinations found between the 2 cathodes
521 } else if (iacc==4) {
522 // Perform fits for the two possibilities !!
527 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
528 chi2=CombiDoubleMathiesonFit(c);
529 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
530 // Float_t prob = TMath::Prob(chi2,ndf);
531 // prob2->Fill(prob);
532 // chi2_2->Fill(chi2);
533 fprintf(stderr," chi2 %f\n",chi2);
539 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
540 chi2=CombiDoubleMathiesonFit(c);
541 // ndf = fgNbins[0]+fgNbins[1]-6;
542 // prob = TMath::Prob(chi2,ndf);
543 // prob2->Fill(prob);
544 // chi2_2->Fill(chi2);
545 fprintf(stderr," chi2 %f\n",chi2);
549 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
550 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
551 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
552 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
554 Float_t xm[4][2], ym[4][2];
555 Float_t dpx, dpy, dx, dy;
556 Int_t ixm[4][2], iym[4][2];
557 Int_t isec, im1, ico;
559 // Form the 2x2 combinations
560 // 0-0, 0-1, 1-0, 1-1
562 for (im1=0; im1<2; im1++) {
563 xm[ico][0]=fX[fIndLocal[im1][0]][0];
564 ym[ico][0]=fY[fIndLocal[im1][0]][0];
565 xm[ico][1]=fX[fIndLocal[0][1]][1];
566 ym[ico][1]=fY[fIndLocal[0][1]][1];
568 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
569 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
570 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
571 iym[ico][1]=fIy[fIndLocal[0][1]][1];
574 // ico = 0 : first local maximum on cathodes 1 and 2
575 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
577 // Analyse the combinations and keep those that are possible !
578 // For each combination check consistency in x and y
583 for (ico=0; ico<2; ico++) {
584 accepted[ico]=kFALSE;
585 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
586 dpx=fSeg[0]->Dpx(isec)/2.;
587 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
588 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
589 dpy=fSeg[1]->Dpy(isec)/2.;
590 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
591 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
592 if ((dx <= dpx) && (dy <= dpy)) {
598 accepted[ico]=kFALSE;
610 chi21=CombiDoubleMathiesonFit(c);
611 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
612 // Float_t prob = TMath::Prob(chi2,ndf);
613 // prob2->Fill(prob);
614 // chi2_2->Fill(chi21);
615 fprintf(stderr," chi2 %f\n",chi21);
616 if (chi21<10) Split(c);
617 } else if (accepted[1]) {
622 chi22=CombiDoubleMathiesonFit(c);
623 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
624 // Float_t prob = TMath::Prob(chi2,ndf);
625 // prob2->Fill(prob);
626 // chi2_2->Fill(chi22);
627 fprintf(stderr," chi2 %f\n",chi22);
628 if (chi22<10) Split(c);
631 if (chi21 > 10 && chi22 > 10) {
632 // We keep only the combination found (X->cathode 2, Y->cathode 1)
633 for (Int_t ico=0; ico<2; ico++) {
635 AliMUONRawCluster cnew;
637 for (cath=0; cath<2; cath++) {
638 cnew.fX[cath]=Float_t(xm[ico][1]);
639 cnew.fY[cath]=Float_t(ym[ico][0]);
640 cnew.fZ[cath]=fZPlane;
641 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
642 for (i=0; i<fMul[cath]; i++) {
643 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
644 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
646 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
647 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
648 FillCluster(&cnew,cath);
650 cnew.fClusterType=cnew.PhysicsContribution();
657 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
658 // (3') One local maximum on cathode 1 and two maxima on cathode 2
659 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
660 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
662 Float_t xm[4][2], ym[4][2];
663 Float_t dpx, dpy, dx, dy;
664 Int_t ixm[4][2], iym[4][2];
665 Int_t isec, im1, ico;
667 // Form the 2x2 combinations
668 // 0-0, 0-1, 1-0, 1-1
670 for (im1=0; im1<2; im1++) {
671 xm[ico][0]=fX[fIndLocal[0][0]][0];
672 ym[ico][0]=fY[fIndLocal[0][0]][0];
673 xm[ico][1]=fX[fIndLocal[im1][1]][1];
674 ym[ico][1]=fY[fIndLocal[im1][1]][1];
676 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
677 iym[ico][0]=fIy[fIndLocal[0][0]][0];
678 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
679 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
682 // ico = 0 : first local maximum on cathodes 1 and 2
683 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
685 // Analyse the combinations and keep those that are possible !
686 // For each combination check consistency in x and y
691 for (ico=0; ico<2; ico++) {
692 accepted[ico]=kFALSE;
693 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
694 dpx=fSeg[0]->Dpx(isec)/2.;
695 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
696 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
697 dpy=fSeg[1]->Dpy(isec)/2.;
698 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
699 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
700 if ((dx <= dpx) && (dy <= dpy)) {
703 fprintf(stderr,"ico %d\n",ico);
707 accepted[ico]=kFALSE;
719 chi21=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(chi21);
724 fprintf(stderr," chi2 %f\n",chi21);
725 if (chi21<10) Split(c);
726 } else if (accepted[1]) {
731 chi22=CombiDoubleMathiesonFit(c);
732 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
733 // Float_t prob = TMath::Prob(chi2,ndf);
734 // prob2->Fill(prob);
735 // chi2_2->Fill(chi22);
736 fprintf(stderr," chi2 %f\n",chi22);
737 if (chi22<10) Split(c);
740 if (chi21 > 10 && chi22 > 10) {
741 //We keep only the combination found (X->cathode 2, Y->cathode 1)
742 for (Int_t ico=0; ico<2; ico++) {
744 AliMUONRawCluster cnew;
746 for (cath=0; cath<2; cath++) {
747 cnew.fX[cath]=Float_t(xm[ico][1]);
748 cnew.fY[cath]=Float_t(ym[ico][0]);
749 cnew.fZ[cath]=fZPlane;
750 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
751 for (i=0; i<fMul[cath]; i++) {
752 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
753 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
755 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
756 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
757 FillCluster(&cnew,cath);
759 cnew.fClusterType=cnew.PhysicsContribution();
766 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
767 // (4) At least three local maxima on cathode 1 or on cathode 2
768 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
769 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
771 Int_t param = fNLocal[0]*fNLocal[1];
774 Float_t ** xm = new Float_t * [param];
775 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
776 Float_t ** ym = new Float_t * [param];
777 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
778 Int_t ** ixm = new Int_t * [param];
779 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
780 Int_t ** iym = new Int_t * [param];
781 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
784 Float_t dpx, dpy, dx, dy;
787 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
788 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
789 xm[ico][0]=fX[fIndLocal[im1][0]][0];
790 ym[ico][0]=fY[fIndLocal[im1][0]][0];
791 xm[ico][1]=fX[fIndLocal[im2][1]][1];
792 ym[ico][1]=fY[fIndLocal[im2][1]][1];
794 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
795 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
796 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
797 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
804 fprintf(stderr,"nIco %d\n",nIco);
805 for (ico=0; ico<nIco; ico++) {
806 fprintf(stderr,"ico = %d\n",ico);
807 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
808 dpx=fSeg[0]->Dpx(isec)/2.;
809 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
810 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
811 dpy=fSeg[1]->Dpy(isec)/2.;
812 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
814 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
815 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
816 if ((dx <= dpx) && (dy <= dpy)) {
817 fprintf(stderr,"ok\n");
819 AliMUONRawCluster cnew;
820 for (cath=0; cath<2; cath++) {
821 cnew.fX[cath]=Float_t(xm[ico][1]);
822 cnew.fY[cath]=Float_t(ym[ico][0]);
823 cnew.fZ[cath]=fZPlane;
824 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
825 for (i=0; i<fMul[cath]; i++) {
826 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
827 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
829 FillCluster(&cnew,cath);
831 cnew.fClusterType=cnew.PhysicsContribution();
843 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
845 // Find all local maxima of a cluster
846 printf("\n Find Local maxima !");
850 Int_t cath, cath1; // loops over cathodes
851 Int_t i; // loops over digits
852 Int_t j; // loops over cathodes
856 // counters for number of local maxima
857 fNLocal[0]=fNLocal[1]=0;
858 // flags digits as local maximum
859 Bool_t isLocal[100][2];
860 for (i=0; i<100;i++) {
861 isLocal[i][0]=isLocal[i][1]=kFALSE;
863 // number of next neighbours and arrays to store them
866 // loop over cathodes
867 for (cath=0; cath<2; cath++) {
868 // loop over cluster digits
869 for (i=0; i<fMul[cath]; i++) {
870 // get neighbours for that digit and assume that it is local maximum
871 fSeg[cath]->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
872 isLocal[i][cath]=kTRUE;
873 Int_t isec= fSeg[cath]->Sector(fIx[i][cath], fIy[i][cath]);
874 Float_t a0 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
875 // loop over next neighbours, if at least one neighbour has higher charger assumption
876 // digit is not local maximum
877 for (j=0; j<nn; j++) {
878 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
879 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
880 isec=fSeg[cath]->Sector(x[j], y[j]);
881 Float_t a1 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
882 if (digt->fSignal/a1 > fQ[i][cath]/a0) {
883 isLocal[i][cath]=kFALSE;
886 // handle special case of neighbouring pads with equal signal
887 } else if (digt->fSignal == fQ[i][cath]) {
888 if (fNLocal[cath]>0) {
889 for (Int_t k=0; k<fNLocal[cath]; k++) {
890 if (x[j]==fIx[fIndLocal[k][cath]][cath]
891 && y[j]==fIy[fIndLocal[k][cath]][cath])
893 isLocal[i][cath]=kFALSE;
895 } // loop over local maxima
896 } // are there already local maxima
898 } // loop over next neighbours
899 if (isLocal[i][cath]) {
900 fIndLocal[fNLocal[cath]][cath]=i;
903 } // loop over all digits
904 } // loop over cathodes
906 printf("\n Found %d %d %d %d local Maxima\n",
907 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
908 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
909 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
914 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
915 Int_t iback=fNLocal[0];
917 // Two local maxima on cathode 2 and one maximum on cathode 1
918 // Look for local maxima considering up and down neighbours on the 1st cathode only
920 // Loop over cluster digits
924 for (i=0; i<fMul[cath]; i++) {
925 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
926 dpy=fSeg[cath]->Dpy(isec);
927 dpx=fSeg[cath]->Dpx(isec);
928 if (isLocal[i][cath]) continue;
929 // Pad position should be consistent with position of local maxima on the opposite cathode
930 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
931 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
934 // get neighbours for that digit and assume that it is local maximum
935 isLocal[i][cath]=kTRUE;
936 // compare signal to that on the two neighbours on the left and on the right
937 // iNN counts the number of neighbours with signal, it should be 1 or 2
941 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpy);
947 ix = fSeg[cath]->Ix();
948 iy = fSeg[cath]->Iy();
949 // skip the current pad
950 if (iy == fIy[i][cath]) continue;
952 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
954 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
955 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
957 } // Loop over pad neighbours in y
958 if (isLocal[i][cath] && iNN>0) {
959 fIndLocal[fNLocal[cath]][cath]=i;
962 } // loop over all digits
963 // if one additional maximum has been found we are happy
964 // if more maxima have been found restore the previous situation
966 "\n New search gives %d local maxima for cathode 1 \n",
969 " %d local maxima for cathode 2 \n",
971 if (fNLocal[cath]>2) {
975 } // 1,2 local maxima
977 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
978 Int_t iback=fNLocal[1];
980 // Two local maxima on cathode 1 and one maximum on cathode 2
981 // Look for local maxima considering left and right neighbours on the 2nd cathode only
985 // Loop over cluster digits
986 for (i=0; i<fMul[cath]; i++) {
987 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
988 dpx=fSeg[cath]->Dpx(isec);
989 dpy=fSeg[cath]->Dpy(isec);
990 if (isLocal[i][cath]) continue;
991 // Pad position should be consistent with position of local maxima on the opposite cathode
992 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
993 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.))
996 // get neighbours for that digit and assume that it is local maximum
997 isLocal[i][cath]=kTRUE;
998 // compare signal to that on the two neighbours on the left and on the right
1000 // iNN counts the number of neighbours with signal, it should be 1 or 2
1003 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpx);
1009 ix = fSeg[cath]->Ix();
1010 iy = fSeg[cath]->Iy();
1012 // skip the current pad
1013 if (ix == fIx[i][cath]) continue;
1015 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
1017 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
1018 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1020 } // Loop over pad neighbours in x
1021 if (isLocal[i][cath] && iNN>0) {
1022 fIndLocal[fNLocal[cath]][cath]=i;
1025 } // loop over all digits
1026 // if one additional maximum has been found we are happy
1027 // if more maxima have been found restore the previous situation
1028 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
1029 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
1030 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
1031 if (fNLocal[cath]>2) {
1032 fNLocal[cath]=iback;
1034 } // 2,1 local maxima
1038 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
1041 // Completes cluster information starting from list of digits
1048 c->fPeakSignal[cath]=c->fPeakSignal[0];
1050 c->fPeakSignal[cath]=0;
1060 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1061 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1063 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1064 ix=dig->fPadX+c->fOffsetMap[i][cath];
1066 Int_t q=dig->fSignal;
1067 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1068 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1069 if (dig->fPhysics >= dig->fSignal) {
1070 c->fPhysicsMap[i]=2;
1071 } else if (dig->fPhysics == 0) {
1072 c->fPhysicsMap[i]=0;
1073 } else c->fPhysicsMap[i]=1;
1076 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1077 // peak signal and track list
1078 if (q>c->fPeakSignal[cath]) {
1079 c->fPeakSignal[cath]=q;
1080 c->fTracks[0]=dig->fHit;
1081 c->fTracks[1]=dig->fTracks[0];
1082 c->fTracks[2]=dig->fTracks[1];
1083 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1087 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1092 } // loop over digits
1093 // fprintf(stderr," fin du cluster c\n");
1097 c->fX[cath]/=c->fQ[cath];
1098 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1099 c->fY[cath]/=c->fQ[cath];
1101 // apply correction to the coordinate along the anode wire
1105 fSeg[cath]->GetPadI(x, y, fZPlane, ix, iy);
1106 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1107 Int_t isec=fSeg[cath]->Sector(ix,iy);
1108 TF1* cogCorr = fSeg[cath]->CorrFunc(isec-1);
1111 Float_t yOnPad=(c->fY[cath]-y)/fSeg[cath]->Dpy(isec);
1112 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1117 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1120 // Completes cluster information starting from list of digits
1130 Float_t xpad, ypad, zpad;
1133 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1135 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1137 GetPadC(dig->fPadX,dig->fPadY,xpad,ypad, zpad);
1138 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1139 dx = xpad - c->fX[0];
1140 dy = ypad - c->fY[0];
1141 dr = TMath::Sqrt(dx*dx+dy*dy);
1145 fprintf(stderr," dr %f\n",dr);
1146 Int_t q=dig->fSignal;
1147 if (dig->fPhysics >= dig->fSignal) {
1148 c->fPhysicsMap[i]=2;
1149 } else if (dig->fPhysics == 0) {
1150 c->fPhysicsMap[i]=0;
1151 } else c->fPhysicsMap[i]=1;
1152 c->fPeakSignal[cath]=q;
1153 c->fTracks[0]=dig->fHit;
1154 c->fTracks[1]=dig->fTracks[0];
1155 c->fTracks[2]=dig->fTracks[1];
1156 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1159 } // loop over digits
1161 // apply correction to the coordinate along the anode wire
1162 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1165 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1169 // Find a super cluster on both cathodes
1172 // Add i,j as element of the cluster
1175 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1176 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1177 Int_t q=dig->fSignal;
1178 Int_t theX=dig->fPadX;
1179 Int_t theY=dig->fPadY;
1181 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1182 c.fPeakSignal[cath]=q;
1183 c.fTracks[0]=dig->fHit;
1184 c.fTracks[1]=dig->fTracks[0];
1185 c.fTracks[2]=dig->fTracks[1];
1189 // Make sure that list of digits is ordered
1191 Int_t mu=c.fMultiplicity[cath];
1192 c.fIndexMap[mu][cath]=idx;
1194 if (dig->fPhysics >= dig->fSignal) {
1195 c.fPhysicsMap[mu]=2;
1196 } else if (dig->fPhysics == 0) {
1197 c.fPhysicsMap[mu]=0;
1198 } else c.fPhysicsMap[mu]=1;
1202 for (Int_t ind = mu-1; ind >= 0; ind--) {
1203 Int_t ist=(c.fIndexMap)[ind][cath];
1204 Int_t ql=fInput->Digit(cath, ist)->fSignal;
1205 Int_t ix=fInput->Digit(cath, ist)->fPadX;
1206 Int_t iy=fInput->Digit(cath, ist)->fPadY;
1208 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1209 c.fIndexMap[ind][cath]=idx;
1210 c.fIndexMap[ind+1][cath]=ist;
1218 c.fMultiplicity[cath]++;
1219 if (c.fMultiplicity[cath] >= 50 ) {
1220 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1221 c.fMultiplicity[cath]=49;
1224 // Prepare center of gravity calculation
1226 fSeg[cath]->GetPadC(i, j, x, y, z);
1232 // Flag hit as "taken"
1233 fHitMap[cath]->FlagHit(i,j);
1235 // Now look recursively for all neighbours and pad hit on opposite cathode
1237 // Loop over neighbours
1241 Int_t xList[10], yList[10];
1242 fSeg[cath]->Neighbours(i,j,&nn,xList,yList);
1243 for (Int_t in=0; in<nn; in++) {
1247 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) {
1248 // printf("\n Neighbours %d %d %d", cath, ix, iy);
1249 FindCluster(ix, iy, cath, c);
1254 Int_t iXopp[50], iYopp[50];
1256 // Neighbours on opposite cathode
1257 // Take into account that several pads can overlap with the present pad
1258 Int_t isec=fSeg[cath]->Sector(i,j);
1264 dx = (fSeg[cath]->Dpx(isec))/2.;
1269 dy = (fSeg[cath]->Dpy(isec))/2;
1271 // loop over pad neighbours on opposite cathode
1272 for (fSeg[iop]->FirstPad(x, y, fZPlane, dx, dy);
1273 fSeg[iop]->MorePads();
1274 fSeg[iop]->NextPad())
1277 ix = fSeg[iop]->Ix(); iy = fSeg[iop]->Iy();
1278 // printf("\n ix, iy: %f %f %f %d %d %d", x,y,z,ix, iy, fSector);
1279 if (fHitMap[iop]->TestHit(ix,iy)==kUnused){
1282 // printf("\n Opposite %d %d %d", iop, ix, iy);
1285 } // Loop over pad neighbours
1286 // This had to go outside the loop since recursive calls inside the iterator are not possible
1289 for (jopp=0; jopp<nOpp; jopp++) {
1290 if (fHitMap[iop]->TestHit(iXopp[jopp],iYopp[jopp]) == kUnused)
1291 FindCluster(iXopp[jopp], iYopp[jopp], iop, c);
1295 //_____________________________________________________________________________
1297 void AliMUONClusterFinderVS::FindRawClusters()
1300 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1301 // fills the tree with raw clusters
1304 // Return if no input datad available
1305 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1307 fSeg[0] = fInput->Segmentation(0);
1308 fSeg[1] = fInput->Segmentation(1);
1310 fHitMap[0] = new AliMUONHitMapA1(fSeg[0], fInput->Digits(0));
1311 fHitMap[1] = new AliMUONHitMapA1(fSeg[1], fInput->Digits(1));
1319 fHitMap[0]->FillHits();
1320 fHitMap[1]->FillHits();
1322 // Outer Loop over Cathodes
1323 for (cath=0; cath<2; cath++) {
1324 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1325 dig = fInput->Digit(cath, ndig);
1328 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1332 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1333 AliMUONRawCluster c;
1334 c.fMultiplicity[0]=0;
1335 c.fMultiplicity[1]=0;
1336 c.fPeakSignal[cath]=dig->fSignal;
1337 c.fTracks[0]=dig->fHit;
1338 c.fTracks[1]=dig->fTracks[0];
1339 c.fTracks[2]=dig->fTracks[1];
1340 // tag the beginning of cluster list in a raw cluster
1343 fSeg[cath]->GetPadC(i,j,xcu, ycu, fZPlane);
1344 fSector= fSeg[cath]->Sector(i,j)/100;
1345 // printf("\n New Seed %d %d ", i,j);
1347 FindCluster(i,j,cath,c);
1348 // ^^^^^^^^^^^^^^^^^^^^^^^^
1349 // center of gravity
1351 c.fX[0]=fSeg[0]->GetAnod(c.fX[0]);
1354 c.fX[1]=fSeg[0]->GetAnod(c.fX[1]);
1360 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",
1361 c.fMultiplicity[0],c.fX[0],c.fY[0]);
1362 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",
1363 c.fMultiplicity[1],c.fX[1],c.fY[1]);
1365 // Analyse cluster and decluster if necessary
1368 c.fNcluster[1]=fNRawClusters;
1369 c.fClusterType=c.PhysicsContribution();
1376 // reset Cluster object
1377 { // begin local scope
1378 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1379 } // end local scope
1381 { // begin local scope
1382 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1383 } // end local scope
1385 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1389 } // end loop cathodes
1394 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1396 // Performs a single Mathieson fit on one cathode
1398 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1400 clusterInput.Fitter()->SetFCN(fcnS1);
1401 clusterInput.Fitter()->mninit(2,10,7);
1402 Double_t arglist[20];
1405 // Set starting values
1406 static Double_t vstart[2];
1411 // lower and upper limits
1412 static Double_t lower[2], upper[2];
1414 fSeg[cath]->GetPadI(c->fX[cath], c->fY[cath], fZPlane, ix, iy);
1415 Int_t isec=fSeg[cath]->Sector(ix, iy);
1416 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec)/2;
1417 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec)/2;
1419 upper[0]=lower[0]+fSeg[cath]->Dpx(isec);
1420 upper[1]=lower[1]+fSeg[cath]->Dpy(isec);
1423 static Double_t step[2]={0.0005, 0.0005};
1425 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1426 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1427 // ready for minimisation
1428 clusterInput.Fitter()->SetPrintLevel(1);
1429 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1433 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1434 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1435 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1436 Double_t fmin, fedm, errdef;
1437 Int_t npari, nparx, istat;
1439 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1443 // Get fitted parameters
1444 Double_t xrec, yrec;
1446 Double_t epxz, b1, b2;
1448 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1449 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1455 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1457 // Perform combined Mathieson fit on both cathode planes
1459 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1460 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1461 clusterInput.Fitter()->mninit(2,10,7);
1462 Double_t arglist[20];
1465 static Double_t vstart[2];
1466 vstart[0]=fXInit[0];
1467 vstart[1]=fYInit[0];
1470 // lower and upper limits
1471 static Float_t lower[2], upper[2];
1473 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1474 isec=fSeg[0]->Sector(ix, iy);
1475 Float_t dpy=fSeg[0]->Dpy(isec);
1476 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1477 isec=fSeg[1]->Sector(ix, iy);
1478 Float_t dpx=fSeg[1]->Dpx(isec);
1481 Float_t xdum, ydum, zdum;
1483 // Find save upper and lower limits
1487 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1488 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1490 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1491 fSeg[1]->GetPadC(ix,iy, upper[0], ydum, zdum);
1492 if (icount ==0) lower[0]=upper[0];
1496 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1499 printf("\n single y %f %f", fXInit[0], fYInit[0]);
1501 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1502 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1504 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1505 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1506 if (icount ==0) lower[1]=upper[1];
1508 printf("\n upper lower %d %f %f", icount, upper[1], lower[1]);
1511 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1514 static Double_t step[2]={0.00001, 0.0001};
1516 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1517 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1518 // ready for minimisation
1519 clusterInput.Fitter()->SetPrintLevel(1);
1520 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1524 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1525 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1526 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1527 Double_t fmin, fedm, errdef;
1528 Int_t npari, nparx, istat;
1530 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1534 // Get fitted parameters
1535 Double_t xrec, yrec;
1537 Double_t epxz, b1, b2;
1539 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1540 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1546 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1548 // Performs a double Mathieson fit on one cathode
1552 // Initialise global variables for fit
1553 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1554 clusterInput.Fitter()->SetFCN(fcnS2);
1555 clusterInput.Fitter()->mninit(5,10,7);
1556 Double_t arglist[20];
1559 // Set starting values
1560 static Double_t vstart[5];
1561 vstart[0]=fX[fIndLocal[0][cath]][cath];
1562 vstart[1]=fY[fIndLocal[0][cath]][cath];
1563 vstart[2]=fX[fIndLocal[1][cath]][cath];
1564 vstart[3]=fY[fIndLocal[1][cath]][cath];
1565 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1566 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1567 // lower and upper limits
1568 static Float_t lower[5], upper[5];
1569 Int_t isec=fSeg[cath]->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1570 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec);
1571 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec);
1573 upper[0]=lower[0]+2.*fSeg[cath]->Dpx(isec);
1574 upper[1]=lower[1]+2.*fSeg[cath]->Dpy(isec);
1576 isec=fSeg[cath]->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1577 lower[2]=vstart[2]-fSeg[cath]->Dpx(isec)/2;
1578 lower[3]=vstart[3]-fSeg[cath]->Dpy(isec)/2;
1580 upper[2]=lower[2]+fSeg[cath]->Dpx(isec);
1581 upper[3]=lower[3]+fSeg[cath]->Dpy(isec);
1586 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
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 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1591 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1592 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1593 // ready for minimisation
1594 clusterInput.Fitter()->SetPrintLevel(-1);
1595 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1599 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1600 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1601 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1602 // Get fitted parameters
1603 Double_t xrec[2], yrec[2], qfrac;
1605 Double_t epxz, b1, b2;
1607 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1608 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1609 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1610 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1611 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1613 Double_t fmin, fedm, errdef;
1614 Int_t npari, nparx, istat;
1616 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1621 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1624 // Perform combined double Mathieson fit on both cathode planes
1626 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1627 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1628 clusterInput.Fitter()->mninit(6,10,7);
1629 Double_t arglist[20];
1632 // Set starting values
1633 static Double_t vstart[6];
1634 vstart[0]=fXInit[0];
1635 vstart[1]=fYInit[0];
1636 vstart[2]=fXInit[1];
1637 vstart[3]=fYInit[1];
1638 vstart[4]=fQrInit[0];
1639 vstart[5]=fQrInit[1];
1640 // lower and upper limits
1641 static Float_t lower[6], upper[6];
1645 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1646 isec=fSeg[1]->Sector(ix, iy);
1647 dpx=fSeg[1]->Dpx(isec);
1649 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1650 isec=fSeg[0]->Sector(ix, iy);
1651 dpy=fSeg[0]->Dpy(isec);
1655 Float_t xdum, ydum, zdum;
1656 // printf("\n Cluster Finder: %f %f %f %f ", fXInit[0], fXInit[1],fYInit[0], fYInit[1] );
1658 // Find save upper and lower limits
1661 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1662 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1664 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1665 fSeg[1]->GetPadC(ix,iy,upper[0],ydum,zdum);
1666 if (icount ==0) lower[0]=upper[0];
1669 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1672 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1673 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1675 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1676 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1677 if (icount ==0) lower[1]=upper[1];
1680 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1682 fSeg[1]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1683 isec=fSeg[1]->Sector(ix, iy);
1684 dpx=fSeg[1]->Dpx(isec);
1685 fSeg[0]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1686 isec=fSeg[0]->Sector(ix, iy);
1687 dpy=fSeg[0]->Dpy(isec);
1690 // Find save upper and lower limits
1694 for (fSeg[1]->FirstPad(fXInit[1], fYInit[1], fZPlane, dpx, 0);
1695 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1697 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1698 fSeg[1]->GetPadC(ix,iy,upper[2],ydum,zdum);
1699 if (icount ==0) lower[2]=upper[2];
1702 if (lower[2]>upper[2]) {xdum=lower[2]; lower[2]=upper[2]; upper[2]=xdum;}
1706 for (fSeg[0]->FirstPad(fXInit[1], fYInit[1], fZPlane, 0, dpy);
1707 fSeg[0]-> MorePads(); fSeg[0]->NextPad())
1709 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1710 fSeg[0]->GetPadC(ix,iy,xdum,upper[3],zdum);
1711 if (icount ==0) lower[3]=upper[3];
1714 if (lower[3]>upper[3]) {xdum=lower[3]; lower[3]=upper[3]; upper[3]=xdum;}
1722 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1723 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1724 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1725 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1726 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1727 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1728 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1729 // ready for minimisation
1730 clusterInput.Fitter()->SetPrintLevel(-1);
1731 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1735 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1736 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1737 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1738 // Get fitted parameters
1740 Double_t epxz, b1, b2;
1742 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1743 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1744 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1745 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1746 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1747 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1749 Double_t fmin, fedm, errdef;
1750 Int_t npari, nparx, istat;
1752 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1760 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1763 // One cluster for each maximum
1766 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1767 for (j=0; j<2; j++) {
1768 AliMUONRawCluster cnew;
1769 for (cath=0; cath<2; cath++) {
1770 cnew.fChi2[cath]=fChi2[0];
1773 cnew.fNcluster[0]=-1;
1774 cnew.fNcluster[1]=fNRawClusters;
1776 cnew.fNcluster[0]=fNPeaks;
1777 cnew.fNcluster[1]=0;
1779 cnew.fMultiplicity[cath]=0;
1780 cnew.fX[cath]=Float_t(fXFit[j]);
1781 cnew.fY[cath]=Float_t(fYFit[j]);
1782 cnew.fZ[cath]=fZPlane;
1784 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
1786 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
1788 fSeg[cath]->SetHit(fXFit[j],fYFit[j],fZPlane);
1789 for (i=0; i<fMul[cath]; i++) {
1790 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1791 c->fIndexMap[i][cath];
1792 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
1793 Float_t q1=fInput->Response()->IntXY(fSeg[cath]);
1794 cnew.fContMap[i][cath]
1795 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1796 cnew.fMultiplicity[cath]++;
1798 FillCluster(&cnew,0,cath);
1801 cnew.fClusterType=cnew.PhysicsContribution();
1802 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1809 // Minimisation functions
1811 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1813 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1820 for (i=0; i<clusterInput.Nmul(0); i++) {
1821 Float_t q0=clusterInput.Charge(i,0);
1822 Float_t q1=clusterInput.DiscrChargeS1(i,par);
1831 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1833 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1840 for (cath=0; cath<2; cath++) {
1841 for (i=0; i<clusterInput.Nmul(cath); i++) {
1842 Float_t q0=clusterInput.Charge(i,cath);
1843 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
1854 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1856 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1863 for (i=0; i<clusterInput.Nmul(0); i++) {
1865 Float_t q0=clusterInput.Charge(i,0);
1866 Float_t q1=clusterInput.DiscrChargeS2(i,par);
1876 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1878 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1884 for (cath=0; cath<2; cath++) {
1885 for (i=0; i<clusterInput.Nmul(cath); i++) {
1886 Float_t q0=clusterInput.Charge(i,cath);
1887 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
1897 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1900 // Add a raw cluster copy to the list
1902 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1903 pMUON->AddRawCluster(fInput->Chamber(),c);
1905 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1908 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
1909 if (fTrack[0]==-1 || fTrack[1]==-1) {
1911 } else if (t==fTrack[0] || t==fTrack[1]) {
1918 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1919 ::operator = (const AliMUONClusterFinderVS& rhs)
1921 // Dummy assignment operator