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.8 2000/07/03 11:54:57 morsch
18 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
19 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
21 Revision 1.7 2000/06/28 15:16:35 morsch
22 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
23 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
24 framework. The changes should have no side effects (mostly dummy arguments).
25 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
26 of chambers with overlapping modules (MakePadHits, Disintegration).
28 Revision 1.6 2000/06/28 12:19:18 morsch
29 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
30 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
31 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
32 It requires two cathode planes. Small modifications in the code will make it usable for
33 one cathode plane and, hence, more general (for test beam data).
34 AliMUONClusterFinder is now obsolete.
36 Revision 1.5 2000/06/28 08:06:10 morsch
37 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
38 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
39 It also naturally takes care of the TMinuit instance.
41 Revision 1.4 2000/06/27 16:18:47 gosset
42 Finally correct implementation of xm, ym, ixm, iym sizes
43 when at least three local maxima on cathode 1 or on cathode 2
45 Revision 1.3 2000/06/22 14:02:45 morsch
46 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
47 Some HP scope problems corrected (PH)
49 Revision 1.2 2000/06/15 07:58:48 morsch
50 Code from MUON-dev joined
52 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
53 Most coding rule violations corrected.
55 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
56 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
57 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
58 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
59 - For clusters with more than 2 maxima on one of the cathode planes all valid
60 combinations of maxima on the two cathodes are preserved. The position of the maxima is
61 taken as the hit position.
62 - New FillCluster method with 2 arguments to find tracks associated to the clusters
63 defined above added. (Method destinction by argument list not very elegant in this case,
64 should be revides (A.M.)
65 - Bug in if-statement to handle maximum 1 maximum per plane corrected
66 - Two cluster per cathode but only 1 combination valid is handled.
67 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
71 #include "AliMUONClusterFinderVS.h"
72 #include "AliMUONDigit.h"
73 #include "AliMUONRawCluster.h"
74 #include "AliSegmentation.h"
75 #include "AliMUONResponse.h"
76 #include "AliMUONHitMapA1.h"
85 #include <TPostScript.h>
92 //_____________________________________________________________________
93 // This function is minimized in the double-Mathieson fit
94 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
95 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
96 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
97 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
99 ClassImp(AliMUONClusterFinderVS)
101 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
103 // Default constructor
104 fInput=AliMUONClusterInput::Instance();
107 fTrack[0]=fTrack[1]=-1;
110 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
111 const AliMUONClusterFinderVS & clusterFinder)
113 // Dummy copy Constructor
117 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
119 // Decluster by local maxima
120 SplitByLocalMaxima(cluster);
123 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
125 // Split complex cluster by local maxima
129 fInput->SetCluster(c);
131 fMul[0]=c->fMultiplicity[0];
132 fMul[1]=c->fMultiplicity[1];
135 // dump digit information into arrays
140 for (cath=0; cath<2; cath++) {
142 for (i=0; i<fMul[cath]; i++)
145 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
147 fIx[i][cath]= fDig[i][cath]->fPadX;
148 fIy[i][cath]= fDig[i][cath]->fPadY;
150 fQ[i][cath] = fDig[i][cath]->fSignal;
151 // pad centre coordinates
152 fInput->Segmentation(cath)->
153 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], zdum);
154 } // loop over cluster digits
155 } // loop over cathodes
161 // Initialise and perform mathieson fits
162 Float_t chi2, oldchi2;
163 // ++++++++++++++++++*************+++++++++++++++++++++
164 // (1) No more than one local maximum per cathode plane
165 // +++++++++++++++++++++++++++++++*************++++++++
166 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
167 (fNLocal[0]==0 && fNLocal[1]==1)) {
169 // Perform combined single Mathieson fit
170 // Initial values for coordinates (x,y)
172 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
173 if (fNLocal[0]==1 && fNLocal[1]==1) {
176 // One local maximum on cathode 1 (X,Y->cathode 1)
177 } else if (fNLocal[0]==1) {
180 // One local maximum on cathode 2 (X,Y->cathode 2)
185 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
186 chi2=CombiSingleMathiesonFit(c);
187 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
188 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
189 // prob1->Fill(prob);
190 // chi2_1->Fill(chi2);
192 fprintf(stderr," chi2 %f ",chi2);
201 c->fX[0]=fInput->Segmentation(0)->GetAnod(c->fX[0]);
202 c->fX[1]=fInput->Segmentation(1)->GetAnod(c->fX[1]);
204 // If reasonable chi^2 add result to the list of rawclusters
208 // If not try combined double Mathieson Fit
210 fprintf(stderr," MAUVAIS CHI2 !!!\n");
211 if (fNLocal[0]==1 && fNLocal[1]==1) {
212 fXInit[0]=fX[fIndLocal[0][1]][1];
213 fYInit[0]=fY[fIndLocal[0][0]][0];
214 fXInit[1]=fX[fIndLocal[0][1]][1];
215 fYInit[1]=fY[fIndLocal[0][0]][0];
216 } else if (fNLocal[0]==1) {
217 fXInit[0]=fX[fIndLocal[0][0]][0];
218 fYInit[0]=fY[fIndLocal[0][0]][0];
219 fXInit[1]=fX[fIndLocal[0][0]][0];
220 fYInit[1]=fY[fIndLocal[0][0]][0];
222 fXInit[0]=fX[fIndLocal[0][1]][1];
223 fYInit[0]=fY[fIndLocal[0][1]][1];
224 fXInit[1]=fX[fIndLocal[0][1]][1];
225 fYInit[1]=fY[fIndLocal[0][1]][1];
228 // Initial value for charge ratios
231 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
232 chi2=CombiDoubleMathiesonFit(c);
233 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
234 // Float_t prob = TMath::Prob(chi2,ndf);
235 // prob2->Fill(prob);
236 // chi2_2->Fill(chi2);
238 // Was this any better ??
239 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
240 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
241 fprintf(stderr," Split\n");
242 // Split cluster into two according to fit result
245 fprintf(stderr," Don't Split\n");
251 // +++++++++++++++++++++++++++++++++++++++
252 // (2) Two local maxima per cathode plane
253 // +++++++++++++++++++++++++++++++++++++++
254 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
256 // Let's look for ghosts first
258 Float_t xm[4][2], ym[4][2];
259 Float_t dpx, dpy, dx, dy;
260 Int_t ixm[4][2], iym[4][2];
261 Int_t isec, im1, im2, ico;
263 // Form the 2x2 combinations
264 // 0-0, 0-1, 1-0, 1-1
266 for (im1=0; im1<2; im1++) {
267 for (im2=0; im2<2; im2++) {
268 xm[ico][0]=fX[fIndLocal[im1][0]][0];
269 ym[ico][0]=fY[fIndLocal[im1][0]][0];
270 xm[ico][1]=fX[fIndLocal[im2][1]][1];
271 ym[ico][1]=fY[fIndLocal[im2][1]][1];
273 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
274 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
275 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
276 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
280 // ico = 0 : first local maximum on cathodes 1 and 2
281 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
282 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
283 // ico = 3 : second local maximum on cathodes 1 and 2
285 // Analyse the combinations and keep those that are possible !
286 // For each combination check consistency in x and y
291 for (ico=0; ico<4; ico++) {
292 accepted[ico]=kFALSE;
293 // cathode one: x-coordinate
294 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
295 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
296 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
297 // cathode two: y-coordinate
298 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
299 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
300 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
301 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
302 if ((dx <= dpx) && (dy <= dpy)) {
308 accepted[ico]=kFALSE;
313 fprintf(stderr,"\n iacc=2: No problem ! \n");
314 } else if (iacc==4) {
315 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
316 } else if (iacc==0) {
317 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
320 // Initial value for charge ratios
321 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
322 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
323 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
324 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
326 // ******* iacc = 0 *******
327 // No combinations found between the 2 cathodes
328 // We keep the center of gravity of the cluster
333 // ******* iacc = 1 *******
334 // Only one combination found between the 2 cathodes
337 // Initial values for the 2 maxima (x,y)
339 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
340 // 1 maximum is initialised with the other maximum of the first cathode
342 fprintf(stderr,"ico=0\n");
347 } else if (accepted[1]){
348 fprintf(stderr,"ico=1\n");
353 } else if (accepted[2]){
354 fprintf(stderr,"ico=2\n");
359 } else if (accepted[3]){
360 fprintf(stderr,"ico=3\n");
366 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
367 chi2=CombiDoubleMathiesonFit(c);
368 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
369 // Float_t prob = TMath::Prob(chi2,ndf);
370 // prob2->Fill(prob);
371 // chi2_2->Fill(chi2);
372 fprintf(stderr," chi2 %f\n",chi2);
374 // If reasonable chi^2 add result to the list of rawclusters
379 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
380 // 1 maximum is initialised with the other maximum of the second cathode
382 fprintf(stderr,"ico=0\n");
387 } else if (accepted[1]){
388 fprintf(stderr,"ico=1\n");
393 } else if (accepted[2]){
394 fprintf(stderr,"ico=2\n");
399 } else if (accepted[3]){
400 fprintf(stderr,"ico=3\n");
406 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
407 chi2=CombiDoubleMathiesonFit(c);
408 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
409 // Float_t prob = TMath::Prob(chi2,ndf);
410 // prob2->Fill(prob);
411 // chi2_2->Fill(chi2);
412 fprintf(stderr," chi2 %f\n",chi2);
414 // If reasonable chi^2 add result to the list of rawclusters
418 //We keep only the combination found (X->cathode 2, Y->cathode 1)
419 for (Int_t ico=0; ico<2; ico++) {
421 AliMUONRawCluster cnew;
423 for (cath=0; cath<2; cath++) {
424 cnew.fX[cath]=Float_t(xm[ico][1]);
425 cnew.fY[cath]=Float_t(ym[ico][0]);
426 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
427 for (i=0; i<fMul[cath]; i++) {
428 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
429 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
431 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
432 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
433 FillCluster(&cnew,cath);
435 cnew.fClusterType=cnew.PhysicsContribution();
444 // ******* iacc = 2 *******
445 // Two combinations found between the 2 cathodes
448 // Was the same maximum taken twice
449 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
450 fprintf(stderr,"\n Maximum taken twice !!!\n");
452 // Have a try !! with that
453 if (accepted[0]&&accepted[3]) {
464 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
465 chi2=CombiDoubleMathiesonFit(c);
466 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
467 // Float_t prob = TMath::Prob(chi2,ndf);
468 // prob2->Fill(prob);
469 // chi2_2->Fill(chi2);
473 // No ghosts ! No Problems ! - Perform one fit only !
474 if (accepted[0]&&accepted[3]) {
485 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
486 chi2=CombiDoubleMathiesonFit(c);
487 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
488 // Float_t prob = TMath::Prob(chi2,ndf);
489 // prob2->Fill(prob);
490 // chi2_2->Fill(chi2);
491 fprintf(stderr," chi2 %f\n",chi2);
495 // ******* iacc = 4 *******
496 // Four combinations found between the 2 cathodes
498 } else if (iacc==4) {
499 // Perform fits for the two possibilities !!
504 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
505 chi2=CombiDoubleMathiesonFit(c);
506 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
507 // Float_t prob = TMath::Prob(chi2,ndf);
508 // prob2->Fill(prob);
509 // chi2_2->Fill(chi2);
510 fprintf(stderr," chi2 %f\n",chi2);
516 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
517 chi2=CombiDoubleMathiesonFit(c);
518 // ndf = fgNbins[0]+fgNbins[1]-6;
519 // prob = TMath::Prob(chi2,ndf);
520 // prob2->Fill(prob);
521 // chi2_2->Fill(chi2);
522 fprintf(stderr," chi2 %f\n",chi2);
526 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
527 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
528 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
529 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
531 Float_t xm[4][2], ym[4][2];
532 Float_t dpx, dpy, dx, dy;
533 Int_t ixm[4][2], iym[4][2];
534 Int_t isec, im1, ico;
536 // Form the 2x2 combinations
537 // 0-0, 0-1, 1-0, 1-1
539 for (im1=0; im1<2; im1++) {
540 xm[ico][0]=fX[fIndLocal[im1][0]][0];
541 ym[ico][0]=fY[fIndLocal[im1][0]][0];
542 xm[ico][1]=fX[fIndLocal[0][1]][1];
543 ym[ico][1]=fY[fIndLocal[0][1]][1];
545 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
546 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
547 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
548 iym[ico][1]=fIy[fIndLocal[0][1]][1];
551 // ico = 0 : first local maximum on cathodes 1 and 2
552 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
554 // Analyse the combinations and keep those that are possible !
555 // For each combination check consistency in x and y
560 for (ico=0; ico<2; ico++) {
561 accepted[ico]=kFALSE;
562 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
563 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
564 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
565 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
566 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
567 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
568 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
569 if ((dx <= dpx) && (dy <= dpy)) {
575 accepted[ico]=kFALSE;
587 chi21=CombiDoubleMathiesonFit(c);
588 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
589 // Float_t prob = TMath::Prob(chi2,ndf);
590 // prob2->Fill(prob);
591 // chi2_2->Fill(chi21);
592 fprintf(stderr," chi2 %f\n",chi21);
593 if (chi21<10) Split(c);
594 } else if (accepted[1]) {
599 chi22=CombiDoubleMathiesonFit(c);
600 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
601 // Float_t prob = TMath::Prob(chi2,ndf);
602 // prob2->Fill(prob);
603 // chi2_2->Fill(chi22);
604 fprintf(stderr," chi2 %f\n",chi22);
605 if (chi22<10) Split(c);
608 if (chi21 > 10 && chi22 > 10) {
609 // We keep only the combination found (X->cathode 2, Y->cathode 1)
610 for (Int_t ico=0; ico<2; ico++) {
612 AliMUONRawCluster cnew;
614 for (cath=0; cath<2; cath++) {
615 cnew.fX[cath]=Float_t(xm[ico][1]);
616 cnew.fY[cath]=Float_t(ym[ico][0]);
617 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
618 for (i=0; i<fMul[cath]; i++) {
619 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
620 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
622 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
623 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
624 FillCluster(&cnew,cath);
626 cnew.fClusterType=cnew.PhysicsContribution();
633 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
634 // (3') One local maximum on cathode 1 and two maxima on cathode 2
635 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
636 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
638 Float_t xm[4][2], ym[4][2];
639 Float_t dpx, dpy, dx, dy;
640 Int_t ixm[4][2], iym[4][2];
641 Int_t isec, im1, ico;
643 // Form the 2x2 combinations
644 // 0-0, 0-1, 1-0, 1-1
646 for (im1=0; im1<2; im1++) {
647 xm[ico][0]=fX[fIndLocal[0][0]][0];
648 ym[ico][0]=fY[fIndLocal[0][0]][0];
649 xm[ico][1]=fX[fIndLocal[im1][1]][1];
650 ym[ico][1]=fY[fIndLocal[im1][1]][1];
652 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
653 iym[ico][0]=fIy[fIndLocal[0][0]][0];
654 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
655 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
658 // ico = 0 : first local maximum on cathodes 1 and 2
659 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
661 // Analyse the combinations and keep those that are possible !
662 // For each combination check consistency in x and y
667 for (ico=0; ico<2; ico++) {
668 accepted[ico]=kFALSE;
669 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
670 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
671 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
672 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
673 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
674 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
675 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
676 if ((dx <= dpx) && (dy <= dpy)) {
679 fprintf(stderr,"ico %d\n",ico);
683 accepted[ico]=kFALSE;
695 chi21=CombiDoubleMathiesonFit(c);
696 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
697 // Float_t prob = TMath::Prob(chi2,ndf);
698 // prob2->Fill(prob);
699 // chi2_2->Fill(chi21);
700 fprintf(stderr," chi2 %f\n",chi21);
701 if (chi21<10) Split(c);
702 } else if (accepted[1]) {
707 chi22=CombiDoubleMathiesonFit(c);
708 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
709 // Float_t prob = TMath::Prob(chi2,ndf);
710 // prob2->Fill(prob);
711 // chi2_2->Fill(chi22);
712 fprintf(stderr," chi2 %f\n",chi22);
713 if (chi22<10) Split(c);
716 if (chi21 > 10 && chi22 > 10) {
717 //We keep only the combination found (X->cathode 2, Y->cathode 1)
718 for (Int_t ico=0; ico<2; ico++) {
720 AliMUONRawCluster cnew;
722 for (cath=0; cath<2; cath++) {
723 cnew.fX[cath]=Float_t(xm[ico][1]);
724 cnew.fY[cath]=Float_t(ym[ico][0]);
725 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
726 for (i=0; i<fMul[cath]; i++) {
727 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
728 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
730 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
731 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
732 FillCluster(&cnew,cath);
734 cnew.fClusterType=cnew.PhysicsContribution();
741 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
742 // (4) At least three local maxima on cathode 1 or on cathode 2
743 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
744 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
746 Int_t param = fNLocal[0]*fNLocal[1];
749 Float_t ** xm = new Float_t * [param];
750 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
751 Float_t ** ym = new Float_t * [param];
752 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
753 Int_t ** ixm = new Int_t * [param];
754 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
755 Int_t ** iym = new Int_t * [param];
756 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
759 Float_t dpx, dpy, dx, dy;
762 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
763 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
764 xm[ico][0]=fX[fIndLocal[im1][0]][0];
765 ym[ico][0]=fY[fIndLocal[im1][0]][0];
766 xm[ico][1]=fX[fIndLocal[im2][1]][1];
767 ym[ico][1]=fY[fIndLocal[im2][1]][1];
769 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
770 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
771 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
772 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
779 fprintf(stderr,"nIco %d\n",nIco);
780 for (ico=0; ico<nIco; ico++) {
781 fprintf(stderr,"ico = %d\n",ico);
782 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
783 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
784 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
785 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
786 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
787 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
789 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
790 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
791 if ((dx <= dpx) && (dy <= dpy)) {
792 fprintf(stderr,"ok\n");
794 AliMUONRawCluster cnew;
795 for (cath=0; cath<2; cath++) {
796 cnew.fX[cath]=Float_t(xm[ico][1]);
797 cnew.fY[cath]=Float_t(ym[ico][0]);
798 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
799 for (i=0; i<fMul[cath]; i++) {
800 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
801 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
803 FillCluster(&cnew,cath);
805 cnew.fClusterType=cnew.PhysicsContribution();
817 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
819 // Find all local maxima of a cluster
823 Int_t cath, cath1; // loops over cathodes
824 Int_t i; // loops over digits
825 Int_t j; // loops over cathodes
829 // counters for number of local maxima
830 fNLocal[0]=fNLocal[1]=0;
831 // flags digits as local maximum
832 Bool_t isLocal[100][2];
833 for (i=0; i<100;i++) {
834 isLocal[i][0]=isLocal[i][1]=kFALSE;
836 // number of next neighbours and arrays to store them
839 // loop over cathodes
840 for (cath=0; cath<2; cath++) {
841 // loop over cluster digits
842 for (i=0; i<fMul[cath]; i++) {
843 // get neighbours for that digit and assume that it is local maximum
844 fInput->Segmentation(cath)->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
845 isLocal[i][cath]=kTRUE;
846 Int_t isec= fInput->Segmentation(cath)->Sector(fIx[i][cath], fIy[i][cath]);
847 Float_t a0 = fInput->Segmentation(cath)->Dpx(isec)*fInput->Segmentation(cath)->Dpy(isec);
848 // loop over next neighbours, if at least one neighbour has higher charger assumption
849 // digit is not local maximum
850 for (j=0; j<nn; j++) {
851 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
852 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
853 isec=fInput->Segmentation(cath)->Sector(x[j], y[j]);
854 Float_t a1 = fInput->Segmentation(cath)->Dpx(isec)*fInput->Segmentation(cath)->Dpy(isec);
855 if (digt->fSignal/a1 > fQ[i][cath]/a0) {
856 isLocal[i][cath]=kFALSE;
859 // handle special case of neighbouring pads with equal signal
860 } else if (digt->fSignal == fQ[i][cath]) {
861 if (fNLocal[cath]>0) {
862 for (Int_t k=0; k<fNLocal[cath]; k++) {
863 if (x[j]==fIx[fIndLocal[k][cath]][cath]
864 && y[j]==fIy[fIndLocal[k][cath]][cath])
866 isLocal[i][cath]=kFALSE;
868 } // loop over local maxima
869 } // are there already local maxima
871 } // loop over next neighbours
872 if (isLocal[i][cath]) {
873 fIndLocal[fNLocal[cath]][cath]=i;
876 } // loop over all digits
877 } // loop over cathodes
879 printf("\n Found %d %d %d %d local Maxima\n",
880 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
881 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
882 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
887 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
888 Int_t iback=fNLocal[0];
890 // Two local maxima on cathode 2 and one maximum on cathode 1
891 // Look for local maxima considering up and down neighbours on the 1st cathode only
893 // Loop over cluster digits
897 for (i=0; i<fMul[cath]; i++) {
898 isec=fInput->Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
899 dpy=fInput->Segmentation(cath)->Dpy(isec);
900 dpx=fInput->Segmentation(cath)->Dpx(isec);
901 if (isLocal[i][cath]) continue;
902 // Pad position should be consistent with position of local maxima on the opposite cathode
903 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
904 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
907 // get neighbours for that digit and assume that it is local maximum
908 isLocal[i][cath]=kTRUE;
909 // compare signal to that on the two neighbours on the left and on the right
910 fInput->Segmentation(cath)->GetPadI(fX[i][cath],fY[i][cath]+dpy,0,ix,iy);
911 // iNN counts the number of neighbours with signal, it should be 1 or 2
913 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
915 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
916 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
918 fInput->Segmentation(cath)->GetPadI(fX[i][cath],fY[i][cath]-dpy,0,ix,iy);
919 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
921 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
922 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
924 if (isLocal[i][cath] && iNN>0) {
925 fIndLocal[fNLocal[cath]][cath]=i;
928 } // loop over all digits
929 // if one additional maximum has been found we are happy
930 // if more maxima have been found restore the previous situation
931 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
932 fprintf(stderr," %d local maxima for cathode 2 \n",fNLocal[1]);
933 if (fNLocal[cath]>2) {
937 } // 1,2 local maxima
939 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
940 Int_t iback=fNLocal[1];
942 // Two local maxima on cathode 1 and one maximum on cathode 2
943 // Look for local maxima considering left and right neighbours on the 2nd cathode only
949 // Loop over cluster digits
950 for (i=0; i<fMul[cath]; i++) {
951 isec=fInput->Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
952 dpx=fInput->Segmentation(cath)->Dpx(isec);
953 dpy=fInput->Segmentation(cath)->Dpy(isec);
954 if (isLocal[i][cath]) continue;
955 // Pad position should be consistent with position of local maxima on the opposite cathode
956 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
957 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.))
960 // get neighbours for that digit and assume that it is local maximum
961 isLocal[i][cath]=kTRUE;
962 // compare signal to that on the two neighbours on the left and on the right
963 fInput->Segmentation(cath)->GetPadI(fX[i][cath]+dpx,fY[i][cath],0,ix,iy);
964 // iNN counts the number of neighbours with signal, it should be 1 or 2
966 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
968 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
969 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
971 fInput->Segmentation(cath)->GetPadI(fX[i][cath]-dpx,fY[i][cath],0,ix,iy);
972 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
974 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
975 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
977 if (isLocal[i][cath] && iNN>0) {
978 fIndLocal[fNLocal[cath]][cath]=i;
981 } // loop over all digits
982 // if one additional maximum has been found we are happy
983 // if more maxima have been found restore the previous situation
984 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
985 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
986 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
987 if (fNLocal[cath]>2) {
993 } // 2,1 local maxima
997 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
1000 // Completes cluster information starting from list of digits
1007 c->fPeakSignal[cath]=c->fPeakSignal[0];
1009 c->fPeakSignal[cath]=0;
1019 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1020 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1022 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1023 ix=dig->fPadX+c->fOffsetMap[i][cath];
1025 Int_t q=dig->fSignal;
1026 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1027 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1028 if (dig->fPhysics >= dig->fSignal) {
1029 c->fPhysicsMap[i]=2;
1030 } else if (dig->fPhysics == 0) {
1031 c->fPhysicsMap[i]=0;
1032 } else c->fPhysicsMap[i]=1;
1035 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1036 // peak signal and track list
1037 if (q>c->fPeakSignal[cath]) {
1038 c->fPeakSignal[cath]=q;
1039 c->fTracks[0]=dig->fHit;
1040 c->fTracks[1]=dig->fTracks[0];
1041 c->fTracks[2]=dig->fTracks[1];
1042 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1046 fInput->Segmentation(cath)->GetPadC(ix, iy, x, y, z);
1051 } // loop over digits
1052 // fprintf(stderr," fin du cluster c\n");
1056 c->fX[cath]/=c->fQ[cath];
1057 c->fX[cath]=fInput->Segmentation(cath)->GetAnod(c->fX[cath]);
1058 c->fY[cath]/=c->fQ[cath];
1060 // apply correction to the coordinate along the anode wire
1064 fInput->Segmentation(cath)->GetPadI(x, y, 0, ix, iy);
1065 fInput->Segmentation(cath)->GetPadC(ix, iy, x, y, z);
1066 Int_t isec=fInput->Segmentation(cath)->Sector(ix,iy);
1067 TF1* cogCorr = fInput->Segmentation(cath)->CorrFunc(isec-1);
1070 Float_t yOnPad=(c->fY[cath]-y)/fInput->Segmentation(cath)->Dpy(isec);
1071 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1076 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1079 // Completes cluster information starting from list of digits
1089 Float_t xpad, ypad, zpad;
1092 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1094 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1095 fInput->Segmentation(cath)->
1096 GetPadC(dig->fPadX,dig->fPadY,xpad,ypad, zpad);
1097 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1098 dx = xpad - c->fX[0];
1099 dy = ypad - c->fY[0];
1100 dr = TMath::Sqrt(dx*dx+dy*dy);
1104 fprintf(stderr," dr %f\n",dr);
1105 Int_t q=dig->fSignal;
1106 if (dig->fPhysics >= dig->fSignal) {
1107 c->fPhysicsMap[i]=2;
1108 } else if (dig->fPhysics == 0) {
1109 c->fPhysicsMap[i]=0;
1110 } else c->fPhysicsMap[i]=1;
1111 c->fPeakSignal[cath]=q;
1112 c->fTracks[0]=dig->fHit;
1113 c->fTracks[1]=dig->fTracks[0];
1114 c->fTracks[2]=dig->fTracks[1];
1115 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1118 } // loop over digits
1120 // apply correction to the coordinate along the anode wire
1121 c->fX[cath]=fInput->Segmentation(cath)->GetAnod(c->fX[cath]);
1124 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1129 // Add i,j as element of the cluster
1132 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1133 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1134 Int_t q=dig->fSignal;
1135 Int_t theX=dig->fPadX;
1136 Int_t theY=dig->fPadY;
1137 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1138 c.fPeakSignal[cath]=q;
1139 c.fTracks[0]=dig->fHit;
1140 c.fTracks[1]=dig->fTracks[0];
1141 c.fTracks[2]=dig->fTracks[1];
1145 // Make sure that list of digits is ordered
1147 Int_t mu=c.fMultiplicity[cath];
1148 c.fIndexMap[mu][cath]=idx;
1150 if (dig->fPhysics >= dig->fSignal) {
1151 c.fPhysicsMap[mu]=2;
1152 } else if (dig->fPhysics == 0) {
1153 c.fPhysicsMap[mu]=0;
1154 } else c.fPhysicsMap[mu]=1;
1156 for (Int_t ind=mu-1; ind>=0; ind--) {
1157 Int_t ist=(c.fIndexMap)[ind][cath];
1158 Int_t ql=fInput->Digit(cath, ist)->fSignal;
1159 Int_t ix=fInput->Digit(cath, ist)->fPadX;
1160 Int_t iy=fInput->Digit(cath, ist)->fPadY;
1162 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1163 c.fIndexMap[ind][cath]=idx;
1164 c.fIndexMap[ind+1][cath]=ist;
1171 c.fMultiplicity[cath]++;
1172 if (c.fMultiplicity[cath] >= 50 ) {
1173 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1174 c.fMultiplicity[cath]=49;
1177 // Prepare center of gravity calculation
1179 fInput->Segmentation(cath)->GetPadC(i, j, x, y, z);
1184 // Flag hit as taken
1185 fHitMap[cath]->FlagHit(i,j);
1187 // Now look recursively for all neighbours and pad hit on opposite cathode
1189 // Loop over neighbours
1192 Int_t xList[10], yList[10];
1193 fInput->Segmentation(cath)->Neighbours(i,j,&nn,xList,yList);
1194 for (Int_t in=0; in<nn; in++) {
1197 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, cath, c);
1199 // Neighbours on opposite cathode
1200 // Take into account that several pads can overlap with the present pad
1201 Float_t xmin, xmax, ymin, ymax, xc, yc;
1203 Int_t isec=fInput->Segmentation(cath)->Sector(i,j);
1206 xmin=x-fInput->Segmentation(cath)->Dpx(isec);
1207 xmax=x+fInput->Segmentation(cath)->Dpx(isec);
1210 xc+=fInput->Segmentation(iop)->Dpx(isec);
1211 fInput->Segmentation(iop)->GetPadI(xc,y,0,ix,iy);
1212 if (ix>=(fInput->Segmentation(iop)->Npx()) || (iy>=fInput->Segmentation(iop)->Npy())) continue;
1213 if (fHitMap[iop]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1217 ymin=y-fInput->Segmentation(cath)->Dpy(isec);
1218 ymax=y+fInput->Segmentation(cath)->Dpy(isec);
1221 yc+=fInput->Segmentation(iop)->Dpy(isec);
1222 fInput->Segmentation(iop)->GetPadI(x,yc,0,ix,iy);
1223 if (ix>=(fInput->Segmentation(iop)->Npx()) || (iy>=fInput->Segmentation(iop)->Npy())) continue;
1224 if (fHitMap[iop]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1229 //_____________________________________________________________________________
1231 void AliMUONClusterFinderVS::FindRawClusters()
1234 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1235 // fills the tree with raw clusters
1238 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1240 fHitMap[0] = new AliMUONHitMapA1(fInput->Segmentation(0), fInput->Digits(0));
1241 fHitMap[1] = new AliMUONHitMapA1(fInput->Segmentation(1), fInput->Digits(1));
1248 fHitMap[0]->FillHits();
1249 fHitMap[1]->FillHits();
1251 // Outer Loop over Cathodes
1252 for (cath=0; cath<2; cath++) {
1253 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1254 dig = fInput->Digit(cath, ndig);
1257 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1261 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1262 AliMUONRawCluster c;
1263 c.fMultiplicity[0]=0;
1264 c.fMultiplicity[1]=0;
1265 c.fPeakSignal[cath]=dig->fSignal;
1266 c.fTracks[0]=dig->fHit;
1267 c.fTracks[1]=dig->fTracks[0];
1268 c.fTracks[2]=dig->fTracks[1];
1269 // tag the beginning of cluster list in a raw cluster
1272 FindCluster(i,j,cath,c);
1274 // center of gravity
1276 c.fX[0]=fInput->Segmentation(0)->GetAnod(c.fX[0]);
1279 c.fX[1]=fInput->Segmentation(0)->GetAnod(c.fX[1]);
1281 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[0],c.fX[0],c.fY[0]);
1282 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[1],c.fX[1],c.fY[1]);
1288 fitted=SingleMathiesonFit(&c, 0);
1289 c.fX[0]=fInput->Segmentation(0)->GetAnod(c.fX[0]);
1290 fitted=SingleMathiesonFit(&c, 1);
1291 c.fX[1]=fInput->Segmentation(1)->GetAnod(c.fX[1]);
1294 // Analyse cluster and decluster if necessary
1297 c.fNcluster[1]=fNRawClusters;
1298 c.fClusterType=c.PhysicsContribution();
1304 // AddRawCluster(c);
1307 // reset Cluster object
1308 { // begin local scope
1309 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1310 } // end local scope
1312 { // begin local scope
1313 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1314 } // end local scope
1316 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1320 } // end loop cathodes
1325 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1328 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1330 clusterInput.Fitter()->SetFCN(fcnS1);
1331 clusterInput.Fitter()->mninit(2,10,7);
1332 Double_t arglist[20];
1335 // clusterInput.Fitter()->mnexcm("SET ERR",arglist,1,ierflag);
1336 // Set starting values
1337 static Double_t vstart[2];
1342 // lower and upper limits
1343 static Double_t lower[2], upper[2];
1345 fInput->Segmentation(cath)->GetPadI(c->fX[cath], c->fY[cath], 0, ix, iy);
1346 Int_t isec=fInput->Segmentation(cath)->Sector(ix, iy);
1347 lower[0]=vstart[0]-fInput->Segmentation(cath)->Dpx(isec)/2;
1348 lower[1]=vstart[1]-fInput->Segmentation(cath)->Dpy(isec)/2;
1350 upper[0]=lower[0]+fInput->Segmentation(cath)->Dpx(isec);
1351 upper[1]=lower[1]+fInput->Segmentation(cath)->Dpy(isec);
1354 static Double_t step[2]={0.0005, 0.0005};
1356 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1357 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1358 // ready for minimisation
1359 clusterInput.Fitter()->SetPrintLevel(1);
1360 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1364 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1365 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1366 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1367 Double_t fmin, fedm, errdef;
1368 Int_t npari, nparx, istat;
1370 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1374 // Get fitted parameters
1375 Double_t xrec, yrec;
1377 Double_t epxz, b1, b2;
1379 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1380 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1386 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1388 // Perform combined Mathieson fit on both cathode planes
1390 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1391 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1392 clusterInput.Fitter()->mninit(2,10,7);
1393 Double_t arglist[20];
1396 static Double_t vstart[2];
1397 vstart[0]=fXInit[0];
1398 vstart[1]=fYInit[0];
1401 // lower and upper limits
1402 static Double_t lower[2], upper[2];
1404 fInput->Segmentation(0)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1405 isec=fInput->Segmentation(0)->Sector(ix, iy);
1406 Float_t dpy=fInput->Segmentation(0)->Dpy(isec)/2;
1407 fInput->Segmentation(1)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1408 isec=fInput->Segmentation(1)->Sector(ix, iy);
1409 Float_t dpx=fInput->Segmentation(1)->Dpx(isec)/2;
1412 lower[0]=vstart[0]-dpx;
1413 lower[1]=vstart[1]-dpy;
1415 upper[0]=vstart[0]+dpx;
1416 upper[1]=vstart[1]+dpy;
1419 static Double_t step[2]={0.00001, 0.0001};
1421 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1422 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1423 // ready for minimisation
1424 clusterInput.Fitter()->SetPrintLevel(1);
1425 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1429 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1430 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1431 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1432 Double_t fmin, fedm, errdef;
1433 Int_t npari, nparx, istat;
1435 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1439 // Get fitted parameters
1440 Double_t xrec, yrec;
1442 Double_t epxz, b1, b2;
1444 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1445 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1451 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1454 // Initialise global variables for fit
1455 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1456 clusterInput.Fitter()->SetFCN(fcnS2);
1457 clusterInput.Fitter()->mninit(5,10,7);
1458 Double_t arglist[20];
1461 // Set starting values
1462 static Double_t vstart[5];
1463 vstart[0]=fX[fIndLocal[0][cath]][cath];
1464 vstart[1]=fY[fIndLocal[0][cath]][cath];
1465 vstart[2]=fX[fIndLocal[1][cath]][cath];
1466 vstart[3]=fY[fIndLocal[1][cath]][cath];
1467 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1468 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1469 // lower and upper limits
1470 static Double_t lower[5], upper[5];
1471 Int_t isec=fInput->Segmentation(cath)->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1472 lower[0]=vstart[0]-fInput->Segmentation(cath)->Dpx(isec);
1473 lower[1]=vstart[1]-fInput->Segmentation(cath)->Dpy(isec);
1475 upper[0]=lower[0]+2.*fInput->Segmentation(cath)->Dpx(isec);
1476 upper[1]=lower[1]+2.*fInput->Segmentation(cath)->Dpy(isec);
1478 isec=fInput->Segmentation(cath)->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1479 lower[2]=vstart[2]-fInput->Segmentation(cath)->Dpx(isec)/2;
1480 lower[3]=vstart[3]-fInput->Segmentation(cath)->Dpy(isec)/2;
1482 upper[2]=lower[2]+fInput->Segmentation(cath)->Dpx(isec);
1483 upper[3]=lower[3]+fInput->Segmentation(cath)->Dpy(isec);
1488 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1490 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1491 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1492 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1493 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1494 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1495 // ready for minimisation
1496 clusterInput.Fitter()->SetPrintLevel(-1);
1497 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1501 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1502 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1503 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1504 // Get fitted parameters
1505 Double_t xrec[2], yrec[2], qfrac;
1507 Double_t epxz, b1, b2;
1509 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1510 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1511 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1512 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1513 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1515 Double_t fmin, fedm, errdef;
1516 Int_t npari, nparx, istat;
1518 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1523 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1526 // Perform combined double Mathieson fit on both cathode planes
1528 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1529 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1530 clusterInput.Fitter()->mninit(6,10,7);
1531 Double_t arglist[20];
1534 // Set starting values
1535 static Double_t vstart[6];
1536 vstart[0]=fXInit[0];
1537 vstart[1]=fYInit[0];
1538 vstart[2]=fXInit[1];
1539 vstart[3]=fYInit[1];
1540 vstart[4]=fQrInit[0];
1541 vstart[5]=fQrInit[1];
1542 // lower and upper limits
1543 static Double_t lower[6], upper[6];
1547 fInput->Segmentation(1)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1548 isec=fInput->Segmentation(1)->Sector(ix, iy);
1549 dpx=fInput->Segmentation(1)->Dpx(isec);
1551 fInput->Segmentation(0)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1552 isec=fInput->Segmentation(0)->Sector(ix, iy);
1553 dpy=fInput->Segmentation(0)->Dpy(isec);
1555 lower[0]=vstart[0]-dpx;
1556 lower[1]=vstart[1]-dpy;
1557 upper[0]=vstart[0]+dpx;
1558 upper[1]=vstart[1]+dpy;
1561 fInput->Segmentation(1)->GetPadI(fXInit[1], fYInit[1], 0, ix, iy);
1562 isec=fInput->Segmentation(1)->Sector(ix, iy);
1563 dpx=fInput->Segmentation(1)->Dpx(isec);
1564 fInput->Segmentation(0)->GetPadI(fXInit[1], fYInit[1], 0, ix, iy);
1565 isec=fInput->Segmentation(0)->Sector(ix, iy);
1566 dpy=fInput->Segmentation(0)->Dpy(isec);
1568 lower[2]=vstart[2]-dpx;
1569 lower[3]=vstart[3]-dpy;
1570 upper[2]=vstart[2]+dpx;
1571 upper[3]=vstart[3]+dpy;
1580 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1582 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1583 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1584 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1585 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1586 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1587 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1588 // ready for minimisation
1589 clusterInput.Fitter()->SetPrintLevel(-1);
1590 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1594 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1595 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1596 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1597 // Get fitted parameters
1599 Double_t epxz, b1, b2;
1601 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1602 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1603 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1604 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1605 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1606 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1608 Double_t fmin, fedm, errdef;
1609 Int_t npari, nparx, istat;
1611 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1619 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1622 // One cluster for each maximum
1625 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1626 for (j=0; j<2; j++) {
1627 AliMUONRawCluster cnew;
1628 for (cath=0; cath<2; cath++) {
1629 cnew.fChi2[cath]=fChi2[0];
1632 cnew.fNcluster[0]=-1;
1633 cnew.fNcluster[1]=fNRawClusters;
1635 cnew.fNcluster[0]=fNPeaks;
1636 cnew.fNcluster[1]=0;
1638 cnew.fMultiplicity[cath]=0;
1639 cnew.fX[cath]=Float_t(fXFit[j]);
1640 cnew.fY[cath]=Float_t(fYFit[j]);
1642 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
1644 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
1646 fInput->Segmentation(cath)->SetHit(fXFit[j],fYFit[j],0);
1647 for (i=0; i<fMul[cath]; i++) {
1648 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1649 c->fIndexMap[i][cath];
1650 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
1651 Float_t q1=fInput->Response()->IntXY(fInput->Segmentation(cath));
1652 cnew.fContMap[i][cath]
1653 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1654 cnew.fMultiplicity[cath]++;
1655 // printf(" fXFIT %f fYFIT %f Multiplicite %d\n",cnew.fX[cath],cnew.fY[cath],cnew.fMultiplicity[cath]);
1657 FillCluster(&cnew,0,cath);
1660 cnew.fClusterType=cnew.PhysicsContribution();
1661 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1668 // Minimisation functions
1670 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1672 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1679 for (i=0; i<clusterInput.Nmul(0); i++) {
1680 Float_t q0=clusterInput.Charge(i,0);
1681 Float_t q1=clusterInput.DiscrChargeS1(i,par);
1690 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1692 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1698 // Float_t chi2temp=0;
1700 for (cath=0; cath<2; cath++) {
1702 for (i=0; i<clusterInput.Nmul(cath); i++) {
1703 Float_t q0=clusterInput.Charge(i,cath);
1704 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
1711 // if (cath == 0) chi2temp=chisq/clusterInput.Nbins[cath];
1713 // chisq = chisq/clusterInput.Nbins[1]+chi2temp;
1718 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1720 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1727 for (i=0; i<clusterInput.Nmul(0); i++) {
1729 Float_t q0=clusterInput.Charge(i,0);
1730 Float_t q1=clusterInput.DiscrChargeS2(i,par);
1736 // chisq=chisq+=(qtot-qcont)*(qtot-qcont)*0.5;
1741 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1743 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1749 // Float_t chi2temp=0;
1751 for (cath=0; cath<2; cath++) {
1753 for (i=0; i<clusterInput.Nmul(cath); i++) {
1754 Float_t q0=clusterInput.Charge(i,cath);
1755 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
1762 // if (cath == 0) chi2temp=chisq/clusterInput.Nbins[cath];
1764 // chisq = chisq/clusterInput.Nbins[1]+chi2temp;
1768 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1771 // Add a raw cluster copy to the list
1773 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1774 pMUON->AddRawCluster(fInput->Chamber(),c);
1776 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1779 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
1780 if (fTrack[0]==-1 || fTrack[1]==-1) {
1782 } else if (t==fTrack[0] || t==fTrack[1]) {
1789 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1790 ::operator = (const AliMUONClusterFinderVS& rhs)
1792 // Dummy assignment operator