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.3 2000/06/22 14:02:45 morsch
18 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
19 Some HP scope problems corrected (PH)
21 Revision 1.2 2000/06/15 07:58:48 morsch
22 Code from MUON-dev joined
24 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
25 Most coding rule violations corrected.
27 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
28 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
29 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
30 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
31 - For clusters with more than 2 maxima on one of the cathode planes all valid
32 combinations of maxima on the two cathodes are preserved. The position of the maxima is
33 taken as the hit position.
34 - New FillCluster method with 2 arguments to find tracks associated to the clusters
35 defined above added. (Method destinction by argument list not very elegant in this case,
36 should be revides (A.M.)
37 - Bug in if-statement to handle maximum 1 maximum per plane corrected
38 - Two cluster per cathode but only 1 combination valid is handled.
39 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
43 #include "AliMUONClusterFinderVS.h"
44 #include "AliMUONDigit.h"
45 #include "AliMUONRawCluster.h"
46 #include "AliMUONSegmentation.h"
47 #include "AliMUONResponse.h"
48 #include "AliMUONHitMap.h"
49 #include "AliMUONHitMapA1.h"
58 #include <TPostScript.h>
63 //_____________________________________________________________________
64 static AliMUONSegmentation* fgSegmentation[2];
65 static AliMUONResponse* fgResponse;
66 static Int_t fgix[500][2];
67 static Int_t fgiy[500][2];
68 static Float_t fgCharge[500][2];
69 static Int_t fgNbins[2];
70 static Int_t fgFirst=kTRUE;
71 static Int_t fgChargeTot[2];
72 static Float_t fgQtot[2];
73 static TMinuit* fgMyMinuit ;
74 // This function is minimized in the double-Mathieson fit
75 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
76 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
77 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
78 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
80 ClassImp(AliMUONClusterFinderVS)
82 AliMUONClusterFinderVS::AliMUONClusterFinderVS
83 (AliMUONSegmentation *seg1, AliMUONSegmentation *seg2,
84 AliMUONResponse *response,
85 TClonesArray *digits1, TClonesArray *digits2,
87 :AliMUONClusterFinder(seg1, response, digits1, chamber)
92 fNdigits2 = fDigits2->GetEntriesFast();
94 fTrack[0]=fTrack[1]=-1;
98 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
99 :AliMUONClusterFinder()
101 // Default constructor
106 fTrack[0]=fTrack[1]=-1;
109 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
110 const AliMUONClusterFinderVS & clusterFinder)
112 // Dummy copy Constructor
116 void AliMUONClusterFinderVS::SetDigits(TClonesArray *MUONdigits1, TClonesArray *MUONdigits2) {
117 // Set pointers to digit lists
120 fNdigits = fDigits->GetEntriesFast();
121 fDigits2=MUONdigits2;
122 fNdigits2 = fDigits2->GetEntriesFast();
126 AliMUONSegmentation* AliMUONClusterFinderVS::Segmentation(Int_t i)
128 // Return pointer to segmentation of cathode plane number 1 (i=0) or 2 (i=1)
129 return ((i==0)? fSegmentation : fSegmentation2);
132 // Get Number of Digits
133 Int_t AliMUONClusterFinderVS::NDigits(Int_t i)
135 // Return number of digits for cathode plane i+1
136 return ((i==0)? fNdigits : fNdigits2);
140 TClonesArray* AliMUONClusterFinderVS::Digits(Int_t i)
142 // Return pointer to digits for cathode plane i+1
143 return ((i==0)? fDigits : fDigits2);
147 AliMUONHitMap* AliMUONClusterFinderVS::HitMap(Int_t i)
149 // Return pointer to HitMap
150 return ((i==0)? fHitMap : fHitMap2);
153 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
155 // Decluster by local maxima
156 SplitByLocalMaxima(cluster);
159 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
161 // Split complex cluster by local maxima
165 fMul[0]=c->fMultiplicity[0];
166 fMul[1]=c->fMultiplicity[1];
169 // dump digit information into arrays
171 fgSegmentation[0]=Segmentation(0);
172 fgSegmentation[1]=Segmentation(1);
173 fgResponse =fResponse;
178 for (cath=0; cath<2; cath++) {
180 for (i=0; i<fMul[cath]; i++)
183 fDig[i][cath]=(AliMUONDigit*)
184 (Digits(cath)->UncheckedAt(c->fIndexMap[i][cath]));
186 fIx[i][cath]= fDig[i][cath]->fPadX;
187 fIy[i][cath]= fDig[i][cath]->fPadY;
189 fQ[i][cath] = fDig[i][cath]->fSignal;
190 // pad centre coordinates
192 GetPadCxy(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath]);
193 // globals kUsed in fitting functions
194 fgix[i][cath]=fIx[i][cath];
195 fgiy[i][cath]=fIy[i][cath];
196 fgCharge[i][cath]=Float_t(fQ[i][cath]);
197 // total charge per cluster
198 qtot+=fgCharge[i][cath];
199 } // loop over cluster digits
201 fgChargeTot[cath]=Int_t(qtot);
202 } // loop over cathodes
208 // Initialise and perform mathieson fits
209 Float_t chi2, oldchi2;
210 // ++++++++++++++++++*************+++++++++++++++++++++
211 // (1) No more than one local maximum per cathode plane
212 // +++++++++++++++++++++++++++++++*************++++++++
213 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
214 (fNLocal[0]==0 && fNLocal[1]==1)) {
216 // Perform combined single Mathieson fit
217 // Initial values for coordinates (x,y)
219 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
220 if (fNLocal[0]==1 && fNLocal[1]==1) {
223 // One local maximum on cathode 1 (X,Y->cathode 1)
224 } else if (fNLocal[0]==1) {
227 // One local maximum on cathode 2 (X,Y->cathode 2)
232 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
233 chi2=CombiSingleMathiesonFit(c);
234 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
235 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
236 // prob1->Fill(prob);
237 // chi2_1->Fill(chi2);
239 fprintf(stderr," chi2 %f ",chi2);
248 c->fX[0]=Segmentation(0)->GetAnod(c->fX[0]);
249 c->fX[1]=Segmentation(1)->GetAnod(c->fX[1]);
251 // If reasonable chi^2 add result to the list of rawclusters
255 // If not try combined double Mathieson Fit
257 fprintf(stderr," MAUVAIS CHI2 !!!\n");
258 if (fNLocal[0]==1 && fNLocal[1]==1) {
259 fXInit[0]=fX[fIndLocal[0][1]][1];
260 fYInit[0]=fY[fIndLocal[0][0]][0];
261 fXInit[1]=fX[fIndLocal[0][1]][1];
262 fYInit[1]=fY[fIndLocal[0][0]][0];
263 } else if (fNLocal[0]==1) {
264 fXInit[0]=fX[fIndLocal[0][0]][0];
265 fYInit[0]=fY[fIndLocal[0][0]][0];
266 fXInit[1]=fX[fIndLocal[0][0]][0];
267 fYInit[1]=fY[fIndLocal[0][0]][0];
269 fXInit[0]=fX[fIndLocal[0][1]][1];
270 fYInit[0]=fY[fIndLocal[0][1]][1];
271 fXInit[1]=fX[fIndLocal[0][1]][1];
272 fYInit[1]=fY[fIndLocal[0][1]][1];
275 // Initial value for charge ratios
278 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
279 chi2=CombiDoubleMathiesonFit(c);
280 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
281 // Float_t prob = TMath::Prob(chi2,ndf);
282 // prob2->Fill(prob);
283 // chi2_2->Fill(chi2);
285 // Was this any better ??
286 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
287 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
288 fprintf(stderr," Split\n");
289 // Split cluster into two according to fit result
292 fprintf(stderr," Don't Split\n");
298 // +++++++++++++++++++++++++++++++++++++++
299 // (2) Two local maxima per cathode plane
300 // +++++++++++++++++++++++++++++++++++++++
301 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
303 // Let's look for ghosts first
305 Float_t xm[4][2], ym[4][2];
306 Float_t dpx, dpy, dx, dy;
307 Int_t ixm[4][2], iym[4][2];
308 Int_t isec, im1, im2, ico;
310 // Form the 2x2 combinations
311 // 0-0, 0-1, 1-0, 1-1
313 for (im1=0; im1<2; im1++) {
314 for (im2=0; im2<2; im2++) {
315 xm[ico][0]=fX[fIndLocal[im1][0]][0];
316 ym[ico][0]=fY[fIndLocal[im1][0]][0];
317 xm[ico][1]=fX[fIndLocal[im2][1]][1];
318 ym[ico][1]=fY[fIndLocal[im2][1]][1];
320 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
321 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
322 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
323 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
327 // ico = 0 : first local maximum on cathodes 1 and 2
328 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
329 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
330 // ico = 3 : second local maximum on cathodes 1 and 2
332 // Analyse the combinations and keep those that are possible !
333 // For each combination check consistency in x and y
338 for (ico=0; ico<4; ico++) {
339 accepted[ico]=kFALSE;
340 // cathode one: x-coordinate
341 isec=Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
342 dpx=Segmentation(0)->Dpx(isec)/2.;
343 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
344 // cathode two: y-coordinate
345 isec=Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
346 dpy=Segmentation(1)->Dpy(isec)/2.;
347 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
348 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
349 if ((dx <= dpx) && (dy <= dpy)) {
355 accepted[ico]=kFALSE;
360 fprintf(stderr,"\n iacc=2: No problem ! \n");
361 } else if (iacc==4) {
362 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
363 } else if (iacc==0) {
364 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
367 // Initial value for charge ratios
368 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
369 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
370 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
371 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
373 // ******* iacc = 0 *******
374 // No combinations found between the 2 cathodes
375 // We keep the center of gravity of the cluster
380 // ******* iacc = 1 *******
381 // Only one combination found between the 2 cathodes
384 // Initial values for the 2 maxima (x,y)
386 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
387 // 1 maximum is initialised with the other maximum of the first cathode
389 fprintf(stderr,"ico=0\n");
394 } else if (accepted[1]){
395 fprintf(stderr,"ico=1\n");
400 } else if (accepted[2]){
401 fprintf(stderr,"ico=2\n");
406 } else if (accepted[3]){
407 fprintf(stderr,"ico=3\n");
413 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
414 chi2=CombiDoubleMathiesonFit(c);
415 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
416 // Float_t prob = TMath::Prob(chi2,ndf);
417 // prob2->Fill(prob);
418 // chi2_2->Fill(chi2);
419 fprintf(stderr," chi2 %f\n",chi2);
421 // If reasonable chi^2 add result to the list of rawclusters
426 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
427 // 1 maximum is initialised with the other maximum of the second cathode
429 fprintf(stderr,"ico=0\n");
434 } else if (accepted[1]){
435 fprintf(stderr,"ico=1\n");
440 } else if (accepted[2]){
441 fprintf(stderr,"ico=2\n");
446 } else if (accepted[3]){
447 fprintf(stderr,"ico=3\n");
453 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
454 chi2=CombiDoubleMathiesonFit(c);
455 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
456 // Float_t prob = TMath::Prob(chi2,ndf);
457 // prob2->Fill(prob);
458 // chi2_2->Fill(chi2);
459 fprintf(stderr," chi2 %f\n",chi2);
461 // If reasonable chi^2 add result to the list of rawclusters
465 //We keep only the combination found (X->cathode 2, Y->cathode 1)
466 for (Int_t ico=0; ico<2; ico++) {
468 AliMUONRawCluster cnew;
470 for (cath=0; cath<2; cath++) {
471 cnew.fX[cath]=Float_t(xm[ico][1]);
472 cnew.fY[cath]=Float_t(ym[ico][0]);
473 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
474 for (i=0; i<fMul[cath]; i++) {
475 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
476 fgSegmentation[cath]->SetPad(fgix[i][cath], fgiy[i][cath]);
478 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
479 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
480 FillCluster(&cnew,cath);
482 cnew.fClusterType=cnew.PhysicsContribution();
491 // ******* iacc = 2 *******
492 // Two combinations found between the 2 cathodes
495 // Was the same maximum taken twice
496 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
497 fprintf(stderr,"\n Maximum taken twice !!!\n");
499 // Have a try !! with that
500 if (accepted[0]&&accepted[3]) {
511 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
512 chi2=CombiDoubleMathiesonFit(c);
513 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
514 // Float_t prob = TMath::Prob(chi2,ndf);
515 // prob2->Fill(prob);
516 // chi2_2->Fill(chi2);
520 // No ghosts ! No Problems ! - Perform one fit only !
521 if (accepted[0]&&accepted[3]) {
532 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
533 chi2=CombiDoubleMathiesonFit(c);
534 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
535 // Float_t prob = TMath::Prob(chi2,ndf);
536 // prob2->Fill(prob);
537 // chi2_2->Fill(chi2);
538 fprintf(stderr," chi2 %f\n",chi2);
542 // ******* iacc = 4 *******
543 // Four combinations found between the 2 cathodes
545 } else if (iacc==4) {
546 // Perform fits for the two possibilities !!
551 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
552 chi2=CombiDoubleMathiesonFit(c);
553 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
554 // Float_t prob = TMath::Prob(chi2,ndf);
555 // prob2->Fill(prob);
556 // chi2_2->Fill(chi2);
557 fprintf(stderr," chi2 %f\n",chi2);
563 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
564 chi2=CombiDoubleMathiesonFit(c);
565 // ndf = fgNbins[0]+fgNbins[1]-6;
566 // prob = TMath::Prob(chi2,ndf);
567 // prob2->Fill(prob);
568 // chi2_2->Fill(chi2);
569 fprintf(stderr," chi2 %f\n",chi2);
573 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
574 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
575 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
576 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
578 Float_t xm[4][2], ym[4][2];
579 Float_t dpx, dpy, dx, dy;
580 Int_t ixm[4][2], iym[4][2];
581 Int_t isec, im1, ico;
583 // Form the 2x2 combinations
584 // 0-0, 0-1, 1-0, 1-1
586 for (im1=0; im1<2; im1++) {
587 xm[ico][0]=fX[fIndLocal[im1][0]][0];
588 ym[ico][0]=fY[fIndLocal[im1][0]][0];
589 xm[ico][1]=fX[fIndLocal[0][1]][1];
590 ym[ico][1]=fY[fIndLocal[0][1]][1];
592 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
593 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
594 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
595 iym[ico][1]=fIy[fIndLocal[0][1]][1];
598 // ico = 0 : first local maximum on cathodes 1 and 2
599 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
601 // Analyse the combinations and keep those that are possible !
602 // For each combination check consistency in x and y
607 for (ico=0; ico<2; ico++) {
608 accepted[ico]=kFALSE;
609 isec=Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
610 dpx=Segmentation(0)->Dpx(isec)/2.;
611 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
612 isec=Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
613 dpy=Segmentation(1)->Dpy(isec)/2.;
614 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
615 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
616 if ((dx <= dpx) && (dy <= dpy)) {
622 accepted[ico]=kFALSE;
634 chi21=CombiDoubleMathiesonFit(c);
635 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
636 // Float_t prob = TMath::Prob(chi2,ndf);
637 // prob2->Fill(prob);
638 // chi2_2->Fill(chi21);
639 fprintf(stderr," chi2 %f\n",chi21);
640 if (chi21<10) Split(c);
641 } else if (accepted[1]) {
646 chi22=CombiDoubleMathiesonFit(c);
647 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
648 // Float_t prob = TMath::Prob(chi2,ndf);
649 // prob2->Fill(prob);
650 // chi2_2->Fill(chi22);
651 fprintf(stderr," chi2 %f\n",chi22);
652 if (chi22<10) Split(c);
655 if (chi21 > 10 && chi22 > 10) {
656 // We keep only the combination found (X->cathode 2, Y->cathode 1)
657 for (Int_t ico=0; ico<2; ico++) {
659 AliMUONRawCluster cnew;
661 for (cath=0; cath<2; cath++) {
662 cnew.fX[cath]=Float_t(xm[ico][1]);
663 cnew.fY[cath]=Float_t(ym[ico][0]);
664 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
665 for (i=0; i<fMul[cath]; i++) {
666 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
667 fgSegmentation[cath]->SetPad(fgix[i][cath], fgiy[i][cath]);
669 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
670 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
671 FillCluster(&cnew,cath);
673 cnew.fClusterType=cnew.PhysicsContribution();
680 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
681 // (3') One local maximum on cathode 1 and two maxima on cathode 2
682 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
683 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
685 Float_t xm[4][2], ym[4][2];
686 Float_t dpx, dpy, dx, dy;
687 Int_t ixm[4][2], iym[4][2];
688 Int_t isec, im1, ico;
690 // Form the 2x2 combinations
691 // 0-0, 0-1, 1-0, 1-1
693 for (im1=0; im1<2; im1++) {
694 xm[ico][0]=fX[fIndLocal[0][0]][0];
695 ym[ico][0]=fY[fIndLocal[0][0]][0];
696 xm[ico][1]=fX[fIndLocal[im1][1]][1];
697 ym[ico][1]=fY[fIndLocal[im1][1]][1];
699 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
700 iym[ico][0]=fIy[fIndLocal[0][0]][0];
701 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
702 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
705 // ico = 0 : first local maximum on cathodes 1 and 2
706 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
708 // Analyse the combinations and keep those that are possible !
709 // For each combination check consistency in x and y
714 for (ico=0; ico<2; ico++) {
715 accepted[ico]=kFALSE;
716 isec=Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
717 dpx=Segmentation(0)->Dpx(isec)/2.;
718 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
719 isec=Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
720 dpy=Segmentation(1)->Dpy(isec)/2.;
721 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
722 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
723 if ((dx <= dpx) && (dy <= dpy)) {
726 fprintf(stderr,"ico %d\n",ico);
730 accepted[ico]=kFALSE;
742 chi21=CombiDoubleMathiesonFit(c);
743 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
744 // Float_t prob = TMath::Prob(chi2,ndf);
745 // prob2->Fill(prob);
746 // chi2_2->Fill(chi21);
747 fprintf(stderr," chi2 %f\n",chi21);
748 if (chi21<10) Split(c);
749 } else if (accepted[1]) {
754 chi22=CombiDoubleMathiesonFit(c);
755 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
756 // Float_t prob = TMath::Prob(chi2,ndf);
757 // prob2->Fill(prob);
758 // chi2_2->Fill(chi22);
759 fprintf(stderr," chi2 %f\n",chi22);
760 if (chi22<10) Split(c);
763 if (chi21 > 10 && chi22 > 10) {
764 //We keep only the combination found (X->cathode 2, Y->cathode 1)
765 for (Int_t ico=0; ico<2; ico++) {
767 AliMUONRawCluster cnew;
769 for (cath=0; cath<2; cath++) {
770 cnew.fX[cath]=Float_t(xm[ico][1]);
771 cnew.fY[cath]=Float_t(ym[ico][0]);
772 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
773 for (i=0; i<fMul[cath]; i++) {
774 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
775 fgSegmentation[cath]->SetPad(fgix[i][cath], fgiy[i][cath]);
777 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
778 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
779 FillCluster(&cnew,cath);
781 cnew.fClusterType=cnew.PhysicsContribution();
788 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
789 // (4) At least three local maxima on cathode 1 or on cathode 2
790 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
791 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
793 Int_t param = fNLocal[0]*fNLocal[1];
796 Float_t ** xm = new Float_t * [param];
797 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
798 Float_t ** ym = new Float_t * [param];
799 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
800 Int_t ** ixm = new Int_t * [param];
801 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
802 Int_t ** iym = new Int_t * [param];
803 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
806 Float_t dpx, dpy, dx, dy;
809 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
810 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
811 xm[ico][0]=fX[fIndLocal[im1][0]][0];
812 ym[ico][0]=fY[fIndLocal[im1][0]][0];
813 xm[ico][1]=fX[fIndLocal[im2][1]][1];
814 ym[ico][1]=fY[fIndLocal[im2][1]][1];
816 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
817 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
818 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
819 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
826 fprintf(stderr,"nIco %d\n",nIco);
827 for (ico=0; ico<nIco; ico++) {
828 fprintf(stderr,"ico = %d\n",ico);
829 isec=Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
830 dpx=Segmentation(0)->Dpx(isec)/2.;
831 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
832 isec=Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
833 dpy=Segmentation(1)->Dpy(isec)/2.;
834 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
836 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
837 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
838 if ((dx <= dpx) && (dy <= dpy)) {
839 fprintf(stderr,"ok\n");
841 AliMUONRawCluster cnew;
842 for (cath=0; cath<2; cath++) {
843 cnew.fX[cath]=Float_t(xm[ico][1]);
844 cnew.fY[cath]=Float_t(ym[ico][0]);
845 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
846 for (i=0; i<fMul[cath]; i++) {
847 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
848 fgSegmentation[cath]->SetPad(fgix[i][cath], fgiy[i][cath]);
850 FillCluster(&cnew,cath);
852 cnew.fClusterType=cnew.PhysicsContribution();
864 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
866 // Find all local maxima of a cluster
870 Int_t cath, cath1; // loops over cathodes
871 Int_t i; // loops over digits
872 Int_t j; // loops over cathodes
876 // counters for number of local maxima
877 fNLocal[0]=fNLocal[1]=0;
878 // flags digits as local maximum
879 Bool_t isLocal[100][2];
880 for (i=0; i<100;i++) {
881 isLocal[i][0]=isLocal[i][1]=kFALSE;
883 // number of next neighbours and arrays to store them
885 Int_t x[kMaxNeighbours], y[kMaxNeighbours];
886 // loop over cathodes
887 for (cath=0; cath<2; cath++) {
888 // loop over cluster digits
889 for (i=0; i<fMul[cath]; i++) {
890 // get neighbours for that digit and assume that it is local maximum
891 Segmentation(cath)->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
892 isLocal[i][cath]=kTRUE;
893 Int_t isec= Segmentation(cath)->Sector(fIx[i][cath], fIy[i][cath]);
894 Float_t a0 = Segmentation(cath)->Dpx(isec)*Segmentation(cath)->Dpy(isec);
895 // loop over next neighbours, if at least one neighbour has higher charger assumption
896 // digit is not local maximum
897 for (j=0; j<nn; j++) {
898 if (HitMap(cath)->TestHit(x[j], y[j])==kEmpty) continue;
899 digt=(AliMUONDigit*) HitMap(cath)->GetHit(x[j], y[j]);
900 isec=Segmentation(cath)->Sector(x[j], y[j]);
901 Float_t a1 = Segmentation(cath)->Dpx(isec)*Segmentation(cath)->Dpy(isec);
902 if (digt->fSignal/a1 > fQ[i][cath]/a0) {
903 isLocal[i][cath]=kFALSE;
906 // handle special case of neighbouring pads with equal signal
907 } else if (digt->fSignal == fQ[i][cath]) {
908 if (fNLocal[cath]>0) {
909 for (Int_t k=0; k<fNLocal[cath]; k++) {
910 if (x[j]==fIx[fIndLocal[k][cath]][cath]
911 && y[j]==fIy[fIndLocal[k][cath]][cath])
913 isLocal[i][cath]=kFALSE;
915 } // loop over local maxima
916 } // are there already local maxima
918 } // loop over next neighbours
919 if (isLocal[i][cath]) {
920 fIndLocal[fNLocal[cath]][cath]=i;
923 } // loop over all digits
924 } // loop over cathodes
926 printf("\n Found %d %d %d %d local Maxima\n",
927 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
928 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
929 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
934 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
935 Int_t iback=fNLocal[0];
937 // Two local maxima on cathode 2 and one maximum on cathode 1
938 // Look for local maxima considering up and down neighbours on the 1st cathode only
940 // Loop over cluster digits
944 for (i=0; i<fMul[cath]; i++) {
945 isec=Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
946 dpy=Segmentation(cath)->Dpy(isec);
947 dpx=Segmentation(cath)->Dpx(isec);
948 if (isLocal[i][cath]) continue;
949 // Pad position should be consistent with position of local maxima on the opposite cathode
950 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
951 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
954 // get neighbours for that digit and assume that it is local maximum
955 isLocal[i][cath]=kTRUE;
956 // compare signal to that on the two neighbours on the left and on the right
957 Segmentation(cath)->GetPadIxy(fX[i][cath],fY[i][cath]+dpy,ix,iy);
958 // iNN counts the number of neighbours with signal, it should be 1 or 2
960 if (HitMap(cath)->TestHit(ix, iy)!=kEmpty) {
962 digt=(AliMUONDigit*) HitMap(cath)->GetHit(ix,iy);
963 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
965 Segmentation(cath)->GetPadIxy(fX[i][cath],fY[i][cath]-dpy,ix,iy);
966 if (HitMap(cath)->TestHit(ix, iy)!=kEmpty) {
968 digt=(AliMUONDigit*) HitMap(cath)->GetHit(ix,iy);
969 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
971 if (isLocal[i][cath] && iNN>0) {
972 fIndLocal[fNLocal[cath]][cath]=i;
975 } // loop over all digits
976 // if one additional maximum has been found we are happy
977 // if more maxima have been found restore the previous situation
978 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
979 fprintf(stderr," %d local maxima for cathode 2 \n",fNLocal[1]);
980 if (fNLocal[cath]>2) {
984 } // 1,2 local maxima
986 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
987 Int_t iback=fNLocal[1];
989 // Two local maxima on cathode 1 and one maximum on cathode 2
990 // Look for local maxima considering left and right neighbours on the 2nd cathode only
996 // Loop over cluster digits
997 for (i=0; i<fMul[cath]; i++) {
998 isec=Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
999 dpx=Segmentation(cath)->Dpx(isec);
1000 dpy=Segmentation(cath)->Dpy(isec);
1001 if (isLocal[i][cath]) continue;
1002 // Pad position should be consistent with position of local maxima on the opposite cathode
1003 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
1004 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.))
1007 // get neighbours for that digit and assume that it is local maximum
1008 isLocal[i][cath]=kTRUE;
1009 // compare signal to that on the two neighbours on the left and on the right
1010 Segmentation(cath)->GetPadIxy(fX[i][cath]+dpx,fY[i][cath],ix,iy);
1011 // iNN counts the number of neighbours with signal, it should be 1 or 2
1013 if (HitMap(cath)->TestHit(ix, iy)!=kEmpty) {
1015 digt=(AliMUONDigit*) HitMap(cath)->GetHit(ix,iy);
1016 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1018 Segmentation(cath)->GetPadIxy(fX[i][cath]-dpx,fY[i][cath],ix,iy);
1019 if (HitMap(cath)->TestHit(ix, iy)!=kEmpty) {
1021 digt=(AliMUONDigit*) HitMap(cath)->GetHit(ix,iy);
1022 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1024 if (isLocal[i][cath] && iNN>0) {
1025 fIndLocal[fNLocal[cath]][cath]=i;
1028 } // loop over all digits
1029 // if one additional maximum has been found we are happy
1030 // if more maxima have been found restore the previous situation
1031 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
1032 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
1033 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
1034 if (fNLocal[cath]>2) {
1035 fNLocal[cath]=iback;
1040 } // 2,1 local maxima
1044 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
1047 // Completes cluster information starting from list of digits
1054 c->fPeakSignal[cath]=c->fPeakSignal[0];
1056 c->fPeakSignal[cath]=0;
1066 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1067 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1069 dig= (AliMUONDigit*)Digits(cath)->UncheckedAt(c->fIndexMap[i][cath]);
1070 ix=dig->fPadX+c->fOffsetMap[i][cath];
1072 Int_t q=dig->fSignal;
1073 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1074 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1075 if (dig->fPhysics >= dig->fSignal) {
1076 c->fPhysicsMap[i]=2;
1077 } else if (dig->fPhysics == 0) {
1078 c->fPhysicsMap[i]=0;
1079 } else c->fPhysicsMap[i]=1;
1082 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1083 // peak signal and track list
1084 if (q>c->fPeakSignal[cath]) {
1085 c->fPeakSignal[cath]=q;
1086 c->fTracks[0]=dig->fHit;
1087 c->fTracks[1]=dig->fTracks[0];
1088 c->fTracks[2]=dig->fTracks[1];
1089 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1093 Segmentation(cath)->GetPadCxy(ix, iy, x, y);
1098 } // loop over digits
1099 // fprintf(stderr," fin du cluster c\n");
1103 c->fX[cath]/=c->fQ[cath];
1104 c->fX[cath]=Segmentation(cath)->GetAnod(c->fX[cath]);
1105 c->fY[cath]/=c->fQ[cath];
1107 // apply correction to the coordinate along the anode wire
1111 Segmentation(cath)->GetPadIxy(x, y, ix, iy);
1112 Segmentation(cath)->GetPadCxy(ix, iy, x, y);
1113 Int_t isec=Segmentation(cath)->Sector(ix,iy);
1114 TF1* cogCorr = Segmentation(cath)->CorrFunc(isec-1);
1117 Float_t yOnPad=(c->fY[cath]-y)/Segmentation(cath)->Dpy(isec);
1118 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1123 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1126 // Completes cluster information starting from list of digits
1139 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1141 dig= (AliMUONDigit*)Digits(cath)->UncheckedAt(c->fIndexMap[i][cath]);
1142 Segmentation(cath)->
1143 GetPadCxy(dig->fPadX,dig->fPadY,xpad,ypad);
1144 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1145 dx = xpad - c->fX[0];
1146 dy = ypad - c->fY[0];
1147 dr = TMath::Sqrt(dx*dx+dy*dy);
1151 fprintf(stderr," dr %f\n",dr);
1152 Int_t q=dig->fSignal;
1153 if (dig->fPhysics >= dig->fSignal) {
1154 c->fPhysicsMap[i]=2;
1155 } else if (dig->fPhysics == 0) {
1156 c->fPhysicsMap[i]=0;
1157 } else c->fPhysicsMap[i]=1;
1158 c->fPeakSignal[cath]=q;
1159 c->fTracks[0]=dig->fHit;
1160 c->fTracks[1]=dig->fTracks[0];
1161 c->fTracks[2]=dig->fTracks[1];
1162 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1165 } // loop over digits
1167 // apply correction to the coordinate along the anode wire
1168 c->fX[cath]=Segmentation(cath)->GetAnod(c->fX[cath]);
1171 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1176 // Add i,j as element of the cluster
1179 Int_t idx = HitMap(cath)->GetHitIndex(i,j);
1180 AliMUONDigit* dig = (AliMUONDigit*) HitMap(cath)->GetHit(i,j);
1181 Int_t q=dig->fSignal;
1182 Int_t theX=dig->fPadX;
1183 Int_t theY=dig->fPadY;
1184 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1185 c.fPeakSignal[cath]=q;
1186 c.fTracks[0]=dig->fHit;
1187 c.fTracks[1]=dig->fTracks[0];
1188 c.fTracks[2]=dig->fTracks[1];
1192 // Make sure that list of digits is ordered
1194 Int_t mu=c.fMultiplicity[cath];
1195 c.fIndexMap[mu][cath]=idx;
1197 if (dig->fPhysics >= dig->fSignal) {
1198 c.fPhysicsMap[mu]=2;
1199 } else if (dig->fPhysics == 0) {
1200 c.fPhysicsMap[mu]=0;
1201 } else c.fPhysicsMap[mu]=1;
1203 for (Int_t ind=mu-1; ind>=0; ind--) {
1204 Int_t ist=(c.fIndexMap)[ind][cath];
1205 Int_t ql=((AliMUONDigit*)Digits(cath)
1206 ->UncheckedAt(ist))->fSignal;
1207 Int_t ix=((AliMUONDigit*)Digits(cath)
1208 ->UncheckedAt(ist))->fPadX;
1209 Int_t iy=((AliMUONDigit*)Digits(cath)
1210 ->UncheckedAt(ist))->fPadY;
1212 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1213 c.fIndexMap[ind][cath]=idx;
1214 c.fIndexMap[ind+1][cath]=ist;
1221 c.fMultiplicity[cath]++;
1222 if (c.fMultiplicity[cath] >= 50 ) {
1223 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1224 c.fMultiplicity[cath]=49;
1227 // Prepare center of gravity calculation
1229 Segmentation(cath)->GetPadCxy(i, j, x, y);
1234 // Flag hit as taken
1235 HitMap(cath)->FlagHit(i,j);
1237 // Now look recursively for all neighbours and pad hit on opposite cathode
1239 // Loop over neighbours
1242 Int_t xList[kMaxNeighbours], yList[kMaxNeighbours];
1243 Segmentation(cath)->Neighbours(i,j,&nn,xList,yList);
1244 for (Int_t in=0; in<nn; in++) {
1247 if (HitMap(cath)->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, cath, c);
1249 // Neighbours on opposite cathode
1250 // Take into account that several pads can overlap with the present pad
1251 Float_t xmin, xmax, ymin, ymax, xc, yc;
1253 Int_t isec=Segmentation(cath)->Sector(i,j);
1256 xmin=x-Segmentation(cath)->Dpx(isec);
1257 xmax=x+Segmentation(cath)->Dpx(isec);
1260 xc+=Segmentation(iop)->Dpx(isec);
1261 Segmentation(iop)->GetPadIxy(xc,y,ix,iy);
1262 if (ix>=(Segmentation(iop)->Npx()) || (iy>=Segmentation(iop)->Npy())) continue;
1263 if (HitMap(iop)->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1267 ymin=y-Segmentation(cath)->Dpy(isec);
1268 ymax=y+Segmentation(cath)->Dpy(isec);
1271 yc+=Segmentation(iop)->Dpy(isec);
1272 Segmentation(iop)->GetPadIxy(x,yc,ix,iy);
1273 if (ix>=(Segmentation(iop)->Npx()) || (iy>=Segmentation(iop)->Npy())) continue;
1274 if (HitMap(iop)->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1279 //_____________________________________________________________________________
1281 void AliMUONClusterFinderVS::FindRawClusters()
1284 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1285 // fills the tree with raw clusters
1288 if (!NDigits(0) && !NDigits(1)) return;
1290 fHitMap = new AliMUONHitMapA1(fSegmentation , fDigits);
1291 fHitMap2 = new AliMUONHitMapA1(fSegmentation2, fDigits2);
1298 HitMap(0)->FillHits();
1299 HitMap(1)->FillHits();
1301 // Outer Loop over Cathodes
1302 for (cath=0; cath<2; cath++) {
1303 for (ndig=0; ndig<NDigits(cath); ndig++) {
1304 dig = (AliMUONDigit*)Digits(cath)->UncheckedAt(ndig);
1307 if (HitMap(cath)->TestHit(i,j)==kUsed ||fHitMap->TestHit(i,j)==kEmpty) {
1311 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1312 AliMUONRawCluster c;
1313 c.fMultiplicity[0]=0;
1314 c.fMultiplicity[1]=0;
1315 c.fPeakSignal[cath]=dig->fSignal;
1316 c.fTracks[0]=dig->fHit;
1317 c.fTracks[1]=dig->fTracks[0];
1318 c.fTracks[2]=dig->fTracks[1];
1319 // tag the beginning of cluster list in a raw cluster
1322 FindCluster(i,j,cath,c);
1324 // center of gravity
1326 c.fX[0]=Segmentation(0)->GetAnod(c.fX[0]);
1329 c.fX[1]=Segmentation(0)->GetAnod(c.fX[1]);
1331 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[0],c.fX[0],c.fY[0]);
1332 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[1],c.fX[1],c.fY[1]);
1338 fitted=SingleMathiesonFit(&c, 0);
1339 c.fX[0]=Segmentation(0)->GetAnod(c.fX[0]);
1340 fitted=SingleMathiesonFit(&c, 1);
1341 c.fX[1]=Segmentation(1)->GetAnod(c.fX[1]);
1344 // Analyse cluster and decluster if necessary
1347 c.fNcluster[1]=fNRawClusters;
1348 c.fClusterType=c.PhysicsContribution();
1354 // AddRawCluster(c);
1357 // reset Cluster object
1358 { // begin local scope
1359 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1360 } // end local scope
1362 { // begin local scope
1363 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1364 } // end local scope
1366 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1370 } // end loop cathodes
1375 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1378 // Initialise global variables for fit
1380 fMul[cath]=c->fMultiplicity[cath];
1381 fgSegmentation[0]=Segmentation(cath);
1382 fgResponse =fResponse;
1383 fgNbins[0]=fMul[cath];
1386 // dump digit information into arrays
1388 for (i=0; i<fMul[cath]; i++)
1390 fDig[i][cath]= (AliMUONDigit*)Digits(cath)->UncheckedAt(c->fIndexMap[i][cath]);
1391 fIx[i][cath]= fDig[i][cath]->fPadX;
1392 fIy[i][cath]= fDig[i][cath]->fPadY;
1393 fQ[i][cath] = fDig[i][cath]->fSignal;
1394 Segmentation(cath)->GetPadCxy(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath]);
1395 fgix[i][0]=fIx[i][cath];
1396 fgiy[i][0]=fIy[i][cath];
1397 fgCharge[i][0]=Float_t(fQ[i][cath]);
1398 qtot+=fgCharge[i][0];
1402 fgChargeTot[0]=Int_t(qtot);
1407 fgMyMinuit = new TMinuit(5);
1410 fgMyMinuit->SetFCN(fcnS1);
1411 fgMyMinuit->mninit(2,10,7);
1412 Double_t arglist[20];
1415 // fgMyMinuit->mnexcm("SET ERR",arglist,1,ierflag);
1416 // Set starting values
1417 static Double_t vstart[2];
1422 // lower and upper limits
1423 static Double_t lower[2], upper[2];
1425 Segmentation(cath)->GetPadIxy(c->fX[cath], c->fY[cath], ix, iy);
1426 Int_t isec=Segmentation(cath)->Sector(ix, iy);
1427 lower[0]=vstart[0]-Segmentation(cath)->Dpx(isec)/2;
1428 lower[1]=vstart[1]-Segmentation(cath)->Dpy(isec)/2;
1430 upper[0]=lower[0]+Segmentation(cath)->Dpx(isec);
1431 upper[1]=lower[1]+Segmentation(cath)->Dpy(isec);
1434 static Double_t step[2]={0.0005, 0.0005};
1436 fgMyMinuit->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1437 fgMyMinuit->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1438 // ready for minimisation
1439 fgMyMinuit->SetPrintLevel(1);
1440 fgMyMinuit->mnexcm("SET OUT", arglist, 0, ierflag);
1444 fgMyMinuit->mnexcm("SET NOGR", arglist, 0, ierflag);
1445 fgMyMinuit->mnexcm("MIGRAD", arglist, 0, ierflag);
1446 fgMyMinuit->mnexcm("EXIT" , arglist, 0, ierflag);
1447 Double_t fmin, fedm, errdef;
1448 Int_t npari, nparx, istat;
1450 fgMyMinuit->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1454 // Get fitted parameters
1455 Double_t xrec, yrec;
1457 Double_t epxz, b1, b2;
1459 fgMyMinuit->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1460 fgMyMinuit->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1466 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1468 // Perform combined Mathieson fit on both cathode planes
1472 fgMyMinuit = new TMinuit(5);
1475 fgMyMinuit->SetFCN(fcnCombiS1);
1476 fgMyMinuit->mninit(2,10,7);
1477 Double_t arglist[20];
1480 static Double_t vstart[2];
1481 vstart[0]=fXInit[0];
1482 vstart[1]=fYInit[0];
1485 // lower and upper limits
1486 static Double_t lower[2], upper[2];
1488 Segmentation(0)->GetPadIxy(fXInit[0], fYInit[0], ix, iy);
1489 isec=Segmentation(0)->Sector(ix, iy);
1490 Float_t dpy=Segmentation(0)->Dpy(isec)/2;
1491 Segmentation(1)->GetPadIxy(fXInit[0], fYInit[0], ix, iy);
1492 isec=Segmentation(1)->Sector(ix, iy);
1493 Float_t dpx=Segmentation(1)->Dpx(isec)/2;
1496 lower[0]=vstart[0]-dpx;
1497 lower[1]=vstart[1]-dpy;
1499 upper[0]=vstart[0]+dpx;
1500 upper[1]=vstart[1]+dpy;
1503 static Double_t step[2]={0.00001, 0.0001};
1505 fgMyMinuit->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1506 fgMyMinuit->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1507 // ready for minimisation
1508 fgMyMinuit->SetPrintLevel(1);
1509 fgMyMinuit->mnexcm("SET OUT", arglist, 0, ierflag);
1513 fgMyMinuit->mnexcm("SET NOGR", arglist, 0, ierflag);
1514 fgMyMinuit->mnexcm("MIGRAD", arglist, 0, ierflag);
1515 fgMyMinuit->mnexcm("EXIT" , arglist, 0, ierflag);
1516 Double_t fmin, fedm, errdef;
1517 Int_t npari, nparx, istat;
1519 fgMyMinuit->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1523 // Get fitted parameters
1524 Double_t xrec, yrec;
1526 Double_t epxz, b1, b2;
1528 fgMyMinuit->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1529 fgMyMinuit->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1535 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1538 // Initialise global variables for fit
1541 fgSegmentation[0]=Segmentation(cath);
1542 fgResponse =fResponse;
1543 fgNbins[0]=fMul[cath];
1546 for (i=0; i<fMul[cath]; i++) {
1547 fgix[i][0]=fIx[i][cath];
1548 fgiy[i][0]=fIy[i][cath];
1549 fgCharge[i][0]=Float_t(fQ[i][cath]);
1550 qtot+=fgCharge[i][0];
1553 fgChargeTot[0]=Int_t(qtot);
1558 fgMyMinuit = new TMinuit(5);
1560 fgMyMinuit->SetFCN(fcnS2);
1561 fgMyMinuit->mninit(5,10,7);
1562 Double_t arglist[20];
1565 // Set starting values
1566 static Double_t vstart[5];
1567 vstart[0]=fX[fIndLocal[0][cath]][cath];
1568 vstart[1]=fY[fIndLocal[0][cath]][cath];
1569 vstart[2]=fX[fIndLocal[1][cath]][cath];
1570 vstart[3]=fY[fIndLocal[1][cath]][cath];
1571 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1572 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1573 // lower and upper limits
1574 static Double_t lower[5], upper[5];
1575 Int_t isec=Segmentation(cath)->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1576 lower[0]=vstart[0]-Segmentation(cath)->Dpx(isec);
1577 lower[1]=vstart[1]-Segmentation(cath)->Dpy(isec);
1579 upper[0]=lower[0]+2.*Segmentation(cath)->Dpx(isec);
1580 upper[1]=lower[1]+2.*Segmentation(cath)->Dpy(isec);
1582 isec=Segmentation(cath)->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1583 lower[2]=vstart[2]-Segmentation(cath)->Dpx(isec)/2;
1584 lower[3]=vstart[3]-Segmentation(cath)->Dpy(isec)/2;
1586 upper[2]=lower[2]+Segmentation(cath)->Dpx(isec);
1587 upper[3]=lower[3]+Segmentation(cath)->Dpy(isec);
1592 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1594 fgMyMinuit->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1595 fgMyMinuit->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1596 fgMyMinuit->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1597 fgMyMinuit->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1598 fgMyMinuit->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1599 // ready for minimisation
1600 fgMyMinuit->SetPrintLevel(-1);
1601 fgMyMinuit->mnexcm("SET OUT", arglist, 0, ierflag);
1605 fgMyMinuit->mnexcm("SET NOGR", arglist, 0, ierflag);
1606 fgMyMinuit->mnexcm("MIGRAD", arglist, 0, ierflag);
1607 fgMyMinuit->mnexcm("EXIT" , arglist, 0, ierflag);
1608 // Get fitted parameters
1609 Double_t xrec[2], yrec[2], qfrac;
1611 Double_t epxz, b1, b2;
1613 fgMyMinuit->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1614 fgMyMinuit->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1615 fgMyMinuit->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1616 fgMyMinuit->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1617 fgMyMinuit->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1619 Double_t fmin, fedm, errdef;
1620 Int_t npari, nparx, istat;
1622 fgMyMinuit->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1627 // One cluster for each maximum
1629 for (j=0; j<2; j++) {
1630 AliMUONRawCluster cnew;
1631 cnew.fChi2[0]=Float_t(fmin);
1634 cnew.fNcluster[0]=-1;
1635 cnew.fNcluster[1]=fNRawClusters;
1637 cnew.fNcluster[0]=fNPeaks;
1638 cnew.fNcluster[1]=0;
1640 cnew.fMultiplicity[0]=0;
1641 cnew.fX[0]=Float_t(xrec[j]);
1642 cnew.fY[0]=Float_t(yrec[j]);
1644 cnew.fQ[0]=Int_t(fgChargeTot[0]*qfrac);
1646 cnew.fQ[0]=Int_t(fgChargeTot[0]*(1-qfrac));
1648 fgSegmentation[0]->SetHit(xrec[j],yrec[j]);
1649 for (i=0; i<fMul[cath]; i++) {
1650 cnew.fIndexMap[cnew.fMultiplicity[0]][cath]=c->fIndexMap[i][cath];
1651 fgSegmentation[0]->SetPad(fgix[i][0], fgiy[i][0]);
1652 Float_t q1=fgResponse->IntXY(fgSegmentation[0]);
1653 cnew.fContMap[cnew.fMultiplicity[0]][0]=(q1*cnew.fQ[0])/Float_t(fQ[i][cath]);
1654 cnew.fMultiplicity[0]++;
1656 FillCluster(&cnew,0,0);
1657 cnew.fClusterType=cnew.PhysicsContribution();
1658 AddRawCluster(cnew);
1664 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1667 // Perform combined double Mathieson fit on both cathode planes
1671 fgMyMinuit = new TMinuit(5);
1673 fgMyMinuit->SetFCN(fcnCombiS2);
1674 fgMyMinuit->mninit(6,10,7);
1675 Double_t arglist[20];
1678 // Set starting values
1679 static Double_t vstart[6];
1680 vstart[0]=fXInit[0];
1681 vstart[1]=fYInit[0];
1682 vstart[2]=fXInit[1];
1683 vstart[3]=fYInit[1];
1684 vstart[4]=fQrInit[0];
1685 vstart[5]=fQrInit[1];
1686 // lower and upper limits
1687 static Double_t lower[6], upper[6];
1691 Segmentation(1)->GetPadIxy(fXInit[0], fYInit[0], ix, iy);
1692 isec=Segmentation(1)->Sector(ix, iy);
1693 dpx=Segmentation(1)->Dpx(isec);
1695 Segmentation(0)->GetPadIxy(fXInit[0], fYInit[0], ix, iy);
1696 isec=Segmentation(0)->Sector(ix, iy);
1697 dpy=Segmentation(0)->Dpy(isec);
1699 lower[0]=vstart[0]-dpx;
1700 lower[1]=vstart[1]-dpy;
1701 upper[0]=vstart[0]+dpx;
1702 upper[1]=vstart[1]+dpy;
1705 Segmentation(1)->GetPadIxy(fXInit[1], fYInit[1], ix, iy);
1706 isec=Segmentation(1)->Sector(ix, iy);
1707 dpx=Segmentation(1)->Dpx(isec);
1708 Segmentation(0)->GetPadIxy(fXInit[1], fYInit[1], ix, iy);
1709 isec=Segmentation(0)->Sector(ix, iy);
1710 dpy=Segmentation(0)->Dpy(isec);
1712 lower[2]=vstart[2]-dpx;
1713 lower[3]=vstart[3]-dpy;
1714 upper[2]=vstart[2]+dpx;
1715 upper[3]=vstart[3]+dpy;
1724 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1726 fgMyMinuit->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1727 fgMyMinuit->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1728 fgMyMinuit->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1729 fgMyMinuit->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1730 fgMyMinuit->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1731 fgMyMinuit->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1732 // ready for minimisation
1733 fgMyMinuit->SetPrintLevel(-1);
1734 fgMyMinuit->mnexcm("SET OUT", arglist, 0, ierflag);
1738 fgMyMinuit->mnexcm("SET NOGR", arglist, 0, ierflag);
1739 fgMyMinuit->mnexcm("MIGRAD", arglist, 0, ierflag);
1740 fgMyMinuit->mnexcm("EXIT" , arglist, 0, ierflag);
1741 // Get fitted parameters
1743 Double_t epxz, b1, b2;
1745 fgMyMinuit->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1746 fgMyMinuit->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1747 fgMyMinuit->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1748 fgMyMinuit->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1749 fgMyMinuit->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1750 fgMyMinuit->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1752 Double_t fmin, fedm, errdef;
1753 Int_t npari, nparx, istat;
1755 fgMyMinuit->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1763 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1766 // One cluster for each maximum
1770 for (j=0; j<2; j++) {
1771 AliMUONRawCluster cnew;
1772 for (cath=0; cath<2; cath++) {
1773 cnew.fChi2[cath]=fChi2[0];
1776 cnew.fNcluster[0]=-1;
1777 cnew.fNcluster[1]=fNRawClusters;
1779 cnew.fNcluster[0]=fNPeaks;
1780 cnew.fNcluster[1]=0;
1782 cnew.fMultiplicity[cath]=0;
1783 cnew.fX[cath]=Float_t(fXFit[j]);
1784 cnew.fY[cath]=Float_t(fYFit[j]);
1786 cnew.fQ[cath]=Int_t(fgChargeTot[cath]*fQrFit[cath]);
1788 cnew.fQ[cath]=Int_t(fgChargeTot[cath]*(1-fQrFit[cath]));
1790 fgSegmentation[cath]->SetHit(fXFit[j],fYFit[j]);
1791 for (i=0; i<fMul[cath]; i++) {
1792 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1793 c->fIndexMap[i][cath];
1794 fgSegmentation[cath]->SetPad(fgix[i][cath], fgiy[i][cath]);
1795 Float_t q1=fgResponse->IntXY(fgSegmentation[cath]);
1796 cnew.fContMap[i][cath]
1797 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1798 cnew.fMultiplicity[cath]++;
1799 // printf(" fXFIT %f fYFIT %f Multiplicite %d\n",cnew.fX[cath],cnew.fY[cath],cnew.fMultiplicity[cath]);
1801 FillCluster(&cnew,0,cath);
1804 cnew.fClusterType=cnew.PhysicsContribution();
1805 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1811 Float_t DiscrChargeS1(Int_t i,Double_t *par)
1813 // par[0] x-position of cluster
1814 // par[1] y-position of cluster
1816 fgSegmentation[0]->SetPad(fgix[i][0], fgiy[i][0]);
1818 fgSegmentation[0]->SetHit(par[0],par[1]);
1819 Float_t q1=fgResponse->IntXY(fgSegmentation[0]);
1821 Float_t value = fgQtot[0]*q1;
1825 Float_t DiscrChargeCombiS1(Int_t i,Double_t *par, Int_t cath)
1827 // par[0] x-position of cluster
1828 // par[1] y-position of cluster
1830 fgSegmentation[cath]->SetPad(fgix[i][cath], fgiy[i][cath]);
1832 fgSegmentation[cath]->SetHit(par[0],par[1]);
1833 Float_t q1=fgResponse->IntXY(fgSegmentation[cath]);
1835 Float_t value = fgQtot[cath]*q1;
1840 Float_t DiscrChargeS2(Int_t i,Double_t *par)
1842 // par[0] x-position of first cluster
1843 // par[1] y-position of first cluster
1844 // par[2] x-position of second cluster
1845 // par[3] y-position of second cluster
1846 // par[4] charge fraction of first cluster
1847 // 1-par[4] charge fraction of second cluster
1849 fgSegmentation[0]->SetPad(fgix[i][0], fgiy[i][0]);
1851 fgSegmentation[0]->SetHit(par[0],par[1]);
1852 Float_t q1=fgResponse->IntXY(fgSegmentation[0]);
1855 fgSegmentation[0]->SetHit(par[2],par[3]);
1856 Float_t q2=fgResponse->IntXY(fgSegmentation[0]);
1858 Float_t value = fgQtot[0]*(par[4]*q1+(1.-par[4])*q2);
1862 Float_t DiscrChargeCombiS2(Int_t i,Double_t *par, Int_t cath)
1864 // par[0] x-position of first cluster
1865 // par[1] y-position of first cluster
1866 // par[2] x-position of second cluster
1867 // par[3] y-position of second cluster
1868 // par[4] charge fraction of first cluster
1869 // 1-par[4] charge fraction of second cluster
1871 fgSegmentation[cath]->SetPad(fgix[i][cath], fgiy[i][cath]);
1873 fgSegmentation[cath]->SetHit(par[0],par[1]);
1874 Float_t q1=fgResponse->IntXY(fgSegmentation[cath]);
1877 fgSegmentation[cath]->SetHit(par[2],par[3]);
1878 Float_t q2=fgResponse->IntXY(fgSegmentation[cath]);
1881 value = fgQtot[0]*(par[4]*q1+(1.-par[4])*q2);
1883 value = fgQtot[1]*(par[5]*q1+(1.-par[5])*q2);
1889 // Minimisation functions
1891 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1899 for (i=0; i<fgNbins[0]; i++) {
1900 Float_t q0=fgCharge[i][0];
1901 Float_t q1=DiscrChargeS1(i,par);
1910 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1917 // Float_t chi2temp=0;
1919 for (cath=0; cath<2; cath++) {
1921 for (i=0; i<fgNbins[cath]; i++) {
1922 Float_t q0=fgCharge[i][cath];
1923 Float_t q1=DiscrChargeCombiS1(i,par,cath);
1930 // if (cath == 0) chi2temp=chisq/fgNbins[cath];
1932 // chisq = chisq/fgNbins[1]+chi2temp;
1938 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1946 for (i=0; i<fgNbins[0]; i++) {
1948 Float_t q0=fgCharge[i][0];
1949 Float_t q1=DiscrChargeS2(i,par);
1955 // chisq=chisq+=(qtot-qcont)*(qtot-qcont)*0.5;
1960 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1967 // Float_t chi2temp=0;
1969 for (cath=0; cath<2; cath++) {
1971 for (i=0; i<fgNbins[cath]; i++) {
1972 Float_t q0=fgCharge[i][cath];
1973 Float_t q1=DiscrChargeCombiS2(i,par,cath);
1980 // if (cath == 0) chi2temp=chisq/fgNbins[cath];
1982 // chisq = chisq/fgNbins[1]+chi2temp;
1986 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1989 // Add a raw cluster copy to the list
1991 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1992 pMUON->AddRawCluster(fChamber,c);
1994 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1998 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1999 ::operator = (const AliMUONClusterFinderVS& rhs)
2001 // Dummy assignment operator