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.11 2000/10/06 09:04:05 morsch
18 - Dummy z-arguments in GetPadI, SetHit, FirstPad replaced by real z-coordinate
19 to make code work with slat chambers (AM)
20 - Replace GetPadI calls with unchecked x,y coordinates by pad iterator calls wherever possible.
22 Revision 1.10 2000/10/03 13:51:57 egangler
23 Removal of useless dependencies via forward declarations
25 Revision 1.9 2000/10/02 16:58:29 egangler
26 Cleaning of the code :
29 -> some useless includes removed or replaced by "class" statement
31 Revision 1.8 2000/07/03 11:54:57 morsch
32 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
33 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
35 Revision 1.7 2000/06/28 15:16:35 morsch
36 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
37 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
38 framework. The changes should have no side effects (mostly dummy arguments).
39 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
40 of chambers with overlapping modules (MakePadHits, Disintegration).
42 Revision 1.6 2000/06/28 12:19:18 morsch
43 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
44 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
45 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
46 It requires two cathode planes. Small modifications in the code will make it usable for
47 one cathode plane and, hence, more general (for test beam data).
48 AliMUONClusterFinder is now obsolete.
50 Revision 1.5 2000/06/28 08:06:10 morsch
51 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
52 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
53 It also naturally takes care of the TMinuit instance.
55 Revision 1.4 2000/06/27 16:18:47 gosset
56 Finally correct implementation of xm, ym, ixm, iym sizes
57 when at least three local maxima on cathode 1 or on cathode 2
59 Revision 1.3 2000/06/22 14:02:45 morsch
60 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
61 Some HP scope problems corrected (PH)
63 Revision 1.2 2000/06/15 07:58:48 morsch
64 Code from MUON-dev joined
66 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
67 Most coding rule violations corrected.
69 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
70 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
71 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
72 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
73 - For clusters with more than 2 maxima on one of the cathode planes all valid
74 combinations of maxima on the two cathodes are preserved. The position of the maxima is
75 taken as the hit position.
76 - New FillCluster method with 2 arguments to find tracks associated to the clusters
77 defined above added. (Method destinction by argument list not very elegant in this case,
78 should be revides (A.M.)
79 - Bug in if-statement to handle maximum 1 maximum per plane corrected
80 - Two cluster per cathode but only 1 combination valid is handled.
81 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
85 #include "AliMUONClusterFinderVS.h"
86 #include "AliMUONDigit.h"
87 #include "AliMUONRawCluster.h"
88 #include "AliSegmentation.h"
89 #include "AliMUONResponse.h"
90 #include "AliMUONClusterInput.h"
91 #include "AliMUONHitMapA1.h"
100 #include <TPostScript.h>
105 #include <iostream.h>
107 //_____________________________________________________________________
108 // This function is minimized in the double-Mathieson fit
109 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
110 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
111 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
112 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
114 ClassImp(AliMUONClusterFinderVS)
116 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
118 // Default constructor
119 fInput=AliMUONClusterInput::Instance();
122 fTrack[0]=fTrack[1]=-1;
125 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
126 const AliMUONClusterFinderVS & clusterFinder)
128 // Dummy copy Constructor
132 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
134 // Decluster by local maxima
135 SplitByLocalMaxima(cluster);
138 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
140 // Split complex cluster by local maxima
143 fInput->SetCluster(c);
145 fMul[0]=c->fMultiplicity[0];
146 fMul[1]=c->fMultiplicity[1];
149 // dump digit information into arrays
154 for (cath=0; cath<2; cath++) {
156 for (i=0; i<fMul[cath]; i++)
159 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
161 fIx[i][cath]= fDig[i][cath]->fPadX;
162 fIy[i][cath]= fDig[i][cath]->fPadY;
164 fQ[i][cath] = fDig[i][cath]->fSignal;
165 // pad centre coordinates
167 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], fZ[i][cath]);
168 } // loop over cluster digits
169 } // loop over cathodes
175 // Initialise and perform mathieson fits
176 Float_t chi2, oldchi2;
177 // ++++++++++++++++++*************+++++++++++++++++++++
178 // (1) No more than one local maximum per cathode plane
179 // +++++++++++++++++++++++++++++++*************++++++++
180 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
181 (fNLocal[0]==0 && fNLocal[1]==1)) {
183 // Perform combined single Mathieson fit
184 // Initial values for coordinates (x,y)
186 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
187 if (fNLocal[0]==1 && fNLocal[1]==1) {
190 // One local maximum on cathode 1 (X,Y->cathode 1)
191 } else if (fNLocal[0]==1) {
194 // One local maximum on cathode 2 (X,Y->cathode 2)
199 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
200 chi2=CombiSingleMathiesonFit(c);
201 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
202 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
203 // prob1->Fill(prob);
204 // chi2_1->Fill(chi2);
206 fprintf(stderr," chi2 %f ",chi2);
215 c->fX[0]=fSeg[0]->GetAnod(c->fX[0]);
216 c->fX[1]=fSeg[1]->GetAnod(c->fX[1]);
218 // If reasonable chi^2 add result to the list of rawclusters
222 // If not try combined double Mathieson Fit
224 fprintf(stderr," MAUVAIS CHI2 !!!\n");
225 if (fNLocal[0]==1 && fNLocal[1]==1) {
226 fXInit[0]=fX[fIndLocal[0][1]][1];
227 fYInit[0]=fY[fIndLocal[0][0]][0];
228 fXInit[1]=fX[fIndLocal[0][1]][1];
229 fYInit[1]=fY[fIndLocal[0][0]][0];
230 } else if (fNLocal[0]==1) {
231 fXInit[0]=fX[fIndLocal[0][0]][0];
232 fYInit[0]=fY[fIndLocal[0][0]][0];
233 fXInit[1]=fX[fIndLocal[0][0]][0];
234 fYInit[1]=fY[fIndLocal[0][0]][0];
236 fXInit[0]=fX[fIndLocal[0][1]][1];
237 fYInit[0]=fY[fIndLocal[0][1]][1];
238 fXInit[1]=fX[fIndLocal[0][1]][1];
239 fYInit[1]=fY[fIndLocal[0][1]][1];
242 // Initial value for charge ratios
245 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
246 chi2=CombiDoubleMathiesonFit(c);
247 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
248 // Float_t prob = TMath::Prob(chi2,ndf);
249 // prob2->Fill(prob);
250 // chi2_2->Fill(chi2);
252 // Was this any better ??
253 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
254 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
255 fprintf(stderr," Split\n");
256 // Split cluster into two according to fit result
259 fprintf(stderr," Don't Split\n");
265 // +++++++++++++++++++++++++++++++++++++++
266 // (2) Two local maxima per cathode plane
267 // +++++++++++++++++++++++++++++++++++++++
268 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
270 // Let's look for ghosts first
272 Float_t xm[4][2], ym[4][2];
273 Float_t dpx, dpy, dx, dy;
274 Int_t ixm[4][2], iym[4][2];
275 Int_t isec, im1, im2, ico;
277 // Form the 2x2 combinations
278 // 0-0, 0-1, 1-0, 1-1
280 for (im1=0; im1<2; im1++) {
281 for (im2=0; im2<2; im2++) {
282 xm[ico][0]=fX[fIndLocal[im1][0]][0];
283 ym[ico][0]=fY[fIndLocal[im1][0]][0];
284 xm[ico][1]=fX[fIndLocal[im2][1]][1];
285 ym[ico][1]=fY[fIndLocal[im2][1]][1];
287 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
288 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
289 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
290 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
294 // ico = 0 : first local maximum on cathodes 1 and 2
295 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
296 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
297 // ico = 3 : second local maximum on cathodes 1 and 2
299 // Analyse the combinations and keep those that are possible !
300 // For each combination check consistency in x and y
305 for (ico=0; ico<4; ico++) {
306 accepted[ico]=kFALSE;
307 // cathode one: x-coordinate
308 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
309 dpx=fSeg[0]->Dpx(isec)/2.;
310 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
311 // cathode two: y-coordinate
312 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
313 dpy=fSeg[1]->Dpy(isec)/2.;
314 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
315 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
316 if ((dx <= dpx) && (dy <= dpy)) {
322 accepted[ico]=kFALSE;
327 fprintf(stderr,"\n iacc=2: No problem ! \n");
328 } else if (iacc==4) {
329 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
330 } else if (iacc==0) {
331 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
334 // Initial value for charge ratios
335 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
336 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
337 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
338 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
340 // ******* iacc = 0 *******
341 // No combinations found between the 2 cathodes
342 // We keep the center of gravity of the cluster
347 // ******* iacc = 1 *******
348 // Only one combination found between the 2 cathodes
351 // Initial values for the 2 maxima (x,y)
353 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
354 // 1 maximum is initialised with the other maximum of the first cathode
356 fprintf(stderr,"ico=0\n");
361 } else if (accepted[1]){
362 fprintf(stderr,"ico=1\n");
367 } else if (accepted[2]){
368 fprintf(stderr,"ico=2\n");
373 } else if (accepted[3]){
374 fprintf(stderr,"ico=3\n");
380 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
381 chi2=CombiDoubleMathiesonFit(c);
382 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
383 // Float_t prob = TMath::Prob(chi2,ndf);
384 // prob2->Fill(prob);
385 // chi2_2->Fill(chi2);
386 fprintf(stderr," chi2 %f\n",chi2);
388 // If reasonable chi^2 add result to the list of rawclusters
393 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
394 // 1 maximum is initialised with the other maximum of the second cathode
396 fprintf(stderr,"ico=0\n");
401 } else if (accepted[1]){
402 fprintf(stderr,"ico=1\n");
407 } else if (accepted[2]){
408 fprintf(stderr,"ico=2\n");
413 } else if (accepted[3]){
414 fprintf(stderr,"ico=3\n");
420 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
421 chi2=CombiDoubleMathiesonFit(c);
422 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
423 // Float_t prob = TMath::Prob(chi2,ndf);
424 // prob2->Fill(prob);
425 // chi2_2->Fill(chi2);
426 fprintf(stderr," chi2 %f\n",chi2);
428 // If reasonable chi^2 add result to the list of rawclusters
432 //We keep only the combination found (X->cathode 2, Y->cathode 1)
433 for (Int_t ico=0; ico<2; ico++) {
435 AliMUONRawCluster cnew;
437 for (cath=0; cath<2; cath++) {
438 cnew.fX[cath]=Float_t(xm[ico][1]);
439 cnew.fY[cath]=Float_t(ym[ico][0]);
440 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
441 for (i=0; i<fMul[cath]; i++) {
442 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
443 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
445 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
446 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
447 FillCluster(&cnew,cath);
449 cnew.fClusterType=cnew.PhysicsContribution();
458 // ******* iacc = 2 *******
459 // Two combinations found between the 2 cathodes
462 // Was the same maximum taken twice
463 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
464 fprintf(stderr,"\n Maximum taken twice !!!\n");
466 // Have a try !! with that
467 if (accepted[0]&&accepted[3]) {
478 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
479 chi2=CombiDoubleMathiesonFit(c);
480 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
481 // Float_t prob = TMath::Prob(chi2,ndf);
482 // prob2->Fill(prob);
483 // chi2_2->Fill(chi2);
487 // No ghosts ! No Problems ! - Perform one fit only !
488 if (accepted[0]&&accepted[3]) {
499 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
500 chi2=CombiDoubleMathiesonFit(c);
501 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
502 // Float_t prob = TMath::Prob(chi2,ndf);
503 // prob2->Fill(prob);
504 // chi2_2->Fill(chi2);
505 fprintf(stderr," chi2 %f\n",chi2);
509 // ******* iacc = 4 *******
510 // Four combinations found between the 2 cathodes
512 } else if (iacc==4) {
513 // Perform fits for the two possibilities !!
518 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
519 chi2=CombiDoubleMathiesonFit(c);
520 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
521 // Float_t prob = TMath::Prob(chi2,ndf);
522 // prob2->Fill(prob);
523 // chi2_2->Fill(chi2);
524 fprintf(stderr," chi2 %f\n",chi2);
530 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
531 chi2=CombiDoubleMathiesonFit(c);
532 // ndf = fgNbins[0]+fgNbins[1]-6;
533 // prob = TMath::Prob(chi2,ndf);
534 // prob2->Fill(prob);
535 // chi2_2->Fill(chi2);
536 fprintf(stderr," chi2 %f\n",chi2);
540 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
541 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
542 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
543 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
545 Float_t xm[4][2], ym[4][2];
546 Float_t dpx, dpy, dx, dy;
547 Int_t ixm[4][2], iym[4][2];
548 Int_t isec, im1, ico;
550 // Form the 2x2 combinations
551 // 0-0, 0-1, 1-0, 1-1
553 for (im1=0; im1<2; im1++) {
554 xm[ico][0]=fX[fIndLocal[im1][0]][0];
555 ym[ico][0]=fY[fIndLocal[im1][0]][0];
556 xm[ico][1]=fX[fIndLocal[0][1]][1];
557 ym[ico][1]=fY[fIndLocal[0][1]][1];
559 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
560 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
561 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
562 iym[ico][1]=fIy[fIndLocal[0][1]][1];
565 // ico = 0 : first local maximum on cathodes 1 and 2
566 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
568 // Analyse the combinations and keep those that are possible !
569 // For each combination check consistency in x and y
574 for (ico=0; ico<2; ico++) {
575 accepted[ico]=kFALSE;
576 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
577 dpx=fSeg[0]->Dpx(isec)/2.;
578 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
579 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
580 dpy=fSeg[1]->Dpy(isec)/2.;
581 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
582 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
583 if ((dx <= dpx) && (dy <= dpy)) {
589 accepted[ico]=kFALSE;
601 chi21=CombiDoubleMathiesonFit(c);
602 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
603 // Float_t prob = TMath::Prob(chi2,ndf);
604 // prob2->Fill(prob);
605 // chi2_2->Fill(chi21);
606 fprintf(stderr," chi2 %f\n",chi21);
607 if (chi21<10) Split(c);
608 } else if (accepted[1]) {
613 chi22=CombiDoubleMathiesonFit(c);
614 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
615 // Float_t prob = TMath::Prob(chi2,ndf);
616 // prob2->Fill(prob);
617 // chi2_2->Fill(chi22);
618 fprintf(stderr," chi2 %f\n",chi22);
619 if (chi22<10) Split(c);
622 if (chi21 > 10 && chi22 > 10) {
623 // We keep only the combination found (X->cathode 2, Y->cathode 1)
624 for (Int_t ico=0; ico<2; ico++) {
626 AliMUONRawCluster cnew;
628 for (cath=0; cath<2; cath++) {
629 cnew.fX[cath]=Float_t(xm[ico][1]);
630 cnew.fY[cath]=Float_t(ym[ico][0]);
631 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
632 for (i=0; i<fMul[cath]; i++) {
633 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
634 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
636 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
637 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
638 FillCluster(&cnew,cath);
640 cnew.fClusterType=cnew.PhysicsContribution();
647 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
648 // (3') One local maximum on cathode 1 and two maxima on cathode 2
649 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
650 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
652 Float_t xm[4][2], ym[4][2];
653 Float_t dpx, dpy, dx, dy;
654 Int_t ixm[4][2], iym[4][2];
655 Int_t isec, im1, ico;
657 // Form the 2x2 combinations
658 // 0-0, 0-1, 1-0, 1-1
660 for (im1=0; im1<2; im1++) {
661 xm[ico][0]=fX[fIndLocal[0][0]][0];
662 ym[ico][0]=fY[fIndLocal[0][0]][0];
663 xm[ico][1]=fX[fIndLocal[im1][1]][1];
664 ym[ico][1]=fY[fIndLocal[im1][1]][1];
666 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
667 iym[ico][0]=fIy[fIndLocal[0][0]][0];
668 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
669 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
672 // ico = 0 : first local maximum on cathodes 1 and 2
673 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
675 // Analyse the combinations and keep those that are possible !
676 // For each combination check consistency in x and y
681 for (ico=0; ico<2; ico++) {
682 accepted[ico]=kFALSE;
683 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
684 dpx=fSeg[0]->Dpx(isec)/2.;
685 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
686 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
687 dpy=fSeg[1]->Dpy(isec)/2.;
688 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
689 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
690 if ((dx <= dpx) && (dy <= dpy)) {
693 fprintf(stderr,"ico %d\n",ico);
697 accepted[ico]=kFALSE;
709 chi21=CombiDoubleMathiesonFit(c);
710 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
711 // Float_t prob = TMath::Prob(chi2,ndf);
712 // prob2->Fill(prob);
713 // chi2_2->Fill(chi21);
714 fprintf(stderr," chi2 %f\n",chi21);
715 if (chi21<10) Split(c);
716 } else if (accepted[1]) {
721 chi22=CombiDoubleMathiesonFit(c);
722 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
723 // Float_t prob = TMath::Prob(chi2,ndf);
724 // prob2->Fill(prob);
725 // chi2_2->Fill(chi22);
726 fprintf(stderr," chi2 %f\n",chi22);
727 if (chi22<10) Split(c);
730 if (chi21 > 10 && chi22 > 10) {
731 //We keep only the combination found (X->cathode 2, Y->cathode 1)
732 for (Int_t ico=0; ico<2; ico++) {
734 AliMUONRawCluster cnew;
736 for (cath=0; cath<2; cath++) {
737 cnew.fX[cath]=Float_t(xm[ico][1]);
738 cnew.fY[cath]=Float_t(ym[ico][0]);
739 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
740 for (i=0; i<fMul[cath]; i++) {
741 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
742 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
744 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
745 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
746 FillCluster(&cnew,cath);
748 cnew.fClusterType=cnew.PhysicsContribution();
755 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
756 // (4) At least three local maxima on cathode 1 or on cathode 2
757 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
758 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
760 Int_t param = fNLocal[0]*fNLocal[1];
763 Float_t ** xm = new Float_t * [param];
764 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
765 Float_t ** ym = new Float_t * [param];
766 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
767 Int_t ** ixm = new Int_t * [param];
768 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
769 Int_t ** iym = new Int_t * [param];
770 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
773 Float_t dpx, dpy, dx, dy;
776 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
777 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
778 xm[ico][0]=fX[fIndLocal[im1][0]][0];
779 ym[ico][0]=fY[fIndLocal[im1][0]][0];
780 xm[ico][1]=fX[fIndLocal[im2][1]][1];
781 ym[ico][1]=fY[fIndLocal[im2][1]][1];
783 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
784 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
785 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
786 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
793 fprintf(stderr,"nIco %d\n",nIco);
794 for (ico=0; ico<nIco; ico++) {
795 fprintf(stderr,"ico = %d\n",ico);
796 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
797 dpx=fSeg[0]->Dpx(isec)/2.;
798 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
799 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
800 dpy=fSeg[1]->Dpy(isec)/2.;
801 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
803 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
804 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
805 if ((dx <= dpx) && (dy <= dpy)) {
806 fprintf(stderr,"ok\n");
808 AliMUONRawCluster cnew;
809 for (cath=0; cath<2; cath++) {
810 cnew.fX[cath]=Float_t(xm[ico][1]);
811 cnew.fY[cath]=Float_t(ym[ico][0]);
812 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
813 for (i=0; i<fMul[cath]; i++) {
814 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
815 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
817 FillCluster(&cnew,cath);
819 cnew.fClusterType=cnew.PhysicsContribution();
831 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
833 // Find all local maxima of a cluster
834 printf("\n Find Local maxima !");
838 Int_t cath, cath1; // loops over cathodes
839 Int_t i; // loops over digits
840 Int_t j; // loops over cathodes
844 // counters for number of local maxima
845 fNLocal[0]=fNLocal[1]=0;
846 // flags digits as local maximum
847 Bool_t isLocal[100][2];
848 for (i=0; i<100;i++) {
849 isLocal[i][0]=isLocal[i][1]=kFALSE;
851 // number of next neighbours and arrays to store them
854 // loop over cathodes
855 for (cath=0; cath<2; cath++) {
856 // loop over cluster digits
857 for (i=0; i<fMul[cath]; i++) {
858 // get neighbours for that digit and assume that it is local maximum
859 fSeg[cath]->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
860 isLocal[i][cath]=kTRUE;
861 Int_t isec= fSeg[cath]->Sector(fIx[i][cath], fIy[i][cath]);
862 Float_t a0 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
863 // loop over next neighbours, if at least one neighbour has higher charger assumption
864 // digit is not local maximum
865 for (j=0; j<nn; j++) {
866 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
867 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
868 isec=fSeg[cath]->Sector(x[j], y[j]);
869 Float_t a1 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
870 if (digt->fSignal/a1 > fQ[i][cath]/a0) {
871 isLocal[i][cath]=kFALSE;
874 // handle special case of neighbouring pads with equal signal
875 } else if (digt->fSignal == fQ[i][cath]) {
876 if (fNLocal[cath]>0) {
877 for (Int_t k=0; k<fNLocal[cath]; k++) {
878 if (x[j]==fIx[fIndLocal[k][cath]][cath]
879 && y[j]==fIy[fIndLocal[k][cath]][cath])
881 isLocal[i][cath]=kFALSE;
883 } // loop over local maxima
884 } // are there already local maxima
886 } // loop over next neighbours
887 if (isLocal[i][cath]) {
888 fIndLocal[fNLocal[cath]][cath]=i;
891 } // loop over all digits
892 } // loop over cathodes
894 printf("\n Found %d %d %d %d local Maxima\n",
895 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
896 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
897 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
902 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
903 Int_t iback=fNLocal[0];
905 // Two local maxima on cathode 2 and one maximum on cathode 1
906 // Look for local maxima considering up and down neighbours on the 1st cathode only
908 // Loop over cluster digits
912 for (i=0; i<fMul[cath]; i++) {
913 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
914 dpy=fSeg[cath]->Dpy(isec);
915 dpx=fSeg[cath]->Dpx(isec);
916 if (isLocal[i][cath]) continue;
917 // Pad position should be consistent with position of local maxima on the opposite cathode
918 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
919 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
922 // get neighbours for that digit and assume that it is local maximum
923 isLocal[i][cath]=kTRUE;
924 // compare signal to that on the two neighbours on the left and on the right
925 // iNN counts the number of neighbours with signal, it should be 1 or 2
929 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpy);
935 ix = fSeg[cath]->Ix();
936 iy = fSeg[cath]->Iy();
937 // skip the current pad
938 if (iy == fIy[i][cath]) continue;
940 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
942 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
943 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
945 } // Loop over pad neighbours in y
946 if (isLocal[i][cath] && iNN>0) {
947 fIndLocal[fNLocal[cath]][cath]=i;
950 } // loop over all digits
951 // if one additional maximum has been found we are happy
952 // if more maxima have been found restore the previous situation
954 "\n New search gives %d local maxima for cathode 1 \n",
957 " %d local maxima for cathode 2 \n",
959 if (fNLocal[cath]>2) {
963 } // 1,2 local maxima
965 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
966 Int_t iback=fNLocal[1];
968 // Two local maxima on cathode 1 and one maximum on cathode 2
969 // Look for local maxima considering left and right neighbours on the 2nd cathode only
973 // Loop over cluster digits
974 for (i=0; i<fMul[cath]; i++) {
975 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
976 dpx=fSeg[cath]->Dpx(isec);
977 dpy=fSeg[cath]->Dpy(isec);
978 if (isLocal[i][cath]) continue;
979 // Pad position should be consistent with position of local maxima on the opposite cathode
980 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
981 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.))
984 // get neighbours for that digit and assume that it is local maximum
985 isLocal[i][cath]=kTRUE;
986 // compare signal to that on the two neighbours on the left and on the right
988 // iNN counts the number of neighbours with signal, it should be 1 or 2
991 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpx);
997 ix = fSeg[cath]->Ix();
998 iy = fSeg[cath]->Iy();
1000 // skip the current pad
1001 if (ix == fIx[i][cath]) continue;
1003 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
1005 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
1006 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1008 } // Loop over pad neighbours in x
1009 if (isLocal[i][cath] && iNN>0) {
1010 fIndLocal[fNLocal[cath]][cath]=i;
1013 } // loop over all digits
1014 // if one additional maximum has been found we are happy
1015 // if more maxima have been found restore the previous situation
1016 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
1017 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
1018 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
1019 if (fNLocal[cath]>2) {
1020 fNLocal[cath]=iback;
1022 } // 2,1 local maxima
1026 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
1029 // Completes cluster information starting from list of digits
1036 c->fPeakSignal[cath]=c->fPeakSignal[0];
1038 c->fPeakSignal[cath]=0;
1048 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1049 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1051 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1052 ix=dig->fPadX+c->fOffsetMap[i][cath];
1054 Int_t q=dig->fSignal;
1055 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1056 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1057 if (dig->fPhysics >= dig->fSignal) {
1058 c->fPhysicsMap[i]=2;
1059 } else if (dig->fPhysics == 0) {
1060 c->fPhysicsMap[i]=0;
1061 } else c->fPhysicsMap[i]=1;
1064 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1065 // peak signal and track list
1066 if (q>c->fPeakSignal[cath]) {
1067 c->fPeakSignal[cath]=q;
1068 c->fTracks[0]=dig->fHit;
1069 c->fTracks[1]=dig->fTracks[0];
1070 c->fTracks[2]=dig->fTracks[1];
1071 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1075 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1080 } // loop over digits
1081 // fprintf(stderr," fin du cluster c\n");
1085 c->fX[cath]/=c->fQ[cath];
1086 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1087 c->fY[cath]/=c->fQ[cath];
1089 // apply correction to the coordinate along the anode wire
1093 fSeg[cath]->GetPadI(x, y, fZPlane, ix, iy);
1094 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1095 Int_t isec=fSeg[cath]->Sector(ix,iy);
1096 TF1* cogCorr = fSeg[cath]->CorrFunc(isec-1);
1099 Float_t yOnPad=(c->fY[cath]-y)/fSeg[cath]->Dpy(isec);
1100 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1105 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1108 // Completes cluster information starting from list of digits
1118 Float_t xpad, ypad, zpad;
1121 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1123 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1125 GetPadC(dig->fPadX,dig->fPadY,xpad,ypad, zpad);
1126 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1127 dx = xpad - c->fX[0];
1128 dy = ypad - c->fY[0];
1129 dr = TMath::Sqrt(dx*dx+dy*dy);
1133 fprintf(stderr," dr %f\n",dr);
1134 Int_t q=dig->fSignal;
1135 if (dig->fPhysics >= dig->fSignal) {
1136 c->fPhysicsMap[i]=2;
1137 } else if (dig->fPhysics == 0) {
1138 c->fPhysicsMap[i]=0;
1139 } else c->fPhysicsMap[i]=1;
1140 c->fPeakSignal[cath]=q;
1141 c->fTracks[0]=dig->fHit;
1142 c->fTracks[1]=dig->fTracks[0];
1143 c->fTracks[2]=dig->fTracks[1];
1144 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1147 } // loop over digits
1149 // apply correction to the coordinate along the anode wire
1150 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1153 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1157 // Find a super cluster on both cathodes
1160 // Add i,j as element of the cluster
1163 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1164 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1165 Int_t q=dig->fSignal;
1166 Int_t theX=dig->fPadX;
1167 Int_t theY=dig->fPadY;
1169 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1170 c.fPeakSignal[cath]=q;
1171 c.fTracks[0]=dig->fHit;
1172 c.fTracks[1]=dig->fTracks[0];
1173 c.fTracks[2]=dig->fTracks[1];
1177 // Make sure that list of digits is ordered
1179 Int_t mu=c.fMultiplicity[cath];
1180 c.fIndexMap[mu][cath]=idx;
1182 if (dig->fPhysics >= dig->fSignal) {
1183 c.fPhysicsMap[mu]=2;
1184 } else if (dig->fPhysics == 0) {
1185 c.fPhysicsMap[mu]=0;
1186 } else c.fPhysicsMap[mu]=1;
1190 for (Int_t ind = mu-1; ind >= 0; ind--) {
1191 Int_t ist=(c.fIndexMap)[ind][cath];
1192 Int_t ql=fInput->Digit(cath, ist)->fSignal;
1193 Int_t ix=fInput->Digit(cath, ist)->fPadX;
1194 Int_t iy=fInput->Digit(cath, ist)->fPadY;
1196 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1197 c.fIndexMap[ind][cath]=idx;
1198 c.fIndexMap[ind+1][cath]=ist;
1206 c.fMultiplicity[cath]++;
1207 if (c.fMultiplicity[cath] >= 50 ) {
1208 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1209 c.fMultiplicity[cath]=49;
1212 // Prepare center of gravity calculation
1214 fSeg[cath]->GetPadC(i, j, x, y, z);
1220 // Flag hit as "taken"
1221 fHitMap[cath]->FlagHit(i,j);
1223 // Now look recursively for all neighbours and pad hit on opposite cathode
1225 // Loop over neighbours
1229 Int_t xList[10], yList[10];
1230 fSeg[cath]->Neighbours(i,j,&nn,xList,yList);
1231 for (Int_t in=0; in<nn; in++) {
1235 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) {
1236 // printf("\n Neighbours %d %d %d", cath, ix, iy);
1237 FindCluster(ix, iy, cath, c);
1242 Int_t iXopp[50], iYopp[50];
1244 // Neighbours on opposite cathode
1245 // Take into account that several pads can overlap with the present pad
1246 Int_t isec=fSeg[cath]->Sector(i,j);
1252 dx = (fSeg[cath]->Dpx(isec))/2.;
1257 dy = (fSeg[cath]->Dpy(isec))/2;
1259 // loop over pad neighbours on opposite cathode
1260 for (fSeg[iop]->FirstPad(x, y, fZPlane, dx, dy);
1261 fSeg[iop]->MorePads();
1262 fSeg[iop]->NextPad())
1265 ix = fSeg[iop]->Ix(); iy = fSeg[iop]->Iy();
1266 // printf("\n ix, iy: %f %f %f %d %d %d", x,y,z,ix, iy, fSector);
1267 if (fHitMap[iop]->TestHit(ix,iy)==kUnused){
1270 // printf("\n Opposite %d %d %d", iop, ix, iy);
1273 } // Loop over pad neighbours
1274 // This had to go outside the loop since recursive calls inside the iterator are not possible
1277 for (jopp=0; jopp<nOpp; jopp++) {
1278 if (fHitMap[iop]->TestHit(iXopp[jopp],iYopp[jopp]) == kUnused)
1279 FindCluster(iXopp[jopp], iYopp[jopp], iop, c);
1283 //_____________________________________________________________________________
1285 void AliMUONClusterFinderVS::FindRawClusters()
1288 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1289 // fills the tree with raw clusters
1292 // Return if no input datad available
1293 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1295 fSeg[0] = fInput->Segmentation(0);
1296 fSeg[1] = fInput->Segmentation(1);
1298 fHitMap[0] = new AliMUONHitMapA1(fSeg[0], fInput->Digits(0));
1299 fHitMap[1] = new AliMUONHitMapA1(fSeg[1], fInput->Digits(1));
1307 fHitMap[0]->FillHits();
1308 fHitMap[1]->FillHits();
1310 // Outer Loop over Cathodes
1311 for (cath=0; cath<2; cath++) {
1312 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1313 dig = fInput->Digit(cath, ndig);
1316 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1320 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1321 AliMUONRawCluster c;
1322 c.fMultiplicity[0]=0;
1323 c.fMultiplicity[1]=0;
1324 c.fPeakSignal[cath]=dig->fSignal;
1325 c.fTracks[0]=dig->fHit;
1326 c.fTracks[1]=dig->fTracks[0];
1327 c.fTracks[2]=dig->fTracks[1];
1328 // tag the beginning of cluster list in a raw cluster
1331 fSeg[cath]->GetPadC(i,j,xcu, ycu, fZPlane);
1332 fSector= fSeg[cath]->Sector(i,j)/100;
1333 // printf("\n New Seed %d %d ", i,j);
1335 FindCluster(i,j,cath,c);
1336 // ^^^^^^^^^^^^^^^^^^^^^^^^
1337 // center of gravity
1339 c.fX[0]=fSeg[0]->GetAnod(c.fX[0]);
1342 c.fX[1]=fSeg[0]->GetAnod(c.fX[1]);
1348 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",
1349 c.fMultiplicity[0],c.fX[0],c.fY[0]);
1350 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",
1351 c.fMultiplicity[1],c.fX[1],c.fY[1]);
1353 // Analyse cluster and decluster if necessary
1356 c.fNcluster[1]=fNRawClusters;
1357 c.fClusterType=c.PhysicsContribution();
1364 // reset Cluster object
1365 { // begin local scope
1366 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1367 } // end local scope
1369 { // begin local scope
1370 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1371 } // end local scope
1373 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1377 } // end loop cathodes
1382 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1384 // Performs a single Mathieson fit on one cathode
1386 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1388 clusterInput.Fitter()->SetFCN(fcnS1);
1389 clusterInput.Fitter()->mninit(2,10,7);
1390 Double_t arglist[20];
1393 // Set starting values
1394 static Double_t vstart[2];
1399 // lower and upper limits
1400 static Double_t lower[2], upper[2];
1402 fSeg[cath]->GetPadI(c->fX[cath], c->fY[cath], fZPlane, ix, iy);
1403 Int_t isec=fSeg[cath]->Sector(ix, iy);
1404 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec)/2;
1405 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec)/2;
1407 upper[0]=lower[0]+fSeg[cath]->Dpx(isec);
1408 upper[1]=lower[1]+fSeg[cath]->Dpy(isec);
1411 static Double_t step[2]={0.0005, 0.0005};
1413 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1414 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1415 // ready for minimisation
1416 clusterInput.Fitter()->SetPrintLevel(1);
1417 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1421 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1422 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1423 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1424 Double_t fmin, fedm, errdef;
1425 Int_t npari, nparx, istat;
1427 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1431 // Get fitted parameters
1432 Double_t xrec, yrec;
1434 Double_t epxz, b1, b2;
1436 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1437 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1443 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1445 // Perform combined Mathieson fit on both cathode planes
1447 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1448 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1449 clusterInput.Fitter()->mninit(2,10,7);
1450 Double_t arglist[20];
1453 static Double_t vstart[2];
1454 vstart[0]=fXInit[0];
1455 vstart[1]=fYInit[0];
1458 // lower and upper limits
1459 static Float_t lower[2], upper[2];
1461 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1462 isec=fSeg[0]->Sector(ix, iy);
1463 Float_t dpy=fSeg[0]->Dpy(isec);
1464 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1465 isec=fSeg[1]->Sector(ix, iy);
1466 Float_t dpx=fSeg[1]->Dpx(isec);
1469 Float_t xdum, ydum, zdum;
1471 // Find save upper and lower limits
1475 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1476 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1478 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1479 fSeg[1]->GetPadC(ix,iy, upper[0], ydum, zdum);
1480 if (icount ==0) lower[0]=upper[0];
1484 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1487 printf("\n single y %f %f", fXInit[0], fYInit[0]);
1489 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1490 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1492 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1493 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1494 if (icount ==0) lower[1]=upper[1];
1496 printf("\n upper lower %d %f %f", icount, upper[1], lower[1]);
1499 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1502 static Double_t step[2]={0.00001, 0.0001};
1504 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1505 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1506 // ready for minimisation
1507 clusterInput.Fitter()->SetPrintLevel(1);
1508 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1512 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1513 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1514 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1515 Double_t fmin, fedm, errdef;
1516 Int_t npari, nparx, istat;
1518 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1522 // Get fitted parameters
1523 Double_t xrec, yrec;
1525 Double_t epxz, b1, b2;
1527 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1528 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1534 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1536 // Performs a double Mathieson fit on one cathode
1540 // Initialise global variables for fit
1541 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1542 clusterInput.Fitter()->SetFCN(fcnS2);
1543 clusterInput.Fitter()->mninit(5,10,7);
1544 Double_t arglist[20];
1547 // Set starting values
1548 static Double_t vstart[5];
1549 vstart[0]=fX[fIndLocal[0][cath]][cath];
1550 vstart[1]=fY[fIndLocal[0][cath]][cath];
1551 vstart[2]=fX[fIndLocal[1][cath]][cath];
1552 vstart[3]=fY[fIndLocal[1][cath]][cath];
1553 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1554 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1555 // lower and upper limits
1556 static Float_t lower[5], upper[5];
1557 Int_t isec=fSeg[cath]->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1558 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec);
1559 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec);
1561 upper[0]=lower[0]+2.*fSeg[cath]->Dpx(isec);
1562 upper[1]=lower[1]+2.*fSeg[cath]->Dpy(isec);
1564 isec=fSeg[cath]->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1565 lower[2]=vstart[2]-fSeg[cath]->Dpx(isec)/2;
1566 lower[3]=vstart[3]-fSeg[cath]->Dpy(isec)/2;
1568 upper[2]=lower[2]+fSeg[cath]->Dpx(isec);
1569 upper[3]=lower[3]+fSeg[cath]->Dpy(isec);
1574 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
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 // ready for minimisation
1582 clusterInput.Fitter()->SetPrintLevel(-1);
1583 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1587 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1588 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1589 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1590 // Get fitted parameters
1591 Double_t xrec[2], yrec[2], qfrac;
1593 Double_t epxz, b1, b2;
1595 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1596 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1597 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1598 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1599 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1601 Double_t fmin, fedm, errdef;
1602 Int_t npari, nparx, istat;
1604 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1609 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1612 // Perform combined double Mathieson fit on both cathode planes
1614 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1615 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1616 clusterInput.Fitter()->mninit(6,10,7);
1617 Double_t arglist[20];
1620 // Set starting values
1621 static Double_t vstart[6];
1622 vstart[0]=fXInit[0];
1623 vstart[1]=fYInit[0];
1624 vstart[2]=fXInit[1];
1625 vstart[3]=fYInit[1];
1626 vstart[4]=fQrInit[0];
1627 vstart[5]=fQrInit[1];
1628 // lower and upper limits
1629 static Float_t lower[6], upper[6];
1633 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1634 isec=fSeg[1]->Sector(ix, iy);
1635 dpx=fSeg[1]->Dpx(isec);
1637 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1638 isec=fSeg[0]->Sector(ix, iy);
1639 dpy=fSeg[0]->Dpy(isec);
1643 Float_t xdum, ydum, zdum;
1644 // printf("\n Cluster Finder: %f %f %f %f ", fXInit[0], fXInit[1],fYInit[0], fYInit[1] );
1646 // Find save upper and lower limits
1649 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1650 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1652 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1653 fSeg[1]->GetPadC(ix,iy,upper[0],ydum,zdum);
1654 if (icount ==0) lower[0]=upper[0];
1657 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1660 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1661 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1663 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1664 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1665 if (icount ==0) lower[1]=upper[1];
1668 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1670 fSeg[1]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1671 isec=fSeg[1]->Sector(ix, iy);
1672 dpx=fSeg[1]->Dpx(isec);
1673 fSeg[0]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1674 isec=fSeg[0]->Sector(ix, iy);
1675 dpy=fSeg[0]->Dpy(isec);
1678 // Find save upper and lower limits
1682 for (fSeg[1]->FirstPad(fXInit[1], fYInit[1], fZPlane, dpx, 0);
1683 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1685 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1686 fSeg[1]->GetPadC(ix,iy,upper[2],ydum,zdum);
1687 if (icount ==0) lower[2]=upper[2];
1690 if (lower[2]>upper[2]) {xdum=lower[2]; lower[2]=upper[2]; upper[2]=xdum;}
1694 for (fSeg[0]->FirstPad(fXInit[1], fYInit[1], fZPlane, 0, dpy);
1695 fSeg[0]-> MorePads(); fSeg[0]->NextPad())
1697 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1698 fSeg[0]->GetPadC(ix,iy,xdum,upper[3],zdum);
1699 if (icount ==0) lower[3]=upper[3];
1702 if (lower[3]>upper[3]) {xdum=lower[3]; lower[3]=upper[3]; upper[3]=xdum;}
1710 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1711 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1712 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1713 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1714 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1715 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1716 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1717 // ready for minimisation
1718 clusterInput.Fitter()->SetPrintLevel(-1);
1719 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1723 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1724 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1725 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1726 // Get fitted parameters
1728 Double_t epxz, b1, b2;
1730 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1731 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1732 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1733 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1734 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1735 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1737 Double_t fmin, fedm, errdef;
1738 Int_t npari, nparx, istat;
1740 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1748 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1751 // One cluster for each maximum
1754 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1755 for (j=0; j<2; j++) {
1756 AliMUONRawCluster cnew;
1757 for (cath=0; cath<2; cath++) {
1758 cnew.fChi2[cath]=fChi2[0];
1761 cnew.fNcluster[0]=-1;
1762 cnew.fNcluster[1]=fNRawClusters;
1764 cnew.fNcluster[0]=fNPeaks;
1765 cnew.fNcluster[1]=0;
1767 cnew.fMultiplicity[cath]=0;
1768 cnew.fX[cath]=Float_t(fXFit[j]);
1769 cnew.fY[cath]=Float_t(fYFit[j]);
1771 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
1773 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
1775 fSeg[cath]->SetHit(fXFit[j],fYFit[j],fZPlane);
1776 for (i=0; i<fMul[cath]; i++) {
1777 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1778 c->fIndexMap[i][cath];
1779 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
1780 Float_t q1=fInput->Response()->IntXY(fSeg[cath]);
1781 cnew.fContMap[i][cath]
1782 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1783 cnew.fMultiplicity[cath]++;
1785 FillCluster(&cnew,0,cath);
1788 cnew.fClusterType=cnew.PhysicsContribution();
1789 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1796 // Minimisation functions
1798 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1800 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1807 for (i=0; i<clusterInput.Nmul(0); i++) {
1808 Float_t q0=clusterInput.Charge(i,0);
1809 Float_t q1=clusterInput.DiscrChargeS1(i,par);
1818 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1820 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1827 for (cath=0; cath<2; cath++) {
1828 for (i=0; i<clusterInput.Nmul(cath); i++) {
1829 Float_t q0=clusterInput.Charge(i,cath);
1830 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
1841 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1843 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1850 for (i=0; i<clusterInput.Nmul(0); i++) {
1852 Float_t q0=clusterInput.Charge(i,0);
1853 Float_t q1=clusterInput.DiscrChargeS2(i,par);
1863 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1865 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1871 for (cath=0; cath<2; cath++) {
1872 for (i=0; i<clusterInput.Nmul(cath); i++) {
1873 Float_t q0=clusterInput.Charge(i,cath);
1874 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
1884 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1887 // Add a raw cluster copy to the list
1889 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1890 pMUON->AddRawCluster(fInput->Chamber(),c);
1892 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1895 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
1896 if (fTrack[0]==-1 || fTrack[1]==-1) {
1898 } else if (t==fTrack[0] || t==fTrack[1]) {
1905 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1906 ::operator = (const AliMUONClusterFinderVS& rhs)
1908 // Dummy assignment operator