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.17 2001/01/23 18:58:19 hristov
18 Initialisation of some pointers
20 Revision 1.16 2000/12/21 23:27:30 morsch
21 Error in argument list of AddRawCluster corrected.
23 Revision 1.15 2000/12/21 22:14:38 morsch
24 Clean-up of coding rule violations.
26 Revision 1.14 2000/10/23 16:03:45 morsch
27 Correct z-position of all clusters created "on the flight".
29 Revision 1.13 2000/10/23 13:38:23 morsch
30 Set correct z-coordinate when cluster is split.
32 Revision 1.12 2000/10/18 11:42:06 morsch
33 - AliMUONRawCluster contains z-position.
34 - Some clean-up of useless print statements during initialisations.
36 Revision 1.11 2000/10/06 09:04:05 morsch
37 - Dummy z-arguments in GetPadI, SetHit, FirstPad replaced by real z-coordinate
38 to make code work with slat chambers (AM)
39 - Replace GetPadI calls with unchecked x,y coordinates by pad iterator calls wherever possible.
41 Revision 1.10 2000/10/03 13:51:57 egangler
42 Removal of useless dependencies via forward declarations
44 Revision 1.9 2000/10/02 16:58:29 egangler
45 Cleaning of the code :
48 -> some useless includes removed or replaced by "class" statement
50 Revision 1.8 2000/07/03 11:54:57 morsch
51 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
52 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
54 Revision 1.7 2000/06/28 15:16:35 morsch
55 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
56 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
57 framework. The changes should have no side effects (mostly dummy arguments).
58 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
59 of chambers with overlapping modules (MakePadHits, Disintegration).
61 Revision 1.6 2000/06/28 12:19:18 morsch
62 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
63 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
64 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
65 It requires two cathode planes. Small modifications in the code will make it usable for
66 one cathode plane and, hence, more general (for test beam data).
67 AliMUONClusterFinder is now obsolete.
69 Revision 1.5 2000/06/28 08:06:10 morsch
70 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
71 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
72 It also naturally takes care of the TMinuit instance.
74 Revision 1.4 2000/06/27 16:18:47 gosset
75 Finally correct implementation of xm, ym, ixm, iym sizes
76 when at least three local maxima on cathode 1 or on cathode 2
78 Revision 1.3 2000/06/22 14:02:45 morsch
79 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
80 Some HP scope problems corrected (PH)
82 Revision 1.2 2000/06/15 07:58:48 morsch
83 Code from MUON-dev joined
85 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
86 Most coding rule violations corrected.
88 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
89 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
90 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
91 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
92 - For clusters with more than 2 maxima on one of the cathode planes all valid
93 combinations of maxima on the two cathodes are preserved. The position of the maxima is
94 taken as the hit position.
95 - New FillCluster method with 2 arguments to find tracks associated to the clusters
96 defined above added. (Method destinction by argument list not very elegant in this case,
97 should be revides (A.M.)
98 - Bug in if-statement to handle maximum 1 maximum per plane corrected
99 - Two cluster per cathode but only 1 combination valid is handled.
100 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
104 #include "AliMUONClusterFinderVS.h"
105 #include "AliMUONDigit.h"
106 #include "AliMUONRawCluster.h"
107 #include "AliSegmentation.h"
108 #include "AliMUONResponse.h"
109 #include "AliMUONClusterInput.h"
110 #include "AliMUONHitMapA1.h"
119 #include <TPostScript.h>
124 #include <iostream.h>
126 //_____________________________________________________________________
127 // This function is minimized in the double-Mathieson fit
128 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
129 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
130 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
131 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
133 ClassImp(AliMUONClusterFinderVS)
135 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
137 // Default constructor
138 fInput=AliMUONClusterInput::Instance();
141 fTrack[0]=fTrack[1]=-1;
144 for(Int_t i=0; i<100; i++) {
145 for (Int_t j=0; j<2; j++) {
151 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
152 const AliMUONClusterFinderVS & clusterFinder)
154 // Dummy copy Constructor
158 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
160 // Decluster by local maxima
161 SplitByLocalMaxima(cluster);
164 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
166 // Split complex cluster by local maxima
169 fInput->SetCluster(c);
171 fMul[0]=c->fMultiplicity[0];
172 fMul[1]=c->fMultiplicity[1];
175 // dump digit information into arrays
180 for (cath=0; cath<2; cath++) {
182 for (i=0; i<fMul[cath]; i++)
185 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
187 fIx[i][cath]= fDig[i][cath]->PadX();
188 fIy[i][cath]= fDig[i][cath]->PadY();
190 fQ[i][cath] = fDig[i][cath]->Signal();
191 // pad centre coordinates
193 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], fZ[i][cath]);
194 } // loop over cluster digits
195 } // loop over cathodes
201 // Initialise and perform mathieson fits
202 Float_t chi2, oldchi2;
203 // ++++++++++++++++++*************+++++++++++++++++++++
204 // (1) No more than one local maximum per cathode plane
205 // +++++++++++++++++++++++++++++++*************++++++++
206 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
207 (fNLocal[0]==0 && fNLocal[1]==1)) {
209 // Perform combined single Mathieson fit
210 // Initial values for coordinates (x,y)
212 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
213 if (fNLocal[0]==1 && fNLocal[1]==1) {
216 // One local maximum on cathode 1 (X,Y->cathode 1)
217 } else if (fNLocal[0]==1) {
220 // One local maximum on cathode 2 (X,Y->cathode 2)
225 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
226 chi2=CombiSingleMathiesonFit(c);
227 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
228 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
229 // prob1->Fill(prob);
230 // chi2_1->Fill(chi2);
232 fprintf(stderr," chi2 %f ",chi2);
241 c->fX[0]=fSeg[0]->GetAnod(c->fX[0]);
242 c->fX[1]=fSeg[1]->GetAnod(c->fX[1]);
244 // If reasonable chi^2 add result to the list of rawclusters
248 // If not try combined double Mathieson Fit
250 fprintf(stderr," MAUVAIS CHI2 !!!\n");
251 if (fNLocal[0]==1 && fNLocal[1]==1) {
252 fXInit[0]=fX[fIndLocal[0][1]][1];
253 fYInit[0]=fY[fIndLocal[0][0]][0];
254 fXInit[1]=fX[fIndLocal[0][1]][1];
255 fYInit[1]=fY[fIndLocal[0][0]][0];
256 } else if (fNLocal[0]==1) {
257 fXInit[0]=fX[fIndLocal[0][0]][0];
258 fYInit[0]=fY[fIndLocal[0][0]][0];
259 fXInit[1]=fX[fIndLocal[0][0]][0];
260 fYInit[1]=fY[fIndLocal[0][0]][0];
262 fXInit[0]=fX[fIndLocal[0][1]][1];
263 fYInit[0]=fY[fIndLocal[0][1]][1];
264 fXInit[1]=fX[fIndLocal[0][1]][1];
265 fYInit[1]=fY[fIndLocal[0][1]][1];
268 // Initial value for charge ratios
271 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
272 chi2=CombiDoubleMathiesonFit(c);
273 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
274 // Float_t prob = TMath::Prob(chi2,ndf);
275 // prob2->Fill(prob);
276 // chi2_2->Fill(chi2);
278 // Was this any better ??
279 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
280 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
281 fprintf(stderr," Split\n");
282 // Split cluster into two according to fit result
285 fprintf(stderr," Don't Split\n");
291 // +++++++++++++++++++++++++++++++++++++++
292 // (2) Two local maxima per cathode plane
293 // +++++++++++++++++++++++++++++++++++++++
294 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
296 // Let's look for ghosts first
298 Float_t xm[4][2], ym[4][2];
299 Float_t dpx, dpy, dx, dy;
300 Int_t ixm[4][2], iym[4][2];
301 Int_t isec, im1, im2, ico;
303 // Form the 2x2 combinations
304 // 0-0, 0-1, 1-0, 1-1
306 for (im1=0; im1<2; im1++) {
307 for (im2=0; im2<2; im2++) {
308 xm[ico][0]=fX[fIndLocal[im1][0]][0];
309 ym[ico][0]=fY[fIndLocal[im1][0]][0];
310 xm[ico][1]=fX[fIndLocal[im2][1]][1];
311 ym[ico][1]=fY[fIndLocal[im2][1]][1];
313 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
314 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
315 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
316 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
320 // ico = 0 : first local maximum on cathodes 1 and 2
321 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
322 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
323 // ico = 3 : second local maximum on cathodes 1 and 2
325 // Analyse the combinations and keep those that are possible !
326 // For each combination check consistency in x and y
331 for (ico=0; ico<4; ico++) {
332 accepted[ico]=kFALSE;
333 // cathode one: x-coordinate
334 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
335 dpx=fSeg[0]->Dpx(isec)/2.;
336 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
337 // cathode two: y-coordinate
338 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
339 dpy=fSeg[1]->Dpy(isec)/2.;
340 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
341 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
342 if ((dx <= dpx) && (dy <= dpy)) {
348 accepted[ico]=kFALSE;
353 fprintf(stderr,"\n iacc=2: No problem ! \n");
354 } else if (iacc==4) {
355 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
356 } else if (iacc==0) {
357 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
360 // Initial value for charge ratios
361 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
362 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
363 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
364 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
366 // ******* iacc = 0 *******
367 // No combinations found between the 2 cathodes
368 // We keep the center of gravity of the cluster
373 // ******* iacc = 1 *******
374 // Only one combination found between the 2 cathodes
377 // Initial values for the 2 maxima (x,y)
379 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
380 // 1 maximum is initialised with the other maximum of the first cathode
382 fprintf(stderr,"ico=0\n");
387 } else if (accepted[1]){
388 fprintf(stderr,"ico=1\n");
393 } else if (accepted[2]){
394 fprintf(stderr,"ico=2\n");
399 } else if (accepted[3]){
400 fprintf(stderr,"ico=3\n");
406 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
407 chi2=CombiDoubleMathiesonFit(c);
408 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
409 // Float_t prob = TMath::Prob(chi2,ndf);
410 // prob2->Fill(prob);
411 // chi2_2->Fill(chi2);
412 fprintf(stderr," chi2 %f\n",chi2);
414 // If reasonable chi^2 add result to the list of rawclusters
419 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
420 // 1 maximum is initialised with the other maximum of the second cathode
422 fprintf(stderr,"ico=0\n");
427 } else if (accepted[1]){
428 fprintf(stderr,"ico=1\n");
433 } else if (accepted[2]){
434 fprintf(stderr,"ico=2\n");
439 } else if (accepted[3]){
440 fprintf(stderr,"ico=3\n");
446 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
447 chi2=CombiDoubleMathiesonFit(c);
448 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
449 // Float_t prob = TMath::Prob(chi2,ndf);
450 // prob2->Fill(prob);
451 // chi2_2->Fill(chi2);
452 fprintf(stderr," chi2 %f\n",chi2);
454 // If reasonable chi^2 add result to the list of rawclusters
458 //We keep only the combination found (X->cathode 2, Y->cathode 1)
459 for (Int_t ico=0; ico<2; ico++) {
461 AliMUONRawCluster cnew;
463 for (cath=0; cath<2; cath++) {
464 cnew.fX[cath]=Float_t(xm[ico][1]);
465 cnew.fY[cath]=Float_t(ym[ico][0]);
466 cnew.fZ[cath]=fZPlane;
468 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
469 for (i=0; i<fMul[cath]; i++) {
470 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
471 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
473 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
474 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
475 FillCluster(&cnew,cath);
477 cnew.fClusterType=cnew.PhysicsContribution();
486 // ******* iacc = 2 *******
487 // Two combinations found between the 2 cathodes
490 // Was the same maximum taken twice
491 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
492 fprintf(stderr,"\n Maximum taken twice !!!\n");
494 // Have a try !! with that
495 if (accepted[0]&&accepted[3]) {
506 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
507 chi2=CombiDoubleMathiesonFit(c);
508 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
509 // Float_t prob = TMath::Prob(chi2,ndf);
510 // prob2->Fill(prob);
511 // chi2_2->Fill(chi2);
515 // No ghosts ! No Problems ! - Perform one fit only !
516 if (accepted[0]&&accepted[3]) {
527 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
528 chi2=CombiDoubleMathiesonFit(c);
529 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
530 // Float_t prob = TMath::Prob(chi2,ndf);
531 // prob2->Fill(prob);
532 // chi2_2->Fill(chi2);
533 fprintf(stderr," chi2 %f\n",chi2);
537 // ******* iacc = 4 *******
538 // Four combinations found between the 2 cathodes
540 } else if (iacc==4) {
541 // Perform fits for the two possibilities !!
546 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
547 chi2=CombiDoubleMathiesonFit(c);
548 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
549 // Float_t prob = TMath::Prob(chi2,ndf);
550 // prob2->Fill(prob);
551 // chi2_2->Fill(chi2);
552 fprintf(stderr," chi2 %f\n",chi2);
558 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
559 chi2=CombiDoubleMathiesonFit(c);
560 // ndf = fgNbins[0]+fgNbins[1]-6;
561 // prob = TMath::Prob(chi2,ndf);
562 // prob2->Fill(prob);
563 // chi2_2->Fill(chi2);
564 fprintf(stderr," chi2 %f\n",chi2);
568 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
569 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
570 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
571 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
573 Float_t xm[4][2], ym[4][2];
574 Float_t dpx, dpy, dx, dy;
575 Int_t ixm[4][2], iym[4][2];
576 Int_t isec, im1, ico;
578 // Form the 2x2 combinations
579 // 0-0, 0-1, 1-0, 1-1
581 for (im1=0; im1<2; im1++) {
582 xm[ico][0]=fX[fIndLocal[im1][0]][0];
583 ym[ico][0]=fY[fIndLocal[im1][0]][0];
584 xm[ico][1]=fX[fIndLocal[0][1]][1];
585 ym[ico][1]=fY[fIndLocal[0][1]][1];
587 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
588 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
589 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
590 iym[ico][1]=fIy[fIndLocal[0][1]][1];
593 // ico = 0 : first local maximum on cathodes 1 and 2
594 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
596 // Analyse the combinations and keep those that are possible !
597 // For each combination check consistency in x and y
602 for (ico=0; ico<2; ico++) {
603 accepted[ico]=kFALSE;
604 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
605 dpx=fSeg[0]->Dpx(isec)/2.;
606 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
607 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
608 dpy=fSeg[1]->Dpy(isec)/2.;
609 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
610 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
611 if ((dx <= dpx) && (dy <= dpy)) {
617 accepted[ico]=kFALSE;
629 chi21=CombiDoubleMathiesonFit(c);
630 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
631 // Float_t prob = TMath::Prob(chi2,ndf);
632 // prob2->Fill(prob);
633 // chi2_2->Fill(chi21);
634 fprintf(stderr," chi2 %f\n",chi21);
635 if (chi21<10) Split(c);
636 } else if (accepted[1]) {
641 chi22=CombiDoubleMathiesonFit(c);
642 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
643 // Float_t prob = TMath::Prob(chi2,ndf);
644 // prob2->Fill(prob);
645 // chi2_2->Fill(chi22);
646 fprintf(stderr," chi2 %f\n",chi22);
647 if (chi22<10) Split(c);
650 if (chi21 > 10 && chi22 > 10) {
651 // We keep only the combination found (X->cathode 2, Y->cathode 1)
652 for (Int_t ico=0; ico<2; ico++) {
654 AliMUONRawCluster cnew;
656 for (cath=0; cath<2; cath++) {
657 cnew.fX[cath]=Float_t(xm[ico][1]);
658 cnew.fY[cath]=Float_t(ym[ico][0]);
659 cnew.fZ[cath]=fZPlane;
660 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
661 for (i=0; i<fMul[cath]; i++) {
662 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
663 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
665 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
666 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
667 FillCluster(&cnew,cath);
669 cnew.fClusterType=cnew.PhysicsContribution();
676 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
677 // (3') One local maximum on cathode 1 and two maxima on cathode 2
678 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
679 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
681 Float_t xm[4][2], ym[4][2];
682 Float_t dpx, dpy, dx, dy;
683 Int_t ixm[4][2], iym[4][2];
684 Int_t isec, im1, ico;
686 // Form the 2x2 combinations
687 // 0-0, 0-1, 1-0, 1-1
689 for (im1=0; im1<2; im1++) {
690 xm[ico][0]=fX[fIndLocal[0][0]][0];
691 ym[ico][0]=fY[fIndLocal[0][0]][0];
692 xm[ico][1]=fX[fIndLocal[im1][1]][1];
693 ym[ico][1]=fY[fIndLocal[im1][1]][1];
695 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
696 iym[ico][0]=fIy[fIndLocal[0][0]][0];
697 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
698 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
701 // ico = 0 : first local maximum on cathodes 1 and 2
702 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
704 // Analyse the combinations and keep those that are possible !
705 // For each combination check consistency in x and y
710 for (ico=0; ico<2; ico++) {
711 accepted[ico]=kFALSE;
712 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
713 dpx=fSeg[0]->Dpx(isec)/2.;
714 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
715 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
716 dpy=fSeg[1]->Dpy(isec)/2.;
717 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
718 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
719 if ((dx <= dpx) && (dy <= dpy)) {
722 fprintf(stderr,"ico %d\n",ico);
726 accepted[ico]=kFALSE;
738 chi21=CombiDoubleMathiesonFit(c);
739 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
740 // Float_t prob = TMath::Prob(chi2,ndf);
741 // prob2->Fill(prob);
742 // chi2_2->Fill(chi21);
743 fprintf(stderr," chi2 %f\n",chi21);
744 if (chi21<10) Split(c);
745 } else if (accepted[1]) {
750 chi22=CombiDoubleMathiesonFit(c);
751 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
752 // Float_t prob = TMath::Prob(chi2,ndf);
753 // prob2->Fill(prob);
754 // chi2_2->Fill(chi22);
755 fprintf(stderr," chi2 %f\n",chi22);
756 if (chi22<10) Split(c);
759 if (chi21 > 10 && chi22 > 10) {
760 //We keep only the combination found (X->cathode 2, Y->cathode 1)
761 for (Int_t ico=0; ico<2; ico++) {
763 AliMUONRawCluster cnew;
765 for (cath=0; cath<2; cath++) {
766 cnew.fX[cath]=Float_t(xm[ico][1]);
767 cnew.fY[cath]=Float_t(ym[ico][0]);
768 cnew.fZ[cath]=fZPlane;
769 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
770 for (i=0; i<fMul[cath]; i++) {
771 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
772 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
774 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
775 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
776 FillCluster(&cnew,cath);
778 cnew.fClusterType=cnew.PhysicsContribution();
785 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
786 // (4) At least three local maxima on cathode 1 or on cathode 2
787 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
788 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
790 Int_t param = fNLocal[0]*fNLocal[1];
793 Float_t ** xm = new Float_t * [param];
794 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
795 Float_t ** ym = new Float_t * [param];
796 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
797 Int_t ** ixm = new Int_t * [param];
798 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
799 Int_t ** iym = new Int_t * [param];
800 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
803 Float_t dpx, dpy, dx, dy;
806 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
807 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
808 xm[ico][0]=fX[fIndLocal[im1][0]][0];
809 ym[ico][0]=fY[fIndLocal[im1][0]][0];
810 xm[ico][1]=fX[fIndLocal[im2][1]][1];
811 ym[ico][1]=fY[fIndLocal[im2][1]][1];
813 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
814 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
815 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
816 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
823 fprintf(stderr,"nIco %d\n",nIco);
824 for (ico=0; ico<nIco; ico++) {
825 fprintf(stderr,"ico = %d\n",ico);
826 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
827 dpx=fSeg[0]->Dpx(isec)/2.;
828 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
829 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
830 dpy=fSeg[1]->Dpy(isec)/2.;
831 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
833 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
834 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
835 if ((dx <= dpx) && (dy <= dpy)) {
836 fprintf(stderr,"ok\n");
838 AliMUONRawCluster cnew;
839 for (cath=0; cath<2; cath++) {
840 cnew.fX[cath]=Float_t(xm[ico][1]);
841 cnew.fY[cath]=Float_t(ym[ico][0]);
842 cnew.fZ[cath]=fZPlane;
843 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
844 for (i=0; i<fMul[cath]; i++) {
845 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
846 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
848 FillCluster(&cnew,cath);
850 cnew.fClusterType=cnew.PhysicsContribution();
862 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
864 // Find all local maxima of a cluster
865 printf("\n Find Local maxima !");
869 Int_t cath, cath1; // loops over cathodes
870 Int_t i; // loops over digits
871 Int_t j; // loops over cathodes
875 // counters for number of local maxima
876 fNLocal[0]=fNLocal[1]=0;
877 // flags digits as local maximum
878 Bool_t isLocal[100][2];
879 for (i=0; i<100;i++) {
880 isLocal[i][0]=isLocal[i][1]=kFALSE;
882 // number of next neighbours and arrays to store them
885 // loop over cathodes
886 for (cath=0; cath<2; cath++) {
887 // loop over cluster digits
888 for (i=0; i<fMul[cath]; i++) {
889 // get neighbours for that digit and assume that it is local maximum
890 fSeg[cath]->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
891 isLocal[i][cath]=kTRUE;
892 Int_t isec= fSeg[cath]->Sector(fIx[i][cath], fIy[i][cath]);
893 Float_t a0 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
894 // loop over next neighbours, if at least one neighbour has higher charger assumption
895 // digit is not local maximum
896 for (j=0; j<nn; j++) {
897 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
898 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
899 isec=fSeg[cath]->Sector(x[j], y[j]);
900 Float_t a1 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
901 if (digt->Signal()/a1 > fQ[i][cath]/a0) {
902 isLocal[i][cath]=kFALSE;
905 // handle special case of neighbouring pads with equal signal
906 } else if (digt->Signal() == fQ[i][cath]) {
907 if (fNLocal[cath]>0) {
908 for (Int_t k=0; k<fNLocal[cath]; k++) {
909 if (x[j]==fIx[fIndLocal[k][cath]][cath]
910 && y[j]==fIy[fIndLocal[k][cath]][cath])
912 isLocal[i][cath]=kFALSE;
914 } // loop over local maxima
915 } // are there already local maxima
917 } // loop over next neighbours
918 if (isLocal[i][cath]) {
919 fIndLocal[fNLocal[cath]][cath]=i;
922 } // loop over all digits
923 } // loop over cathodes
925 printf("\n Found %d %d %d %d local Maxima\n",
926 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
927 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
928 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
933 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
934 Int_t iback=fNLocal[0];
936 // Two local maxima on cathode 2 and one maximum on cathode 1
937 // Look for local maxima considering up and down neighbours on the 1st cathode only
939 // Loop over cluster digits
943 for (i=0; i<fMul[cath]; i++) {
944 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
945 dpy=fSeg[cath]->Dpy(isec);
946 dpx=fSeg[cath]->Dpx(isec);
947 if (isLocal[i][cath]) continue;
948 // Pad position should be consistent with position of local maxima on the opposite cathode
949 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
950 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
953 // get neighbours for that digit and assume that it is local maximum
954 isLocal[i][cath]=kTRUE;
955 // compare signal to that on the two neighbours on the left and on the right
956 // iNN counts the number of neighbours with signal, it should be 1 or 2
960 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpy);
966 ix = fSeg[cath]->Ix();
967 iy = fSeg[cath]->Iy();
968 // skip the current pad
969 if (iy == fIy[i][cath]) continue;
971 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
973 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
974 if (digt->Signal() > fQ[i][cath]) isLocal[i][cath]=kFALSE;
976 } // Loop over pad neighbours in y
977 if (isLocal[i][cath] && iNN>0) {
978 fIndLocal[fNLocal[cath]][cath]=i;
981 } // loop over all digits
982 // if one additional maximum has been found we are happy
983 // if more maxima have been found restore the previous situation
985 "\n New search gives %d local maxima for cathode 1 \n",
988 " %d local maxima for cathode 2 \n",
990 if (fNLocal[cath]>2) {
994 } // 1,2 local maxima
996 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
997 Int_t iback=fNLocal[1];
999 // Two local maxima on cathode 1 and one maximum on cathode 2
1000 // Look for local maxima considering left and right neighbours on the 2nd cathode only
1004 // Loop over cluster digits
1005 for (i=0; i<fMul[cath]; i++) {
1006 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
1007 dpx=fSeg[cath]->Dpx(isec);
1008 dpy=fSeg[cath]->Dpy(isec);
1009 if (isLocal[i][cath]) continue;
1010 // Pad position should be consistent with position of local maxima on the opposite cathode
1011 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
1012 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.))
1015 // get neighbours for that digit and assume that it is local maximum
1016 isLocal[i][cath]=kTRUE;
1017 // compare signal to that on the two neighbours on the left and on the right
1019 // iNN counts the number of neighbours with signal, it should be 1 or 2
1022 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpx);
1028 ix = fSeg[cath]->Ix();
1029 iy = fSeg[cath]->Iy();
1031 // skip the current pad
1032 if (ix == fIx[i][cath]) continue;
1034 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
1036 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
1037 if (digt->Signal() > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1039 } // Loop over pad neighbours in x
1040 if (isLocal[i][cath] && iNN>0) {
1041 fIndLocal[fNLocal[cath]][cath]=i;
1044 } // loop over all digits
1045 // if one additional maximum has been found we are happy
1046 // if more maxima have been found restore the previous situation
1047 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
1048 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
1049 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
1050 if (fNLocal[cath]>2) {
1051 fNLocal[cath]=iback;
1053 } // 2,1 local maxima
1057 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
1060 // Completes cluster information starting from list of digits
1067 c->fPeakSignal[cath]=c->fPeakSignal[0];
1069 c->fPeakSignal[cath]=0;
1079 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1080 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1082 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1083 ix=dig->PadX()+c->fOffsetMap[i][cath];
1085 Int_t q=dig->Signal();
1086 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1087 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1088 if (dig->Physics() >= dig->Signal()) {
1089 c->fPhysicsMap[i]=2;
1090 } else if (dig->Physics() == 0) {
1091 c->fPhysicsMap[i]=0;
1092 } else c->fPhysicsMap[i]=1;
1095 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1096 // peak signal and track list
1097 if (q>c->fPeakSignal[cath]) {
1098 c->fPeakSignal[cath]=q;
1099 c->fTracks[0]=dig->Hit();
1100 c->fTracks[1]=dig->Track(0);
1101 c->fTracks[2]=dig->Track(1);
1102 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1106 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1111 } // loop over digits
1112 // fprintf(stderr," fin du cluster c\n");
1116 c->fX[cath]/=c->fQ[cath];
1117 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1118 c->fY[cath]/=c->fQ[cath];
1120 // apply correction to the coordinate along the anode wire
1124 fSeg[cath]->GetPadI(x, y, fZPlane, ix, iy);
1125 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1126 Int_t isec=fSeg[cath]->Sector(ix,iy);
1127 TF1* cogCorr = fSeg[cath]->CorrFunc(isec-1);
1130 Float_t yOnPad=(c->fY[cath]-y)/fSeg[cath]->Dpy(isec);
1131 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1136 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1139 // Completes cluster information starting from list of digits
1149 Float_t xpad, ypad, zpad;
1152 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1154 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1156 GetPadC(dig->PadX(),dig->PadY(),xpad,ypad, zpad);
1157 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1158 dx = xpad - c->fX[0];
1159 dy = ypad - c->fY[0];
1160 dr = TMath::Sqrt(dx*dx+dy*dy);
1164 fprintf(stderr," dr %f\n",dr);
1165 Int_t q=dig->Signal();
1166 if (dig->Physics() >= dig->Signal()) {
1167 c->fPhysicsMap[i]=2;
1168 } else if (dig->Physics() == 0) {
1169 c->fPhysicsMap[i]=0;
1170 } else c->fPhysicsMap[i]=1;
1171 c->fPeakSignal[cath]=q;
1172 c->fTracks[0]=dig->Hit();
1173 c->fTracks[1]=dig->Track(0);
1174 c->fTracks[2]=dig->Track(1);
1175 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->Hit(),
1179 } // loop over digits
1181 // apply correction to the coordinate along the anode wire
1182 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1185 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1189 // Find a super cluster on both cathodes
1192 // Add i,j as element of the cluster
1195 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1196 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1197 Int_t q=dig->Signal();
1198 Int_t theX=dig->PadX();
1199 Int_t theY=dig->PadY();
1201 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1202 c.fPeakSignal[cath]=q;
1203 c.fTracks[0]=dig->Hit();
1204 c.fTracks[1]=dig->Track(0);
1205 c.fTracks[2]=dig->Track(1);
1209 // Make sure that list of digits is ordered
1211 Int_t mu=c.fMultiplicity[cath];
1212 c.fIndexMap[mu][cath]=idx;
1214 if (dig->Physics() >= dig->Signal()) {
1215 c.fPhysicsMap[mu]=2;
1216 } else if (dig->Physics() == 0) {
1217 c.fPhysicsMap[mu]=0;
1218 } else c.fPhysicsMap[mu]=1;
1222 for (Int_t ind = mu-1; ind >= 0; ind--) {
1223 Int_t ist=(c.fIndexMap)[ind][cath];
1224 Int_t ql=fInput->Digit(cath, ist)->Signal();
1225 Int_t ix=fInput->Digit(cath, ist)->PadX();
1226 Int_t iy=fInput->Digit(cath, ist)->PadY();
1228 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1229 c.fIndexMap[ind][cath]=idx;
1230 c.fIndexMap[ind+1][cath]=ist;
1238 c.fMultiplicity[cath]++;
1239 if (c.fMultiplicity[cath] >= 50 ) {
1240 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1241 c.fMultiplicity[cath]=49;
1244 // Prepare center of gravity calculation
1246 fSeg[cath]->GetPadC(i, j, x, y, z);
1252 // Flag hit as "taken"
1253 fHitMap[cath]->FlagHit(i,j);
1255 // Now look recursively for all neighbours and pad hit on opposite cathode
1257 // Loop over neighbours
1261 Int_t xList[10], yList[10];
1262 fSeg[cath]->Neighbours(i,j,&nn,xList,yList);
1263 for (Int_t in=0; in<nn; in++) {
1267 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) {
1268 // printf("\n Neighbours %d %d %d", cath, ix, iy);
1269 FindCluster(ix, iy, cath, c);
1274 Int_t iXopp[50], iYopp[50];
1276 // Neighbours on opposite cathode
1277 // Take into account that several pads can overlap with the present pad
1278 Int_t isec=fSeg[cath]->Sector(i,j);
1284 dx = (fSeg[cath]->Dpx(isec))/2.;
1289 dy = (fSeg[cath]->Dpy(isec))/2;
1291 // loop over pad neighbours on opposite cathode
1292 for (fSeg[iop]->FirstPad(x, y, fZPlane, dx, dy);
1293 fSeg[iop]->MorePads();
1294 fSeg[iop]->NextPad())
1297 ix = fSeg[iop]->Ix(); iy = fSeg[iop]->Iy();
1298 // printf("\n ix, iy: %f %f %f %d %d %d", x,y,z,ix, iy, fSector);
1299 if (fHitMap[iop]->TestHit(ix,iy)==kUnused){
1302 // printf("\n Opposite %d %d %d", iop, ix, iy);
1305 } // Loop over pad neighbours
1306 // This had to go outside the loop since recursive calls inside the iterator are not possible
1309 for (jopp=0; jopp<nOpp; jopp++) {
1310 if (fHitMap[iop]->TestHit(iXopp[jopp],iYopp[jopp]) == kUnused)
1311 FindCluster(iXopp[jopp], iYopp[jopp], iop, c);
1315 //_____________________________________________________________________________
1317 void AliMUONClusterFinderVS::FindRawClusters()
1320 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1321 // fills the tree with raw clusters
1324 // Return if no input datad available
1325 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1327 fSeg[0] = fInput->Segmentation(0);
1328 fSeg[1] = fInput->Segmentation(1);
1330 fHitMap[0] = new AliMUONHitMapA1(fSeg[0], fInput->Digits(0));
1331 fHitMap[1] = new AliMUONHitMapA1(fSeg[1], fInput->Digits(1));
1339 fHitMap[0]->FillHits();
1340 fHitMap[1]->FillHits();
1342 // Outer Loop over Cathodes
1343 for (cath=0; cath<2; cath++) {
1344 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1345 dig = fInput->Digit(cath, ndig);
1346 Int_t i=dig->PadX();
1347 Int_t j=dig->PadY();
1348 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1352 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1353 AliMUONRawCluster c;
1354 c.fMultiplicity[0]=0;
1355 c.fMultiplicity[1]=0;
1356 c.fPeakSignal[cath]=dig->Signal();
1357 c.fTracks[0]=dig->Hit();
1358 c.fTracks[1]=dig->Track(0);
1359 c.fTracks[2]=dig->Track(1);
1360 // tag the beginning of cluster list in a raw cluster
1363 fSeg[cath]->GetPadC(i,j,xcu, ycu, fZPlane);
1364 fSector= fSeg[cath]->Sector(i,j)/100;
1365 // printf("\n New Seed %d %d ", i,j);
1367 FindCluster(i,j,cath,c);
1368 // ^^^^^^^^^^^^^^^^^^^^^^^^
1369 // center of gravity
1371 c.fX[0]=fSeg[0]->GetAnod(c.fX[0]);
1374 c.fX[1]=fSeg[0]->GetAnod(c.fX[1]);
1380 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",
1381 c.fMultiplicity[0],c.fX[0],c.fY[0]);
1382 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",
1383 c.fMultiplicity[1],c.fX[1],c.fY[1]);
1385 // Analyse cluster and decluster if necessary
1388 c.fNcluster[1]=fNRawClusters;
1389 c.fClusterType=c.PhysicsContribution();
1396 // reset Cluster object
1397 { // begin local scope
1398 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1399 } // end local scope
1401 { // begin local scope
1402 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1403 } // end local scope
1405 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1409 } // end loop cathodes
1414 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1416 // Performs a single Mathieson fit on one cathode
1418 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1420 clusterInput.Fitter()->SetFCN(fcnS1);
1421 clusterInput.Fitter()->mninit(2,10,7);
1422 Double_t arglist[20];
1425 // Set starting values
1426 static Double_t vstart[2];
1431 // lower and upper limits
1432 static Double_t lower[2], upper[2];
1434 fSeg[cath]->GetPadI(c->fX[cath], c->fY[cath], fZPlane, ix, iy);
1435 Int_t isec=fSeg[cath]->Sector(ix, iy);
1436 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec)/2;
1437 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec)/2;
1439 upper[0]=lower[0]+fSeg[cath]->Dpx(isec);
1440 upper[1]=lower[1]+fSeg[cath]->Dpy(isec);
1443 static Double_t step[2]={0.0005, 0.0005};
1445 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1446 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1447 // ready for minimisation
1448 clusterInput.Fitter()->SetPrintLevel(1);
1449 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1453 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1454 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1455 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1456 Double_t fmin, fedm, errdef;
1457 Int_t npari, nparx, istat;
1459 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1463 // Get fitted parameters
1464 Double_t xrec, yrec;
1466 Double_t epxz, b1, b2;
1468 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1469 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1475 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1477 // Perform combined Mathieson fit on both cathode planes
1479 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1480 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1481 clusterInput.Fitter()->mninit(2,10,7);
1482 Double_t arglist[20];
1485 static Double_t vstart[2];
1486 vstart[0]=fXInit[0];
1487 vstart[1]=fYInit[0];
1490 // lower and upper limits
1491 static Float_t lower[2], upper[2];
1493 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1494 isec=fSeg[0]->Sector(ix, iy);
1495 Float_t dpy=fSeg[0]->Dpy(isec);
1496 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1497 isec=fSeg[1]->Sector(ix, iy);
1498 Float_t dpx=fSeg[1]->Dpx(isec);
1501 Float_t xdum, ydum, zdum;
1503 // Find save upper and lower limits
1507 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1508 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1510 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1511 fSeg[1]->GetPadC(ix,iy, upper[0], ydum, zdum);
1512 if (icount ==0) lower[0]=upper[0];
1516 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1519 printf("\n single y %f %f", fXInit[0], fYInit[0]);
1521 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1522 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1524 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1525 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1526 if (icount ==0) lower[1]=upper[1];
1528 printf("\n upper lower %d %f %f", icount, upper[1], lower[1]);
1531 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1534 static Double_t step[2]={0.00001, 0.0001};
1536 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1537 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1538 // ready for minimisation
1539 clusterInput.Fitter()->SetPrintLevel(1);
1540 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1544 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1545 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1546 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1547 Double_t fmin, fedm, errdef;
1548 Int_t npari, nparx, istat;
1550 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1554 // Get fitted parameters
1555 Double_t xrec, yrec;
1557 Double_t epxz, b1, b2;
1559 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1560 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1566 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1568 // Performs a double Mathieson fit on one cathode
1572 // Initialise global variables for fit
1573 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1574 clusterInput.Fitter()->SetFCN(fcnS2);
1575 clusterInput.Fitter()->mninit(5,10,7);
1576 Double_t arglist[20];
1579 // Set starting values
1580 static Double_t vstart[5];
1581 vstart[0]=fX[fIndLocal[0][cath]][cath];
1582 vstart[1]=fY[fIndLocal[0][cath]][cath];
1583 vstart[2]=fX[fIndLocal[1][cath]][cath];
1584 vstart[3]=fY[fIndLocal[1][cath]][cath];
1585 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1586 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1587 // lower and upper limits
1588 static Float_t lower[5], upper[5];
1589 Int_t isec=fSeg[cath]->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1590 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec);
1591 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec);
1593 upper[0]=lower[0]+2.*fSeg[cath]->Dpx(isec);
1594 upper[1]=lower[1]+2.*fSeg[cath]->Dpy(isec);
1596 isec=fSeg[cath]->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1597 lower[2]=vstart[2]-fSeg[cath]->Dpx(isec)/2;
1598 lower[3]=vstart[3]-fSeg[cath]->Dpy(isec)/2;
1600 upper[2]=lower[2]+fSeg[cath]->Dpx(isec);
1601 upper[3]=lower[3]+fSeg[cath]->Dpy(isec);
1606 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1608 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1609 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1610 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1611 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1612 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1613 // ready for minimisation
1614 clusterInput.Fitter()->SetPrintLevel(-1);
1615 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1619 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1620 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1621 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1622 // Get fitted parameters
1623 Double_t xrec[2], yrec[2], qfrac;
1625 Double_t epxz, b1, b2;
1627 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1628 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1629 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1630 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1631 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1633 Double_t fmin, fedm, errdef;
1634 Int_t npari, nparx, istat;
1636 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1641 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1644 // Perform combined double Mathieson fit on both cathode planes
1646 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1647 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1648 clusterInput.Fitter()->mninit(6,10,7);
1649 Double_t arglist[20];
1652 // Set starting values
1653 static Double_t vstart[6];
1654 vstart[0]=fXInit[0];
1655 vstart[1]=fYInit[0];
1656 vstart[2]=fXInit[1];
1657 vstart[3]=fYInit[1];
1658 vstart[4]=fQrInit[0];
1659 vstart[5]=fQrInit[1];
1660 // lower and upper limits
1661 static Float_t lower[6], upper[6];
1665 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1666 isec=fSeg[1]->Sector(ix, iy);
1667 dpx=fSeg[1]->Dpx(isec);
1669 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1670 isec=fSeg[0]->Sector(ix, iy);
1671 dpy=fSeg[0]->Dpy(isec);
1675 Float_t xdum, ydum, zdum;
1676 // printf("\n Cluster Finder: %f %f %f %f ", fXInit[0], fXInit[1],fYInit[0], fYInit[1] );
1678 // Find save upper and lower limits
1681 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1682 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1684 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1685 fSeg[1]->GetPadC(ix,iy,upper[0],ydum,zdum);
1686 if (icount ==0) lower[0]=upper[0];
1689 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1692 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1693 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1695 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1696 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1697 if (icount ==0) lower[1]=upper[1];
1700 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1702 fSeg[1]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1703 isec=fSeg[1]->Sector(ix, iy);
1704 dpx=fSeg[1]->Dpx(isec);
1705 fSeg[0]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1706 isec=fSeg[0]->Sector(ix, iy);
1707 dpy=fSeg[0]->Dpy(isec);
1710 // Find save upper and lower limits
1714 for (fSeg[1]->FirstPad(fXInit[1], fYInit[1], fZPlane, dpx, 0);
1715 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1717 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1718 fSeg[1]->GetPadC(ix,iy,upper[2],ydum,zdum);
1719 if (icount ==0) lower[2]=upper[2];
1722 if (lower[2]>upper[2]) {xdum=lower[2]; lower[2]=upper[2]; upper[2]=xdum;}
1726 for (fSeg[0]->FirstPad(fXInit[1], fYInit[1], fZPlane, 0, dpy);
1727 fSeg[0]-> MorePads(); fSeg[0]->NextPad())
1729 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1730 fSeg[0]->GetPadC(ix,iy,xdum,upper[3],zdum);
1731 if (icount ==0) lower[3]=upper[3];
1734 if (lower[3]>upper[3]) {xdum=lower[3]; lower[3]=upper[3]; upper[3]=xdum;}
1742 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1743 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1744 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1745 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1746 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1747 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1748 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1749 // ready for minimisation
1750 clusterInput.Fitter()->SetPrintLevel(-1);
1751 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1755 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1756 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1757 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1758 // Get fitted parameters
1760 Double_t epxz, b1, b2;
1762 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1763 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1764 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1765 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1766 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1767 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1769 Double_t fmin, fedm, errdef;
1770 Int_t npari, nparx, istat;
1772 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1780 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1783 // One cluster for each maximum
1786 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1787 for (j=0; j<2; j++) {
1788 AliMUONRawCluster cnew;
1789 for (cath=0; cath<2; cath++) {
1790 cnew.fChi2[cath]=fChi2[0];
1793 cnew.fNcluster[0]=-1;
1794 cnew.fNcluster[1]=fNRawClusters;
1796 cnew.fNcluster[0]=fNPeaks;
1797 cnew.fNcluster[1]=0;
1799 cnew.fMultiplicity[cath]=0;
1800 cnew.fX[cath]=Float_t(fXFit[j]);
1801 cnew.fY[cath]=Float_t(fYFit[j]);
1802 cnew.fZ[cath]=fZPlane;
1804 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
1806 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
1808 fSeg[cath]->SetHit(fXFit[j],fYFit[j],fZPlane);
1809 for (i=0; i<fMul[cath]; i++) {
1810 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1811 c->fIndexMap[i][cath];
1812 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
1813 Float_t q1=fInput->Response()->IntXY(fSeg[cath]);
1814 cnew.fContMap[i][cath]
1815 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1816 cnew.fMultiplicity[cath]++;
1818 FillCluster(&cnew,0,cath);
1821 cnew.fClusterType=cnew.PhysicsContribution();
1822 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1829 // Minimisation functions
1831 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1833 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1840 for (i=0; i<clusterInput.Nmul(0); i++) {
1841 Float_t q0=clusterInput.Charge(i,0);
1842 Float_t q1=clusterInput.DiscrChargeS1(i,par);
1851 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1853 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1860 for (cath=0; cath<2; cath++) {
1861 for (i=0; i<clusterInput.Nmul(cath); i++) {
1862 Float_t q0=clusterInput.Charge(i,cath);
1863 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
1874 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1876 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1883 for (i=0; i<clusterInput.Nmul(0); i++) {
1885 Float_t q0=clusterInput.Charge(i,0);
1886 Float_t q1=clusterInput.DiscrChargeS2(i,par);
1896 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1898 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1904 for (cath=0; cath<2; cath++) {
1905 for (i=0; i<clusterInput.Nmul(cath); i++) {
1906 Float_t q0=clusterInput.Charge(i,cath);
1907 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
1917 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1920 // Add a raw cluster copy to the list
1922 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1923 pMUON->AddRawCluster(fInput->Chamber(),c);
1925 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1928 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
1929 // Test if track was user selected
1930 if (fTrack[0]==-1 || fTrack[1]==-1) {
1932 } else if (t==fTrack[0] || t==fTrack[1]) {
1939 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1940 ::operator = (const AliMUONClusterFinderVS& rhs)
1942 // Dummy assignment operator