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.7 2000/06/28 15:16:35 morsch
18 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
19 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
20 framework. The changes should have no side effects (mostly dummy arguments).
21 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
22 of chambers with overlapping modules (MakePadHits, Disintegration).
24 Revision 1.6 2000/06/28 12:19:18 morsch
25 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
26 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
27 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
28 It requires two cathode planes. Small modifications in the code will make it usable for
29 one cathode plane and, hence, more general (for test beam data).
30 AliMUONClusterFinder is now obsolete.
32 Revision 1.5 2000/06/28 08:06:10 morsch
33 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
34 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
35 It also naturally takes care of the TMinuit instance.
37 Revision 1.4 2000/06/27 16:18:47 gosset
38 Finally correct implementation of xm, ym, ixm, iym sizes
39 when at least three local maxima on cathode 1 or on cathode 2
41 Revision 1.3 2000/06/22 14:02:45 morsch
42 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
43 Some HP scope problems corrected (PH)
45 Revision 1.2 2000/06/15 07:58:48 morsch
46 Code from MUON-dev joined
48 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
49 Most coding rule violations corrected.
51 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
52 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
53 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
54 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
55 - For clusters with more than 2 maxima on one of the cathode planes all valid
56 combinations of maxima on the two cathodes are preserved. The position of the maxima is
57 taken as the hit position.
58 - New FillCluster method with 2 arguments to find tracks associated to the clusters
59 defined above added. (Method destinction by argument list not very elegant in this case,
60 should be revides (A.M.)
61 - Bug in if-statement to handle maximum 1 maximum per plane corrected
62 - Two cluster per cathode but only 1 combination valid is handled.
63 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
67 #include "AliMUONClusterFinderVS.h"
68 #include "AliMUONDigit.h"
69 #include "AliMUONRawCluster.h"
70 #include "AliSegmentation.h"
71 #include "AliMUONResponse.h"
72 #include "AliMUONHitMapA1.h"
81 #include <TPostScript.h>
86 //_____________________________________________________________________
87 // This function is minimized in the double-Mathieson fit
88 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
89 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
90 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
91 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
93 ClassImp(AliMUONClusterFinderVS)
95 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
97 // Default constructor
98 fInput=AliMUONClusterInput::Instance();
101 fTrack[0]=fTrack[1]=-1;
104 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
105 const AliMUONClusterFinderVS & clusterFinder)
107 // Dummy copy Constructor
111 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
113 // Decluster by local maxima
114 SplitByLocalMaxima(cluster);
117 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
119 // Split complex cluster by local maxima
123 fInput->SetCluster(c);
125 fMul[0]=c->fMultiplicity[0];
126 fMul[1]=c->fMultiplicity[1];
129 // dump digit information into arrays
134 for (cath=0; cath<2; cath++) {
136 for (i=0; i<fMul[cath]; i++)
139 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
141 fIx[i][cath]= fDig[i][cath]->fPadX;
142 fIy[i][cath]= fDig[i][cath]->fPadY;
144 fQ[i][cath] = fDig[i][cath]->fSignal;
145 // pad centre coordinates
146 fInput->Segmentation(cath)->
147 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], zdum);
148 } // loop over cluster digits
149 } // loop over cathodes
155 // Initialise and perform mathieson fits
156 Float_t chi2, oldchi2;
157 // ++++++++++++++++++*************+++++++++++++++++++++
158 // (1) No more than one local maximum per cathode plane
159 // +++++++++++++++++++++++++++++++*************++++++++
160 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
161 (fNLocal[0]==0 && fNLocal[1]==1)) {
163 // Perform combined single Mathieson fit
164 // Initial values for coordinates (x,y)
166 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
167 if (fNLocal[0]==1 && fNLocal[1]==1) {
170 // One local maximum on cathode 1 (X,Y->cathode 1)
171 } else if (fNLocal[0]==1) {
174 // One local maximum on cathode 2 (X,Y->cathode 2)
179 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
180 chi2=CombiSingleMathiesonFit(c);
181 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
182 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
183 // prob1->Fill(prob);
184 // chi2_1->Fill(chi2);
186 fprintf(stderr," chi2 %f ",chi2);
195 c->fX[0]=fInput->Segmentation(0)->GetAnod(c->fX[0]);
196 c->fX[1]=fInput->Segmentation(1)->GetAnod(c->fX[1]);
198 // If reasonable chi^2 add result to the list of rawclusters
202 // If not try combined double Mathieson Fit
204 fprintf(stderr," MAUVAIS CHI2 !!!\n");
205 if (fNLocal[0]==1 && fNLocal[1]==1) {
206 fXInit[0]=fX[fIndLocal[0][1]][1];
207 fYInit[0]=fY[fIndLocal[0][0]][0];
208 fXInit[1]=fX[fIndLocal[0][1]][1];
209 fYInit[1]=fY[fIndLocal[0][0]][0];
210 } else if (fNLocal[0]==1) {
211 fXInit[0]=fX[fIndLocal[0][0]][0];
212 fYInit[0]=fY[fIndLocal[0][0]][0];
213 fXInit[1]=fX[fIndLocal[0][0]][0];
214 fYInit[1]=fY[fIndLocal[0][0]][0];
216 fXInit[0]=fX[fIndLocal[0][1]][1];
217 fYInit[0]=fY[fIndLocal[0][1]][1];
218 fXInit[1]=fX[fIndLocal[0][1]][1];
219 fYInit[1]=fY[fIndLocal[0][1]][1];
222 // Initial value for charge ratios
225 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
226 chi2=CombiDoubleMathiesonFit(c);
227 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
228 // Float_t prob = TMath::Prob(chi2,ndf);
229 // prob2->Fill(prob);
230 // chi2_2->Fill(chi2);
232 // Was this any better ??
233 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
234 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
235 fprintf(stderr," Split\n");
236 // Split cluster into two according to fit result
239 fprintf(stderr," Don't Split\n");
245 // +++++++++++++++++++++++++++++++++++++++
246 // (2) Two local maxima per cathode plane
247 // +++++++++++++++++++++++++++++++++++++++
248 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
250 // Let's look for ghosts first
252 Float_t xm[4][2], ym[4][2];
253 Float_t dpx, dpy, dx, dy;
254 Int_t ixm[4][2], iym[4][2];
255 Int_t isec, im1, im2, ico;
257 // Form the 2x2 combinations
258 // 0-0, 0-1, 1-0, 1-1
260 for (im1=0; im1<2; im1++) {
261 for (im2=0; im2<2; im2++) {
262 xm[ico][0]=fX[fIndLocal[im1][0]][0];
263 ym[ico][0]=fY[fIndLocal[im1][0]][0];
264 xm[ico][1]=fX[fIndLocal[im2][1]][1];
265 ym[ico][1]=fY[fIndLocal[im2][1]][1];
267 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
268 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
269 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
270 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
274 // ico = 0 : first local maximum on cathodes 1 and 2
275 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
276 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
277 // ico = 3 : second local maximum on cathodes 1 and 2
279 // Analyse the combinations and keep those that are possible !
280 // For each combination check consistency in x and y
285 for (ico=0; ico<4; ico++) {
286 accepted[ico]=kFALSE;
287 // cathode one: x-coordinate
288 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
289 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
290 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
291 // cathode two: y-coordinate
292 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
293 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
294 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
295 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
296 if ((dx <= dpx) && (dy <= dpy)) {
302 accepted[ico]=kFALSE;
307 fprintf(stderr,"\n iacc=2: No problem ! \n");
308 } else if (iacc==4) {
309 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
310 } else if (iacc==0) {
311 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
314 // Initial value for charge ratios
315 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
316 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
317 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
318 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
320 // ******* iacc = 0 *******
321 // No combinations found between the 2 cathodes
322 // We keep the center of gravity of the cluster
327 // ******* iacc = 1 *******
328 // Only one combination found between the 2 cathodes
331 // Initial values for the 2 maxima (x,y)
333 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
334 // 1 maximum is initialised with the other maximum of the first cathode
336 fprintf(stderr,"ico=0\n");
341 } else if (accepted[1]){
342 fprintf(stderr,"ico=1\n");
347 } else if (accepted[2]){
348 fprintf(stderr,"ico=2\n");
353 } else if (accepted[3]){
354 fprintf(stderr,"ico=3\n");
360 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
361 chi2=CombiDoubleMathiesonFit(c);
362 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
363 // Float_t prob = TMath::Prob(chi2,ndf);
364 // prob2->Fill(prob);
365 // chi2_2->Fill(chi2);
366 fprintf(stderr," chi2 %f\n",chi2);
368 // If reasonable chi^2 add result to the list of rawclusters
373 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
374 // 1 maximum is initialised with the other maximum of the second cathode
376 fprintf(stderr,"ico=0\n");
381 } else if (accepted[1]){
382 fprintf(stderr,"ico=1\n");
387 } else if (accepted[2]){
388 fprintf(stderr,"ico=2\n");
393 } else if (accepted[3]){
394 fprintf(stderr,"ico=3\n");
400 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
401 chi2=CombiDoubleMathiesonFit(c);
402 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
403 // Float_t prob = TMath::Prob(chi2,ndf);
404 // prob2->Fill(prob);
405 // chi2_2->Fill(chi2);
406 fprintf(stderr," chi2 %f\n",chi2);
408 // If reasonable chi^2 add result to the list of rawclusters
412 //We keep only the combination found (X->cathode 2, Y->cathode 1)
413 for (Int_t ico=0; ico<2; ico++) {
415 AliMUONRawCluster cnew;
417 for (cath=0; cath<2; cath++) {
418 cnew.fX[cath]=Float_t(xm[ico][1]);
419 cnew.fY[cath]=Float_t(ym[ico][0]);
420 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
421 for (i=0; i<fMul[cath]; i++) {
422 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
423 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
425 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
426 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
427 FillCluster(&cnew,cath);
429 cnew.fClusterType=cnew.PhysicsContribution();
438 // ******* iacc = 2 *******
439 // Two combinations found between the 2 cathodes
442 // Was the same maximum taken twice
443 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
444 fprintf(stderr,"\n Maximum taken twice !!!\n");
446 // Have a try !! with that
447 if (accepted[0]&&accepted[3]) {
458 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
459 chi2=CombiDoubleMathiesonFit(c);
460 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
461 // Float_t prob = TMath::Prob(chi2,ndf);
462 // prob2->Fill(prob);
463 // chi2_2->Fill(chi2);
467 // No ghosts ! No Problems ! - Perform one fit only !
468 if (accepted[0]&&accepted[3]) {
479 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
480 chi2=CombiDoubleMathiesonFit(c);
481 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
482 // Float_t prob = TMath::Prob(chi2,ndf);
483 // prob2->Fill(prob);
484 // chi2_2->Fill(chi2);
485 fprintf(stderr," chi2 %f\n",chi2);
489 // ******* iacc = 4 *******
490 // Four combinations found between the 2 cathodes
492 } else if (iacc==4) {
493 // Perform fits for the two possibilities !!
498 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
499 chi2=CombiDoubleMathiesonFit(c);
500 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
501 // Float_t prob = TMath::Prob(chi2,ndf);
502 // prob2->Fill(prob);
503 // chi2_2->Fill(chi2);
504 fprintf(stderr," chi2 %f\n",chi2);
510 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
511 chi2=CombiDoubleMathiesonFit(c);
512 // ndf = fgNbins[0]+fgNbins[1]-6;
513 // prob = TMath::Prob(chi2,ndf);
514 // prob2->Fill(prob);
515 // chi2_2->Fill(chi2);
516 fprintf(stderr," chi2 %f\n",chi2);
520 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
521 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
522 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
523 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
525 Float_t xm[4][2], ym[4][2];
526 Float_t dpx, dpy, dx, dy;
527 Int_t ixm[4][2], iym[4][2];
528 Int_t isec, im1, ico;
530 // Form the 2x2 combinations
531 // 0-0, 0-1, 1-0, 1-1
533 for (im1=0; im1<2; im1++) {
534 xm[ico][0]=fX[fIndLocal[im1][0]][0];
535 ym[ico][0]=fY[fIndLocal[im1][0]][0];
536 xm[ico][1]=fX[fIndLocal[0][1]][1];
537 ym[ico][1]=fY[fIndLocal[0][1]][1];
539 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
540 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
541 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
542 iym[ico][1]=fIy[fIndLocal[0][1]][1];
545 // ico = 0 : first local maximum on cathodes 1 and 2
546 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
548 // Analyse the combinations and keep those that are possible !
549 // For each combination check consistency in x and y
554 for (ico=0; ico<2; ico++) {
555 accepted[ico]=kFALSE;
556 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
557 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
558 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
559 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
560 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
561 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
562 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
563 if ((dx <= dpx) && (dy <= dpy)) {
569 accepted[ico]=kFALSE;
581 chi21=CombiDoubleMathiesonFit(c);
582 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
583 // Float_t prob = TMath::Prob(chi2,ndf);
584 // prob2->Fill(prob);
585 // chi2_2->Fill(chi21);
586 fprintf(stderr," chi2 %f\n",chi21);
587 if (chi21<10) Split(c);
588 } else if (accepted[1]) {
593 chi22=CombiDoubleMathiesonFit(c);
594 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
595 // Float_t prob = TMath::Prob(chi2,ndf);
596 // prob2->Fill(prob);
597 // chi2_2->Fill(chi22);
598 fprintf(stderr," chi2 %f\n",chi22);
599 if (chi22<10) Split(c);
602 if (chi21 > 10 && chi22 > 10) {
603 // We keep only the combination found (X->cathode 2, Y->cathode 1)
604 for (Int_t ico=0; ico<2; ico++) {
606 AliMUONRawCluster cnew;
608 for (cath=0; cath<2; cath++) {
609 cnew.fX[cath]=Float_t(xm[ico][1]);
610 cnew.fY[cath]=Float_t(ym[ico][0]);
611 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
612 for (i=0; i<fMul[cath]; i++) {
613 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
614 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
616 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
617 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
618 FillCluster(&cnew,cath);
620 cnew.fClusterType=cnew.PhysicsContribution();
627 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
628 // (3') One local maximum on cathode 1 and two maxima on cathode 2
629 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
630 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
632 Float_t xm[4][2], ym[4][2];
633 Float_t dpx, dpy, dx, dy;
634 Int_t ixm[4][2], iym[4][2];
635 Int_t isec, im1, ico;
637 // Form the 2x2 combinations
638 // 0-0, 0-1, 1-0, 1-1
640 for (im1=0; im1<2; im1++) {
641 xm[ico][0]=fX[fIndLocal[0][0]][0];
642 ym[ico][0]=fY[fIndLocal[0][0]][0];
643 xm[ico][1]=fX[fIndLocal[im1][1]][1];
644 ym[ico][1]=fY[fIndLocal[im1][1]][1];
646 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
647 iym[ico][0]=fIy[fIndLocal[0][0]][0];
648 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
649 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
652 // ico = 0 : first local maximum on cathodes 1 and 2
653 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
655 // Analyse the combinations and keep those that are possible !
656 // For each combination check consistency in x and y
661 for (ico=0; ico<2; ico++) {
662 accepted[ico]=kFALSE;
663 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
664 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
665 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
666 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
667 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
668 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
669 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
670 if ((dx <= dpx) && (dy <= dpy)) {
673 fprintf(stderr,"ico %d\n",ico);
677 accepted[ico]=kFALSE;
689 chi21=CombiDoubleMathiesonFit(c);
690 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
691 // Float_t prob = TMath::Prob(chi2,ndf);
692 // prob2->Fill(prob);
693 // chi2_2->Fill(chi21);
694 fprintf(stderr," chi2 %f\n",chi21);
695 if (chi21<10) Split(c);
696 } else if (accepted[1]) {
701 chi22=CombiDoubleMathiesonFit(c);
702 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
703 // Float_t prob = TMath::Prob(chi2,ndf);
704 // prob2->Fill(prob);
705 // chi2_2->Fill(chi22);
706 fprintf(stderr," chi2 %f\n",chi22);
707 if (chi22<10) Split(c);
710 if (chi21 > 10 && chi22 > 10) {
711 //We keep only the combination found (X->cathode 2, Y->cathode 1)
712 for (Int_t ico=0; ico<2; ico++) {
714 AliMUONRawCluster cnew;
716 for (cath=0; cath<2; cath++) {
717 cnew.fX[cath]=Float_t(xm[ico][1]);
718 cnew.fY[cath]=Float_t(ym[ico][0]);
719 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
720 for (i=0; i<fMul[cath]; i++) {
721 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
722 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
724 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
725 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
726 FillCluster(&cnew,cath);
728 cnew.fClusterType=cnew.PhysicsContribution();
735 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
736 // (4) At least three local maxima on cathode 1 or on cathode 2
737 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
738 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
740 Int_t param = fNLocal[0]*fNLocal[1];
743 Float_t ** xm = new Float_t * [param];
744 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
745 Float_t ** ym = new Float_t * [param];
746 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
747 Int_t ** ixm = new Int_t * [param];
748 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
749 Int_t ** iym = new Int_t * [param];
750 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
753 Float_t dpx, dpy, dx, dy;
756 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
757 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
758 xm[ico][0]=fX[fIndLocal[im1][0]][0];
759 ym[ico][0]=fY[fIndLocal[im1][0]][0];
760 xm[ico][1]=fX[fIndLocal[im2][1]][1];
761 ym[ico][1]=fY[fIndLocal[im2][1]][1];
763 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
764 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
765 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
766 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
773 fprintf(stderr,"nIco %d\n",nIco);
774 for (ico=0; ico<nIco; ico++) {
775 fprintf(stderr,"ico = %d\n",ico);
776 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
777 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
778 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
779 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
780 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
781 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
783 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
784 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
785 if ((dx <= dpx) && (dy <= dpy)) {
786 fprintf(stderr,"ok\n");
788 AliMUONRawCluster cnew;
789 for (cath=0; cath<2; cath++) {
790 cnew.fX[cath]=Float_t(xm[ico][1]);
791 cnew.fY[cath]=Float_t(ym[ico][0]);
792 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
793 for (i=0; i<fMul[cath]; i++) {
794 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
795 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
797 FillCluster(&cnew,cath);
799 cnew.fClusterType=cnew.PhysicsContribution();
811 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
813 // Find all local maxima of a cluster
817 Int_t cath, cath1; // loops over cathodes
818 Int_t i; // loops over digits
819 Int_t j; // loops over cathodes
823 // counters for number of local maxima
824 fNLocal[0]=fNLocal[1]=0;
825 // flags digits as local maximum
826 Bool_t isLocal[100][2];
827 for (i=0; i<100;i++) {
828 isLocal[i][0]=isLocal[i][1]=kFALSE;
830 // number of next neighbours and arrays to store them
833 // loop over cathodes
834 for (cath=0; cath<2; cath++) {
835 // loop over cluster digits
836 for (i=0; i<fMul[cath]; i++) {
837 // get neighbours for that digit and assume that it is local maximum
838 fInput->Segmentation(cath)->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
839 isLocal[i][cath]=kTRUE;
840 Int_t isec= fInput->Segmentation(cath)->Sector(fIx[i][cath], fIy[i][cath]);
841 Float_t a0 = fInput->Segmentation(cath)->Dpx(isec)*fInput->Segmentation(cath)->Dpy(isec);
842 // loop over next neighbours, if at least one neighbour has higher charger assumption
843 // digit is not local maximum
844 for (j=0; j<nn; j++) {
845 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
846 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
847 isec=fInput->Segmentation(cath)->Sector(x[j], y[j]);
848 Float_t a1 = fInput->Segmentation(cath)->Dpx(isec)*fInput->Segmentation(cath)->Dpy(isec);
849 if (digt->fSignal/a1 > fQ[i][cath]/a0) {
850 isLocal[i][cath]=kFALSE;
853 // handle special case of neighbouring pads with equal signal
854 } else if (digt->fSignal == fQ[i][cath]) {
855 if (fNLocal[cath]>0) {
856 for (Int_t k=0; k<fNLocal[cath]; k++) {
857 if (x[j]==fIx[fIndLocal[k][cath]][cath]
858 && y[j]==fIy[fIndLocal[k][cath]][cath])
860 isLocal[i][cath]=kFALSE;
862 } // loop over local maxima
863 } // are there already local maxima
865 } // loop over next neighbours
866 if (isLocal[i][cath]) {
867 fIndLocal[fNLocal[cath]][cath]=i;
870 } // loop over all digits
871 } // loop over cathodes
873 printf("\n Found %d %d %d %d local Maxima\n",
874 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
875 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
876 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
881 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
882 Int_t iback=fNLocal[0];
884 // Two local maxima on cathode 2 and one maximum on cathode 1
885 // Look for local maxima considering up and down neighbours on the 1st cathode only
887 // Loop over cluster digits
891 for (i=0; i<fMul[cath]; i++) {
892 isec=fInput->Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
893 dpy=fInput->Segmentation(cath)->Dpy(isec);
894 dpx=fInput->Segmentation(cath)->Dpx(isec);
895 if (isLocal[i][cath]) continue;
896 // Pad position should be consistent with position of local maxima on the opposite cathode
897 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
898 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
901 // get neighbours for that digit and assume that it is local maximum
902 isLocal[i][cath]=kTRUE;
903 // compare signal to that on the two neighbours on the left and on the right
904 fInput->Segmentation(cath)->GetPadI(fX[i][cath],fY[i][cath]+dpy,0,ix,iy);
905 // iNN counts the number of neighbours with signal, it should be 1 or 2
907 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
909 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
910 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
912 fInput->Segmentation(cath)->GetPadI(fX[i][cath],fY[i][cath]-dpy,0,ix,iy);
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 if (isLocal[i][cath] && iNN>0) {
919 fIndLocal[fNLocal[cath]][cath]=i;
922 } // loop over all digits
923 // if one additional maximum has been found we are happy
924 // if more maxima have been found restore the previous situation
925 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
926 fprintf(stderr," %d local maxima for cathode 2 \n",fNLocal[1]);
927 if (fNLocal[cath]>2) {
931 } // 1,2 local maxima
933 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
934 Int_t iback=fNLocal[1];
936 // Two local maxima on cathode 1 and one maximum on cathode 2
937 // Look for local maxima considering left and right neighbours on the 2nd cathode only
943 // Loop over cluster digits
944 for (i=0; i<fMul[cath]; i++) {
945 isec=fInput->Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
946 dpx=fInput->Segmentation(cath)->Dpx(isec);
947 dpy=fInput->Segmentation(cath)->Dpy(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(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
951 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/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 fInput->Segmentation(cath)->GetPadI(fX[i][cath]+dpx,fY[i][cath],0,ix,iy);
958 // iNN counts the number of neighbours with signal, it should be 1 or 2
960 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
962 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
963 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
965 fInput->Segmentation(cath)->GetPadI(fX[i][cath]-dpx,fY[i][cath],0,ix,iy);
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 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,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
980 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
981 if (fNLocal[cath]>2) {
987 } // 2,1 local maxima
991 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
994 // Completes cluster information starting from list of digits
1001 c->fPeakSignal[cath]=c->fPeakSignal[0];
1003 c->fPeakSignal[cath]=0;
1013 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1014 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1016 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1017 ix=dig->fPadX+c->fOffsetMap[i][cath];
1019 Int_t q=dig->fSignal;
1020 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1021 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1022 if (dig->fPhysics >= dig->fSignal) {
1023 c->fPhysicsMap[i]=2;
1024 } else if (dig->fPhysics == 0) {
1025 c->fPhysicsMap[i]=0;
1026 } else c->fPhysicsMap[i]=1;
1029 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1030 // peak signal and track list
1031 if (q>c->fPeakSignal[cath]) {
1032 c->fPeakSignal[cath]=q;
1033 c->fTracks[0]=dig->fHit;
1034 c->fTracks[1]=dig->fTracks[0];
1035 c->fTracks[2]=dig->fTracks[1];
1036 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1040 fInput->Segmentation(cath)->GetPadC(ix, iy, x, y, z);
1045 } // loop over digits
1046 // fprintf(stderr," fin du cluster c\n");
1050 c->fX[cath]/=c->fQ[cath];
1051 c->fX[cath]=fInput->Segmentation(cath)->GetAnod(c->fX[cath]);
1052 c->fY[cath]/=c->fQ[cath];
1054 // apply correction to the coordinate along the anode wire
1058 fInput->Segmentation(cath)->GetPadI(x, y, 0, ix, iy);
1059 fInput->Segmentation(cath)->GetPadC(ix, iy, x, y, z);
1060 Int_t isec=fInput->Segmentation(cath)->Sector(ix,iy);
1061 TF1* cogCorr = fInput->Segmentation(cath)->CorrFunc(isec-1);
1064 Float_t yOnPad=(c->fY[cath]-y)/fInput->Segmentation(cath)->Dpy(isec);
1065 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1070 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1073 // Completes cluster information starting from list of digits
1083 Float_t xpad, ypad, zpad;
1086 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1088 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1089 fInput->Segmentation(cath)->
1090 GetPadC(dig->fPadX,dig->fPadY,xpad,ypad, zpad);
1091 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1092 dx = xpad - c->fX[0];
1093 dy = ypad - c->fY[0];
1094 dr = TMath::Sqrt(dx*dx+dy*dy);
1098 fprintf(stderr," dr %f\n",dr);
1099 Int_t q=dig->fSignal;
1100 if (dig->fPhysics >= dig->fSignal) {
1101 c->fPhysicsMap[i]=2;
1102 } else if (dig->fPhysics == 0) {
1103 c->fPhysicsMap[i]=0;
1104 } else c->fPhysicsMap[i]=1;
1105 c->fPeakSignal[cath]=q;
1106 c->fTracks[0]=dig->fHit;
1107 c->fTracks[1]=dig->fTracks[0];
1108 c->fTracks[2]=dig->fTracks[1];
1109 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1112 } // loop over digits
1114 // apply correction to the coordinate along the anode wire
1115 c->fX[cath]=fInput->Segmentation(cath)->GetAnod(c->fX[cath]);
1118 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1123 // Add i,j as element of the cluster
1126 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1127 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1128 Int_t q=dig->fSignal;
1129 Int_t theX=dig->fPadX;
1130 Int_t theY=dig->fPadY;
1131 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1132 c.fPeakSignal[cath]=q;
1133 c.fTracks[0]=dig->fHit;
1134 c.fTracks[1]=dig->fTracks[0];
1135 c.fTracks[2]=dig->fTracks[1];
1139 // Make sure that list of digits is ordered
1141 Int_t mu=c.fMultiplicity[cath];
1142 c.fIndexMap[mu][cath]=idx;
1144 if (dig->fPhysics >= dig->fSignal) {
1145 c.fPhysicsMap[mu]=2;
1146 } else if (dig->fPhysics == 0) {
1147 c.fPhysicsMap[mu]=0;
1148 } else c.fPhysicsMap[mu]=1;
1150 for (Int_t ind=mu-1; ind>=0; ind--) {
1151 Int_t ist=(c.fIndexMap)[ind][cath];
1152 Int_t ql=fInput->Digit(cath, ist)->fSignal;
1153 Int_t ix=fInput->Digit(cath, ist)->fPadX;
1154 Int_t iy=fInput->Digit(cath, ist)->fPadY;
1156 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1157 c.fIndexMap[ind][cath]=idx;
1158 c.fIndexMap[ind+1][cath]=ist;
1165 c.fMultiplicity[cath]++;
1166 if (c.fMultiplicity[cath] >= 50 ) {
1167 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1168 c.fMultiplicity[cath]=49;
1171 // Prepare center of gravity calculation
1173 fInput->Segmentation(cath)->GetPadC(i, j, x, y, z);
1178 // Flag hit as taken
1179 fHitMap[cath]->FlagHit(i,j);
1181 // Now look recursively for all neighbours and pad hit on opposite cathode
1183 // Loop over neighbours
1186 Int_t xList[10], yList[10];
1187 fInput->Segmentation(cath)->Neighbours(i,j,&nn,xList,yList);
1188 for (Int_t in=0; in<nn; in++) {
1191 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, cath, c);
1193 // Neighbours on opposite cathode
1194 // Take into account that several pads can overlap with the present pad
1195 Float_t xmin, xmax, ymin, ymax, xc, yc;
1197 Int_t isec=fInput->Segmentation(cath)->Sector(i,j);
1200 xmin=x-fInput->Segmentation(cath)->Dpx(isec);
1201 xmax=x+fInput->Segmentation(cath)->Dpx(isec);
1204 xc+=fInput->Segmentation(iop)->Dpx(isec);
1205 fInput->Segmentation(iop)->GetPadI(xc,y,0,ix,iy);
1206 if (ix>=(fInput->Segmentation(iop)->Npx()) || (iy>=fInput->Segmentation(iop)->Npy())) continue;
1207 if (fHitMap[iop]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1211 ymin=y-fInput->Segmentation(cath)->Dpy(isec);
1212 ymax=y+fInput->Segmentation(cath)->Dpy(isec);
1215 yc+=fInput->Segmentation(iop)->Dpy(isec);
1216 fInput->Segmentation(iop)->GetPadI(x,yc,0,ix,iy);
1217 if (ix>=(fInput->Segmentation(iop)->Npx()) || (iy>=fInput->Segmentation(iop)->Npy())) continue;
1218 if (fHitMap[iop]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1223 //_____________________________________________________________________________
1225 void AliMUONClusterFinderVS::FindRawClusters()
1228 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1229 // fills the tree with raw clusters
1232 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1234 fHitMap[0] = new AliMUONHitMapA1(fInput->Segmentation(0), fInput->Digits(0));
1235 fHitMap[1] = new AliMUONHitMapA1(fInput->Segmentation(1), fInput->Digits(1));
1242 fHitMap[0]->FillHits();
1243 fHitMap[1]->FillHits();
1245 // Outer Loop over Cathodes
1246 for (cath=0; cath<2; cath++) {
1247 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1248 dig = fInput->Digit(cath, ndig);
1251 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1255 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1256 AliMUONRawCluster c;
1257 c.fMultiplicity[0]=0;
1258 c.fMultiplicity[1]=0;
1259 c.fPeakSignal[cath]=dig->fSignal;
1260 c.fTracks[0]=dig->fHit;
1261 c.fTracks[1]=dig->fTracks[0];
1262 c.fTracks[2]=dig->fTracks[1];
1263 // tag the beginning of cluster list in a raw cluster
1266 FindCluster(i,j,cath,c);
1268 // center of gravity
1270 c.fX[0]=fInput->Segmentation(0)->GetAnod(c.fX[0]);
1273 c.fX[1]=fInput->Segmentation(0)->GetAnod(c.fX[1]);
1275 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[0],c.fX[0],c.fY[0]);
1276 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[1],c.fX[1],c.fY[1]);
1282 fitted=SingleMathiesonFit(&c, 0);
1283 c.fX[0]=fInput->Segmentation(0)->GetAnod(c.fX[0]);
1284 fitted=SingleMathiesonFit(&c, 1);
1285 c.fX[1]=fInput->Segmentation(1)->GetAnod(c.fX[1]);
1288 // Analyse cluster and decluster if necessary
1291 c.fNcluster[1]=fNRawClusters;
1292 c.fClusterType=c.PhysicsContribution();
1298 // AddRawCluster(c);
1301 // reset Cluster object
1302 { // begin local scope
1303 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1304 } // end local scope
1306 { // begin local scope
1307 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1308 } // end local scope
1310 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1314 } // end loop cathodes
1319 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1322 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1324 clusterInput.Fitter()->SetFCN(fcnS1);
1325 clusterInput.Fitter()->mninit(2,10,7);
1326 Double_t arglist[20];
1329 // clusterInput.Fitter()->mnexcm("SET ERR",arglist,1,ierflag);
1330 // Set starting values
1331 static Double_t vstart[2];
1336 // lower and upper limits
1337 static Double_t lower[2], upper[2];
1339 fInput->Segmentation(cath)->GetPadI(c->fX[cath], c->fY[cath], 0, ix, iy);
1340 Int_t isec=fInput->Segmentation(cath)->Sector(ix, iy);
1341 lower[0]=vstart[0]-fInput->Segmentation(cath)->Dpx(isec)/2;
1342 lower[1]=vstart[1]-fInput->Segmentation(cath)->Dpy(isec)/2;
1344 upper[0]=lower[0]+fInput->Segmentation(cath)->Dpx(isec);
1345 upper[1]=lower[1]+fInput->Segmentation(cath)->Dpy(isec);
1348 static Double_t step[2]={0.0005, 0.0005};
1350 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1351 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1352 // ready for minimisation
1353 clusterInput.Fitter()->SetPrintLevel(1);
1354 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1358 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1359 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1360 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1361 Double_t fmin, fedm, errdef;
1362 Int_t npari, nparx, istat;
1364 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1368 // Get fitted parameters
1369 Double_t xrec, yrec;
1371 Double_t epxz, b1, b2;
1373 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1374 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1380 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1382 // Perform combined Mathieson fit on both cathode planes
1384 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1385 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1386 clusterInput.Fitter()->mninit(2,10,7);
1387 Double_t arglist[20];
1390 static Double_t vstart[2];
1391 vstart[0]=fXInit[0];
1392 vstart[1]=fYInit[0];
1395 // lower and upper limits
1396 static Double_t lower[2], upper[2];
1398 fInput->Segmentation(0)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1399 isec=fInput->Segmentation(0)->Sector(ix, iy);
1400 Float_t dpy=fInput->Segmentation(0)->Dpy(isec)/2;
1401 fInput->Segmentation(1)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1402 isec=fInput->Segmentation(1)->Sector(ix, iy);
1403 Float_t dpx=fInput->Segmentation(1)->Dpx(isec)/2;
1406 lower[0]=vstart[0]-dpx;
1407 lower[1]=vstart[1]-dpy;
1409 upper[0]=vstart[0]+dpx;
1410 upper[1]=vstart[1]+dpy;
1413 static Double_t step[2]={0.00001, 0.0001};
1415 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1416 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1417 // ready for minimisation
1418 clusterInput.Fitter()->SetPrintLevel(1);
1419 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1423 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1424 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1425 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1426 Double_t fmin, fedm, errdef;
1427 Int_t npari, nparx, istat;
1429 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1433 // Get fitted parameters
1434 Double_t xrec, yrec;
1436 Double_t epxz, b1, b2;
1438 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1439 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1445 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1448 // Initialise global variables for fit
1449 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1450 clusterInput.Fitter()->SetFCN(fcnS2);
1451 clusterInput.Fitter()->mninit(5,10,7);
1452 Double_t arglist[20];
1455 // Set starting values
1456 static Double_t vstart[5];
1457 vstart[0]=fX[fIndLocal[0][cath]][cath];
1458 vstart[1]=fY[fIndLocal[0][cath]][cath];
1459 vstart[2]=fX[fIndLocal[1][cath]][cath];
1460 vstart[3]=fY[fIndLocal[1][cath]][cath];
1461 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1462 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1463 // lower and upper limits
1464 static Double_t lower[5], upper[5];
1465 Int_t isec=fInput->Segmentation(cath)->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1466 lower[0]=vstart[0]-fInput->Segmentation(cath)->Dpx(isec);
1467 lower[1]=vstart[1]-fInput->Segmentation(cath)->Dpy(isec);
1469 upper[0]=lower[0]+2.*fInput->Segmentation(cath)->Dpx(isec);
1470 upper[1]=lower[1]+2.*fInput->Segmentation(cath)->Dpy(isec);
1472 isec=fInput->Segmentation(cath)->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1473 lower[2]=vstart[2]-fInput->Segmentation(cath)->Dpx(isec)/2;
1474 lower[3]=vstart[3]-fInput->Segmentation(cath)->Dpy(isec)/2;
1476 upper[2]=lower[2]+fInput->Segmentation(cath)->Dpx(isec);
1477 upper[3]=lower[3]+fInput->Segmentation(cath)->Dpy(isec);
1482 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1484 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1485 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1486 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1487 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1488 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1489 // ready for minimisation
1490 clusterInput.Fitter()->SetPrintLevel(-1);
1491 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1495 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1496 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1497 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1498 // Get fitted parameters
1499 Double_t xrec[2], yrec[2], qfrac;
1501 Double_t epxz, b1, b2;
1503 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1504 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1505 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1506 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1507 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1509 Double_t fmin, fedm, errdef;
1510 Int_t npari, nparx, istat;
1512 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1517 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1520 // Perform combined double Mathieson fit on both cathode planes
1522 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1523 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1524 clusterInput.Fitter()->mninit(6,10,7);
1525 Double_t arglist[20];
1528 // Set starting values
1529 static Double_t vstart[6];
1530 vstart[0]=fXInit[0];
1531 vstart[1]=fYInit[0];
1532 vstart[2]=fXInit[1];
1533 vstart[3]=fYInit[1];
1534 vstart[4]=fQrInit[0];
1535 vstart[5]=fQrInit[1];
1536 // lower and upper limits
1537 static Double_t lower[6], upper[6];
1541 fInput->Segmentation(1)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1542 isec=fInput->Segmentation(1)->Sector(ix, iy);
1543 dpx=fInput->Segmentation(1)->Dpx(isec);
1545 fInput->Segmentation(0)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1546 isec=fInput->Segmentation(0)->Sector(ix, iy);
1547 dpy=fInput->Segmentation(0)->Dpy(isec);
1549 lower[0]=vstart[0]-dpx;
1550 lower[1]=vstart[1]-dpy;
1551 upper[0]=vstart[0]+dpx;
1552 upper[1]=vstart[1]+dpy;
1555 fInput->Segmentation(1)->GetPadI(fXInit[1], fYInit[1], 0, ix, iy);
1556 isec=fInput->Segmentation(1)->Sector(ix, iy);
1557 dpx=fInput->Segmentation(1)->Dpx(isec);
1558 fInput->Segmentation(0)->GetPadI(fXInit[1], fYInit[1], 0, ix, iy);
1559 isec=fInput->Segmentation(0)->Sector(ix, iy);
1560 dpy=fInput->Segmentation(0)->Dpy(isec);
1562 lower[2]=vstart[2]-dpx;
1563 lower[3]=vstart[3]-dpy;
1564 upper[2]=vstart[2]+dpx;
1565 upper[3]=vstart[3]+dpy;
1574 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1576 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1577 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1578 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1579 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1580 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1581 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1582 // ready for minimisation
1583 clusterInput.Fitter()->SetPrintLevel(-1);
1584 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1588 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1589 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1590 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1591 // Get fitted parameters
1593 Double_t epxz, b1, b2;
1595 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1596 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1597 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1598 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1599 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1600 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1602 Double_t fmin, fedm, errdef;
1603 Int_t npari, nparx, istat;
1605 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1613 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1616 // One cluster for each maximum
1619 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1620 for (j=0; j<2; j++) {
1621 AliMUONRawCluster cnew;
1622 for (cath=0; cath<2; cath++) {
1623 cnew.fChi2[cath]=fChi2[0];
1626 cnew.fNcluster[0]=-1;
1627 cnew.fNcluster[1]=fNRawClusters;
1629 cnew.fNcluster[0]=fNPeaks;
1630 cnew.fNcluster[1]=0;
1632 cnew.fMultiplicity[cath]=0;
1633 cnew.fX[cath]=Float_t(fXFit[j]);
1634 cnew.fY[cath]=Float_t(fYFit[j]);
1636 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
1638 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
1640 fInput->Segmentation(cath)->SetHit(fXFit[j],fYFit[j],0);
1641 for (i=0; i<fMul[cath]; i++) {
1642 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1643 c->fIndexMap[i][cath];
1644 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
1645 Float_t q1=fInput->Response()->IntXY(fInput->Segmentation(cath));
1646 cnew.fContMap[i][cath]
1647 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1648 cnew.fMultiplicity[cath]++;
1649 // printf(" fXFIT %f fYFIT %f Multiplicite %d\n",cnew.fX[cath],cnew.fY[cath],cnew.fMultiplicity[cath]);
1651 FillCluster(&cnew,0,cath);
1654 cnew.fClusterType=cnew.PhysicsContribution();
1655 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1662 // Minimisation functions
1664 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1666 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1673 for (i=0; i<clusterInput.Nmul(0); i++) {
1674 Float_t q0=clusterInput.Charge(i,0);
1675 Float_t q1=clusterInput.DiscrChargeS1(i,par);
1684 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1686 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1692 // Float_t chi2temp=0;
1694 for (cath=0; cath<2; cath++) {
1696 for (i=0; i<clusterInput.Nmul(cath); i++) {
1697 Float_t q0=clusterInput.Charge(i,cath);
1698 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
1705 // if (cath == 0) chi2temp=chisq/clusterInput.Nbins[cath];
1707 // chisq = chisq/clusterInput.Nbins[1]+chi2temp;
1712 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1714 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1721 for (i=0; i<clusterInput.Nmul(0); i++) {
1723 Float_t q0=clusterInput.Charge(i,0);
1724 Float_t q1=clusterInput.DiscrChargeS2(i,par);
1730 // chisq=chisq+=(qtot-qcont)*(qtot-qcont)*0.5;
1735 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1737 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1743 // Float_t chi2temp=0;
1745 for (cath=0; cath<2; cath++) {
1747 for (i=0; i<clusterInput.Nmul(cath); i++) {
1748 Float_t q0=clusterInput.Charge(i,cath);
1749 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
1756 // if (cath == 0) chi2temp=chisq/clusterInput.Nbins[cath];
1758 // chisq = chisq/clusterInput.Nbins[1]+chi2temp;
1762 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1765 // Add a raw cluster copy to the list
1767 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1768 pMUON->AddRawCluster(fInput->Chamber(),c);
1770 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1773 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
1774 if (fTrack[0]==-1 || fTrack[1]==-1) {
1776 } else if (t==fTrack[0] || t==fTrack[1]) {
1783 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1784 ::operator = (const AliMUONClusterFinderVS& rhs)
1786 // Dummy assignment operator