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.9 2000/10/02 16:58:29 egangler
18 Cleaning of the code :
21 -> some useless includes removed or replaced by "class" statement
23 Revision 1.8 2000/07/03 11:54:57 morsch
24 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
25 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
27 Revision 1.7 2000/06/28 15:16:35 morsch
28 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
29 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
30 framework. The changes should have no side effects (mostly dummy arguments).
31 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
32 of chambers with overlapping modules (MakePadHits, Disintegration).
34 Revision 1.6 2000/06/28 12:19:18 morsch
35 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
36 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
37 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
38 It requires two cathode planes. Small modifications in the code will make it usable for
39 one cathode plane and, hence, more general (for test beam data).
40 AliMUONClusterFinder is now obsolete.
42 Revision 1.5 2000/06/28 08:06:10 morsch
43 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
44 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
45 It also naturally takes care of the TMinuit instance.
47 Revision 1.4 2000/06/27 16:18:47 gosset
48 Finally correct implementation of xm, ym, ixm, iym sizes
49 when at least three local maxima on cathode 1 or on cathode 2
51 Revision 1.3 2000/06/22 14:02:45 morsch
52 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
53 Some HP scope problems corrected (PH)
55 Revision 1.2 2000/06/15 07:58:48 morsch
56 Code from MUON-dev joined
58 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
59 Most coding rule violations corrected.
61 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
62 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
63 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
64 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
65 - For clusters with more than 2 maxima on one of the cathode planes all valid
66 combinations of maxima on the two cathodes are preserved. The position of the maxima is
67 taken as the hit position.
68 - New FillCluster method with 2 arguments to find tracks associated to the clusters
69 defined above added. (Method destinction by argument list not very elegant in this case,
70 should be revides (A.M.)
71 - Bug in if-statement to handle maximum 1 maximum per plane corrected
72 - Two cluster per cathode but only 1 combination valid is handled.
73 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
77 #include "AliMUONClusterFinderVS.h"
78 #include "AliMUONDigit.h"
79 #include "AliMUONRawCluster.h"
80 #include "AliSegmentation.h"
81 #include "AliMUONResponse.h"
82 #include "AliMUONClusterInput.h"
83 #include "AliMUONHitMapA1.h"
92 #include <TPostScript.h>
99 //_____________________________________________________________________
100 // This function is minimized in the double-Mathieson fit
101 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
102 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
103 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
104 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
106 ClassImp(AliMUONClusterFinderVS)
108 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
110 // Default constructor
111 fInput=AliMUONClusterInput::Instance();
114 fTrack[0]=fTrack[1]=-1;
117 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
118 const AliMUONClusterFinderVS & clusterFinder)
120 // Dummy copy Constructor
124 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
126 // Decluster by local maxima
127 SplitByLocalMaxima(cluster);
130 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
132 // Split complex cluster by local maxima
136 fInput->SetCluster(c);
138 fMul[0]=c->fMultiplicity[0];
139 fMul[1]=c->fMultiplicity[1];
142 // dump digit information into arrays
147 for (cath=0; cath<2; cath++) {
149 for (i=0; i<fMul[cath]; i++)
152 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
154 fIx[i][cath]= fDig[i][cath]->fPadX;
155 fIy[i][cath]= fDig[i][cath]->fPadY;
157 fQ[i][cath] = fDig[i][cath]->fSignal;
158 // pad centre coordinates
159 fInput->Segmentation(cath)->
160 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], zdum);
161 } // loop over cluster digits
162 } // loop over cathodes
168 // Initialise and perform mathieson fits
169 Float_t chi2, oldchi2;
170 // ++++++++++++++++++*************+++++++++++++++++++++
171 // (1) No more than one local maximum per cathode plane
172 // +++++++++++++++++++++++++++++++*************++++++++
173 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
174 (fNLocal[0]==0 && fNLocal[1]==1)) {
176 // Perform combined single Mathieson fit
177 // Initial values for coordinates (x,y)
179 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
180 if (fNLocal[0]==1 && fNLocal[1]==1) {
183 // One local maximum on cathode 1 (X,Y->cathode 1)
184 } else if (fNLocal[0]==1) {
187 // One local maximum on cathode 2 (X,Y->cathode 2)
192 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
193 chi2=CombiSingleMathiesonFit(c);
194 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
195 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
196 // prob1->Fill(prob);
197 // chi2_1->Fill(chi2);
199 fprintf(stderr," chi2 %f ",chi2);
208 c->fX[0]=fInput->Segmentation(0)->GetAnod(c->fX[0]);
209 c->fX[1]=fInput->Segmentation(1)->GetAnod(c->fX[1]);
211 // If reasonable chi^2 add result to the list of rawclusters
215 // If not try combined double Mathieson Fit
217 fprintf(stderr," MAUVAIS CHI2 !!!\n");
218 if (fNLocal[0]==1 && fNLocal[1]==1) {
219 fXInit[0]=fX[fIndLocal[0][1]][1];
220 fYInit[0]=fY[fIndLocal[0][0]][0];
221 fXInit[1]=fX[fIndLocal[0][1]][1];
222 fYInit[1]=fY[fIndLocal[0][0]][0];
223 } else if (fNLocal[0]==1) {
224 fXInit[0]=fX[fIndLocal[0][0]][0];
225 fYInit[0]=fY[fIndLocal[0][0]][0];
226 fXInit[1]=fX[fIndLocal[0][0]][0];
227 fYInit[1]=fY[fIndLocal[0][0]][0];
229 fXInit[0]=fX[fIndLocal[0][1]][1];
230 fYInit[0]=fY[fIndLocal[0][1]][1];
231 fXInit[1]=fX[fIndLocal[0][1]][1];
232 fYInit[1]=fY[fIndLocal[0][1]][1];
235 // Initial value for charge ratios
238 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
239 chi2=CombiDoubleMathiesonFit(c);
240 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
241 // Float_t prob = TMath::Prob(chi2,ndf);
242 // prob2->Fill(prob);
243 // chi2_2->Fill(chi2);
245 // Was this any better ??
246 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
247 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
248 fprintf(stderr," Split\n");
249 // Split cluster into two according to fit result
252 fprintf(stderr," Don't Split\n");
258 // +++++++++++++++++++++++++++++++++++++++
259 // (2) Two local maxima per cathode plane
260 // +++++++++++++++++++++++++++++++++++++++
261 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
263 // Let's look for ghosts first
265 Float_t xm[4][2], ym[4][2];
266 Float_t dpx, dpy, dx, dy;
267 Int_t ixm[4][2], iym[4][2];
268 Int_t isec, im1, im2, ico;
270 // Form the 2x2 combinations
271 // 0-0, 0-1, 1-0, 1-1
273 for (im1=0; im1<2; im1++) {
274 for (im2=0; im2<2; im2++) {
275 xm[ico][0]=fX[fIndLocal[im1][0]][0];
276 ym[ico][0]=fY[fIndLocal[im1][0]][0];
277 xm[ico][1]=fX[fIndLocal[im2][1]][1];
278 ym[ico][1]=fY[fIndLocal[im2][1]][1];
280 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
281 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
282 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
283 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
287 // ico = 0 : first local maximum on cathodes 1 and 2
288 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
289 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
290 // ico = 3 : second local maximum on cathodes 1 and 2
292 // Analyse the combinations and keep those that are possible !
293 // For each combination check consistency in x and y
298 for (ico=0; ico<4; ico++) {
299 accepted[ico]=kFALSE;
300 // cathode one: x-coordinate
301 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
302 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
303 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
304 // cathode two: y-coordinate
305 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
306 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
307 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
308 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
309 if ((dx <= dpx) && (dy <= dpy)) {
315 accepted[ico]=kFALSE;
320 fprintf(stderr,"\n iacc=2: No problem ! \n");
321 } else if (iacc==4) {
322 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
323 } else if (iacc==0) {
324 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
327 // Initial value for charge ratios
328 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
329 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
330 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
331 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
333 // ******* iacc = 0 *******
334 // No combinations found between the 2 cathodes
335 // We keep the center of gravity of the cluster
340 // ******* iacc = 1 *******
341 // Only one combination found between the 2 cathodes
344 // Initial values for the 2 maxima (x,y)
346 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
347 // 1 maximum is initialised with the other maximum of the first cathode
349 fprintf(stderr,"ico=0\n");
354 } else if (accepted[1]){
355 fprintf(stderr,"ico=1\n");
360 } else if (accepted[2]){
361 fprintf(stderr,"ico=2\n");
366 } else if (accepted[3]){
367 fprintf(stderr,"ico=3\n");
373 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
374 chi2=CombiDoubleMathiesonFit(c);
375 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
376 // Float_t prob = TMath::Prob(chi2,ndf);
377 // prob2->Fill(prob);
378 // chi2_2->Fill(chi2);
379 fprintf(stderr," chi2 %f\n",chi2);
381 // If reasonable chi^2 add result to the list of rawclusters
386 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
387 // 1 maximum is initialised with the other maximum of the second cathode
389 fprintf(stderr,"ico=0\n");
394 } else if (accepted[1]){
395 fprintf(stderr,"ico=1\n");
400 } else if (accepted[2]){
401 fprintf(stderr,"ico=2\n");
406 } else if (accepted[3]){
407 fprintf(stderr,"ico=3\n");
413 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
414 chi2=CombiDoubleMathiesonFit(c);
415 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
416 // Float_t prob = TMath::Prob(chi2,ndf);
417 // prob2->Fill(prob);
418 // chi2_2->Fill(chi2);
419 fprintf(stderr," chi2 %f\n",chi2);
421 // If reasonable chi^2 add result to the list of rawclusters
425 //We keep only the combination found (X->cathode 2, Y->cathode 1)
426 for (Int_t ico=0; ico<2; ico++) {
428 AliMUONRawCluster cnew;
430 for (cath=0; cath<2; cath++) {
431 cnew.fX[cath]=Float_t(xm[ico][1]);
432 cnew.fY[cath]=Float_t(ym[ico][0]);
433 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
434 for (i=0; i<fMul[cath]; i++) {
435 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
436 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
438 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
439 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
440 FillCluster(&cnew,cath);
442 cnew.fClusterType=cnew.PhysicsContribution();
451 // ******* iacc = 2 *******
452 // Two combinations found between the 2 cathodes
455 // Was the same maximum taken twice
456 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
457 fprintf(stderr,"\n Maximum taken twice !!!\n");
459 // Have a try !! with that
460 if (accepted[0]&&accepted[3]) {
471 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
472 chi2=CombiDoubleMathiesonFit(c);
473 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
474 // Float_t prob = TMath::Prob(chi2,ndf);
475 // prob2->Fill(prob);
476 // chi2_2->Fill(chi2);
480 // No ghosts ! No Problems ! - Perform one fit only !
481 if (accepted[0]&&accepted[3]) {
492 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
493 chi2=CombiDoubleMathiesonFit(c);
494 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
495 // Float_t prob = TMath::Prob(chi2,ndf);
496 // prob2->Fill(prob);
497 // chi2_2->Fill(chi2);
498 fprintf(stderr," chi2 %f\n",chi2);
502 // ******* iacc = 4 *******
503 // Four combinations found between the 2 cathodes
505 } else if (iacc==4) {
506 // Perform fits for the two possibilities !!
511 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
512 chi2=CombiDoubleMathiesonFit(c);
513 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
514 // Float_t prob = TMath::Prob(chi2,ndf);
515 // prob2->Fill(prob);
516 // chi2_2->Fill(chi2);
517 fprintf(stderr," chi2 %f\n",chi2);
523 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
524 chi2=CombiDoubleMathiesonFit(c);
525 // ndf = fgNbins[0]+fgNbins[1]-6;
526 // prob = TMath::Prob(chi2,ndf);
527 // prob2->Fill(prob);
528 // chi2_2->Fill(chi2);
529 fprintf(stderr," chi2 %f\n",chi2);
533 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
534 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
535 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
536 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
538 Float_t xm[4][2], ym[4][2];
539 Float_t dpx, dpy, dx, dy;
540 Int_t ixm[4][2], iym[4][2];
541 Int_t isec, im1, ico;
543 // Form the 2x2 combinations
544 // 0-0, 0-1, 1-0, 1-1
546 for (im1=0; im1<2; im1++) {
547 xm[ico][0]=fX[fIndLocal[im1][0]][0];
548 ym[ico][0]=fY[fIndLocal[im1][0]][0];
549 xm[ico][1]=fX[fIndLocal[0][1]][1];
550 ym[ico][1]=fY[fIndLocal[0][1]][1];
552 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
553 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
554 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
555 iym[ico][1]=fIy[fIndLocal[0][1]][1];
558 // ico = 0 : first local maximum on cathodes 1 and 2
559 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
561 // Analyse the combinations and keep those that are possible !
562 // For each combination check consistency in x and y
567 for (ico=0; ico<2; ico++) {
568 accepted[ico]=kFALSE;
569 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
570 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
571 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
572 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
573 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
574 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
575 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
576 if ((dx <= dpx) && (dy <= dpy)) {
582 accepted[ico]=kFALSE;
594 chi21=CombiDoubleMathiesonFit(c);
595 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
596 // Float_t prob = TMath::Prob(chi2,ndf);
597 // prob2->Fill(prob);
598 // chi2_2->Fill(chi21);
599 fprintf(stderr," chi2 %f\n",chi21);
600 if (chi21<10) Split(c);
601 } else if (accepted[1]) {
606 chi22=CombiDoubleMathiesonFit(c);
607 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
608 // Float_t prob = TMath::Prob(chi2,ndf);
609 // prob2->Fill(prob);
610 // chi2_2->Fill(chi22);
611 fprintf(stderr," chi2 %f\n",chi22);
612 if (chi22<10) Split(c);
615 if (chi21 > 10 && chi22 > 10) {
616 // We keep only the combination found (X->cathode 2, Y->cathode 1)
617 for (Int_t ico=0; ico<2; ico++) {
619 AliMUONRawCluster cnew;
621 for (cath=0; cath<2; cath++) {
622 cnew.fX[cath]=Float_t(xm[ico][1]);
623 cnew.fY[cath]=Float_t(ym[ico][0]);
624 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
625 for (i=0; i<fMul[cath]; i++) {
626 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
627 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
629 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
630 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
631 FillCluster(&cnew,cath);
633 cnew.fClusterType=cnew.PhysicsContribution();
640 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
641 // (3') One local maximum on cathode 1 and two maxima on cathode 2
642 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
643 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
645 Float_t xm[4][2], ym[4][2];
646 Float_t dpx, dpy, dx, dy;
647 Int_t ixm[4][2], iym[4][2];
648 Int_t isec, im1, ico;
650 // Form the 2x2 combinations
651 // 0-0, 0-1, 1-0, 1-1
653 for (im1=0; im1<2; im1++) {
654 xm[ico][0]=fX[fIndLocal[0][0]][0];
655 ym[ico][0]=fY[fIndLocal[0][0]][0];
656 xm[ico][1]=fX[fIndLocal[im1][1]][1];
657 ym[ico][1]=fY[fIndLocal[im1][1]][1];
659 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
660 iym[ico][0]=fIy[fIndLocal[0][0]][0];
661 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
662 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
665 // ico = 0 : first local maximum on cathodes 1 and 2
666 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
668 // Analyse the combinations and keep those that are possible !
669 // For each combination check consistency in x and y
674 for (ico=0; ico<2; ico++) {
675 accepted[ico]=kFALSE;
676 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
677 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
678 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
679 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
680 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
681 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
682 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
683 if ((dx <= dpx) && (dy <= dpy)) {
686 fprintf(stderr,"ico %d\n",ico);
690 accepted[ico]=kFALSE;
702 chi21=CombiDoubleMathiesonFit(c);
703 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
704 // Float_t prob = TMath::Prob(chi2,ndf);
705 // prob2->Fill(prob);
706 // chi2_2->Fill(chi21);
707 fprintf(stderr," chi2 %f\n",chi21);
708 if (chi21<10) Split(c);
709 } else if (accepted[1]) {
714 chi22=CombiDoubleMathiesonFit(c);
715 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
716 // Float_t prob = TMath::Prob(chi2,ndf);
717 // prob2->Fill(prob);
718 // chi2_2->Fill(chi22);
719 fprintf(stderr," chi2 %f\n",chi22);
720 if (chi22<10) Split(c);
723 if (chi21 > 10 && chi22 > 10) {
724 //We keep only the combination found (X->cathode 2, Y->cathode 1)
725 for (Int_t ico=0; ico<2; ico++) {
727 AliMUONRawCluster cnew;
729 for (cath=0; cath<2; cath++) {
730 cnew.fX[cath]=Float_t(xm[ico][1]);
731 cnew.fY[cath]=Float_t(ym[ico][0]);
732 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
733 for (i=0; i<fMul[cath]; i++) {
734 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
735 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
737 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
738 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
739 FillCluster(&cnew,cath);
741 cnew.fClusterType=cnew.PhysicsContribution();
748 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
749 // (4) At least three local maxima on cathode 1 or on cathode 2
750 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
751 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
753 Int_t param = fNLocal[0]*fNLocal[1];
756 Float_t ** xm = new Float_t * [param];
757 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
758 Float_t ** ym = new Float_t * [param];
759 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
760 Int_t ** ixm = new Int_t * [param];
761 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
762 Int_t ** iym = new Int_t * [param];
763 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
766 Float_t dpx, dpy, dx, dy;
769 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
770 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
771 xm[ico][0]=fX[fIndLocal[im1][0]][0];
772 ym[ico][0]=fY[fIndLocal[im1][0]][0];
773 xm[ico][1]=fX[fIndLocal[im2][1]][1];
774 ym[ico][1]=fY[fIndLocal[im2][1]][1];
776 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
777 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
778 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
779 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
786 fprintf(stderr,"nIco %d\n",nIco);
787 for (ico=0; ico<nIco; ico++) {
788 fprintf(stderr,"ico = %d\n",ico);
789 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
790 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
791 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
792 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
793 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
794 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
796 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
797 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
798 if ((dx <= dpx) && (dy <= dpy)) {
799 fprintf(stderr,"ok\n");
801 AliMUONRawCluster cnew;
802 for (cath=0; cath<2; cath++) {
803 cnew.fX[cath]=Float_t(xm[ico][1]);
804 cnew.fY[cath]=Float_t(ym[ico][0]);
805 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
806 for (i=0; i<fMul[cath]; i++) {
807 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
808 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
810 FillCluster(&cnew,cath);
812 cnew.fClusterType=cnew.PhysicsContribution();
824 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
826 // Find all local maxima of a cluster
830 Int_t cath, cath1; // loops over cathodes
831 Int_t i; // loops over digits
832 Int_t j; // loops over cathodes
836 // counters for number of local maxima
837 fNLocal[0]=fNLocal[1]=0;
838 // flags digits as local maximum
839 Bool_t isLocal[100][2];
840 for (i=0; i<100;i++) {
841 isLocal[i][0]=isLocal[i][1]=kFALSE;
843 // number of next neighbours and arrays to store them
846 // loop over cathodes
847 for (cath=0; cath<2; cath++) {
848 // loop over cluster digits
849 for (i=0; i<fMul[cath]; i++) {
850 // get neighbours for that digit and assume that it is local maximum
851 fInput->Segmentation(cath)->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
852 isLocal[i][cath]=kTRUE;
853 Int_t isec= fInput->Segmentation(cath)->Sector(fIx[i][cath], fIy[i][cath]);
854 Float_t a0 = fInput->Segmentation(cath)->Dpx(isec)*fInput->Segmentation(cath)->Dpy(isec);
855 // loop over next neighbours, if at least one neighbour has higher charger assumption
856 // digit is not local maximum
857 for (j=0; j<nn; j++) {
858 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
859 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
860 isec=fInput->Segmentation(cath)->Sector(x[j], y[j]);
861 Float_t a1 = fInput->Segmentation(cath)->Dpx(isec)*fInput->Segmentation(cath)->Dpy(isec);
862 if (digt->fSignal/a1 > fQ[i][cath]/a0) {
863 isLocal[i][cath]=kFALSE;
866 // handle special case of neighbouring pads with equal signal
867 } else if (digt->fSignal == fQ[i][cath]) {
868 if (fNLocal[cath]>0) {
869 for (Int_t k=0; k<fNLocal[cath]; k++) {
870 if (x[j]==fIx[fIndLocal[k][cath]][cath]
871 && y[j]==fIy[fIndLocal[k][cath]][cath])
873 isLocal[i][cath]=kFALSE;
875 } // loop over local maxima
876 } // are there already local maxima
878 } // loop over next neighbours
879 if (isLocal[i][cath]) {
880 fIndLocal[fNLocal[cath]][cath]=i;
883 } // loop over all digits
884 } // loop over cathodes
886 printf("\n Found %d %d %d %d local Maxima\n",
887 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
888 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
889 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
894 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
895 Int_t iback=fNLocal[0];
897 // Two local maxima on cathode 2 and one maximum on cathode 1
898 // Look for local maxima considering up and down neighbours on the 1st cathode only
900 // Loop over cluster digits
904 for (i=0; i<fMul[cath]; i++) {
905 isec=fInput->Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
906 dpy=fInput->Segmentation(cath)->Dpy(isec);
907 dpx=fInput->Segmentation(cath)->Dpx(isec);
908 if (isLocal[i][cath]) continue;
909 // Pad position should be consistent with position of local maxima on the opposite cathode
910 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
911 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
914 // get neighbours for that digit and assume that it is local maximum
915 isLocal[i][cath]=kTRUE;
916 // compare signal to that on the two neighbours on the left and on the right
917 fInput->Segmentation(cath)->GetPadI(fX[i][cath],fY[i][cath]+dpy,0,ix,iy);
918 // iNN counts the number of neighbours with signal, it should be 1 or 2
920 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
922 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
923 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
925 fInput->Segmentation(cath)->GetPadI(fX[i][cath],fY[i][cath]-dpy,0,ix,iy);
926 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
928 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
929 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
931 if (isLocal[i][cath] && iNN>0) {
932 fIndLocal[fNLocal[cath]][cath]=i;
935 } // loop over all digits
936 // if one additional maximum has been found we are happy
937 // if more maxima have been found restore the previous situation
938 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
939 fprintf(stderr," %d local maxima for cathode 2 \n",fNLocal[1]);
940 if (fNLocal[cath]>2) {
944 } // 1,2 local maxima
946 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
947 Int_t iback=fNLocal[1];
949 // Two local maxima on cathode 1 and one maximum on cathode 2
950 // Look for local maxima considering left and right neighbours on the 2nd cathode only
956 // Loop over cluster digits
957 for (i=0; i<fMul[cath]; i++) {
958 isec=fInput->Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
959 dpx=fInput->Segmentation(cath)->Dpx(isec);
960 dpy=fInput->Segmentation(cath)->Dpy(isec);
961 if (isLocal[i][cath]) continue;
962 // Pad position should be consistent with position of local maxima on the opposite cathode
963 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
964 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.))
967 // get neighbours for that digit and assume that it is local maximum
968 isLocal[i][cath]=kTRUE;
969 // compare signal to that on the two neighbours on the left and on the right
970 fInput->Segmentation(cath)->GetPadI(fX[i][cath]+dpx,fY[i][cath],0,ix,iy);
971 // iNN counts the number of neighbours with signal, it should be 1 or 2
973 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
975 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
976 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
978 fInput->Segmentation(cath)->GetPadI(fX[i][cath]-dpx,fY[i][cath],0,ix,iy);
979 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
981 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
982 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
984 if (isLocal[i][cath] && iNN>0) {
985 fIndLocal[fNLocal[cath]][cath]=i;
988 } // loop over all digits
989 // if one additional maximum has been found we are happy
990 // if more maxima have been found restore the previous situation
991 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
992 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
993 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
994 if (fNLocal[cath]>2) {
1000 } // 2,1 local maxima
1004 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
1007 // Completes cluster information starting from list of digits
1014 c->fPeakSignal[cath]=c->fPeakSignal[0];
1016 c->fPeakSignal[cath]=0;
1026 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1027 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1029 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1030 ix=dig->fPadX+c->fOffsetMap[i][cath];
1032 Int_t q=dig->fSignal;
1033 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1034 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1035 if (dig->fPhysics >= dig->fSignal) {
1036 c->fPhysicsMap[i]=2;
1037 } else if (dig->fPhysics == 0) {
1038 c->fPhysicsMap[i]=0;
1039 } else c->fPhysicsMap[i]=1;
1042 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1043 // peak signal and track list
1044 if (q>c->fPeakSignal[cath]) {
1045 c->fPeakSignal[cath]=q;
1046 c->fTracks[0]=dig->fHit;
1047 c->fTracks[1]=dig->fTracks[0];
1048 c->fTracks[2]=dig->fTracks[1];
1049 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1053 fInput->Segmentation(cath)->GetPadC(ix, iy, x, y, z);
1058 } // loop over digits
1059 // fprintf(stderr," fin du cluster c\n");
1063 c->fX[cath]/=c->fQ[cath];
1064 c->fX[cath]=fInput->Segmentation(cath)->GetAnod(c->fX[cath]);
1065 c->fY[cath]/=c->fQ[cath];
1067 // apply correction to the coordinate along the anode wire
1071 fInput->Segmentation(cath)->GetPadI(x, y, 0, ix, iy);
1072 fInput->Segmentation(cath)->GetPadC(ix, iy, x, y, z);
1073 Int_t isec=fInput->Segmentation(cath)->Sector(ix,iy);
1074 TF1* cogCorr = fInput->Segmentation(cath)->CorrFunc(isec-1);
1077 Float_t yOnPad=(c->fY[cath]-y)/fInput->Segmentation(cath)->Dpy(isec);
1078 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1083 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1086 // Completes cluster information starting from list of digits
1096 Float_t xpad, ypad, zpad;
1099 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1101 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1102 fInput->Segmentation(cath)->
1103 GetPadC(dig->fPadX,dig->fPadY,xpad,ypad, zpad);
1104 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1105 dx = xpad - c->fX[0];
1106 dy = ypad - c->fY[0];
1107 dr = TMath::Sqrt(dx*dx+dy*dy);
1111 fprintf(stderr," dr %f\n",dr);
1112 Int_t q=dig->fSignal;
1113 if (dig->fPhysics >= dig->fSignal) {
1114 c->fPhysicsMap[i]=2;
1115 } else if (dig->fPhysics == 0) {
1116 c->fPhysicsMap[i]=0;
1117 } else c->fPhysicsMap[i]=1;
1118 c->fPeakSignal[cath]=q;
1119 c->fTracks[0]=dig->fHit;
1120 c->fTracks[1]=dig->fTracks[0];
1121 c->fTracks[2]=dig->fTracks[1];
1122 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1125 } // loop over digits
1127 // apply correction to the coordinate along the anode wire
1128 c->fX[cath]=fInput->Segmentation(cath)->GetAnod(c->fX[cath]);
1131 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1136 // Add i,j as element of the cluster
1139 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1140 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1141 Int_t q=dig->fSignal;
1142 Int_t theX=dig->fPadX;
1143 Int_t theY=dig->fPadY;
1144 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1145 c.fPeakSignal[cath]=q;
1146 c.fTracks[0]=dig->fHit;
1147 c.fTracks[1]=dig->fTracks[0];
1148 c.fTracks[2]=dig->fTracks[1];
1152 // Make sure that list of digits is ordered
1154 Int_t mu=c.fMultiplicity[cath];
1155 c.fIndexMap[mu][cath]=idx;
1157 if (dig->fPhysics >= dig->fSignal) {
1158 c.fPhysicsMap[mu]=2;
1159 } else if (dig->fPhysics == 0) {
1160 c.fPhysicsMap[mu]=0;
1161 } else c.fPhysicsMap[mu]=1;
1163 for (Int_t ind=mu-1; ind>=0; ind--) {
1164 Int_t ist=(c.fIndexMap)[ind][cath];
1165 Int_t ql=fInput->Digit(cath, ist)->fSignal;
1166 Int_t ix=fInput->Digit(cath, ist)->fPadX;
1167 Int_t iy=fInput->Digit(cath, ist)->fPadY;
1169 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1170 c.fIndexMap[ind][cath]=idx;
1171 c.fIndexMap[ind+1][cath]=ist;
1178 c.fMultiplicity[cath]++;
1179 if (c.fMultiplicity[cath] >= 50 ) {
1180 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1181 c.fMultiplicity[cath]=49;
1184 // Prepare center of gravity calculation
1186 fInput->Segmentation(cath)->GetPadC(i, j, x, y, z);
1191 // Flag hit as taken
1192 fHitMap[cath]->FlagHit(i,j);
1194 // Now look recursively for all neighbours and pad hit on opposite cathode
1196 // Loop over neighbours
1199 Int_t xList[10], yList[10];
1200 fInput->Segmentation(cath)->Neighbours(i,j,&nn,xList,yList);
1201 for (Int_t in=0; in<nn; in++) {
1204 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, cath, c);
1206 // Neighbours on opposite cathode
1207 // Take into account that several pads can overlap with the present pad
1208 Float_t xmin, xmax, ymin, ymax, xc, yc;
1210 Int_t isec=fInput->Segmentation(cath)->Sector(i,j);
1213 xmin=x-fInput->Segmentation(cath)->Dpx(isec);
1214 xmax=x+fInput->Segmentation(cath)->Dpx(isec);
1217 xc+=fInput->Segmentation(iop)->Dpx(isec);
1218 fInput->Segmentation(iop)->GetPadI(xc,y,0,ix,iy);
1219 if (ix>=(fInput->Segmentation(iop)->Npx()) || (iy>=fInput->Segmentation(iop)->Npy())) continue;
1220 if (fHitMap[iop]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1224 ymin=y-fInput->Segmentation(cath)->Dpy(isec);
1225 ymax=y+fInput->Segmentation(cath)->Dpy(isec);
1228 yc+=fInput->Segmentation(iop)->Dpy(isec);
1229 fInput->Segmentation(iop)->GetPadI(x,yc,0,ix,iy);
1230 if (ix>=(fInput->Segmentation(iop)->Npx()) || (iy>=fInput->Segmentation(iop)->Npy())) continue;
1231 if (fHitMap[iop]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1236 //_____________________________________________________________________________
1238 void AliMUONClusterFinderVS::FindRawClusters()
1241 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1242 // fills the tree with raw clusters
1245 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1247 fHitMap[0] = new AliMUONHitMapA1(fInput->Segmentation(0), fInput->Digits(0));
1248 fHitMap[1] = new AliMUONHitMapA1(fInput->Segmentation(1), fInput->Digits(1));
1255 fHitMap[0]->FillHits();
1256 fHitMap[1]->FillHits();
1258 // Outer Loop over Cathodes
1259 for (cath=0; cath<2; cath++) {
1260 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1261 dig = fInput->Digit(cath, ndig);
1264 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1268 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1269 AliMUONRawCluster c;
1270 c.fMultiplicity[0]=0;
1271 c.fMultiplicity[1]=0;
1272 c.fPeakSignal[cath]=dig->fSignal;
1273 c.fTracks[0]=dig->fHit;
1274 c.fTracks[1]=dig->fTracks[0];
1275 c.fTracks[2]=dig->fTracks[1];
1276 // tag the beginning of cluster list in a raw cluster
1279 FindCluster(i,j,cath,c);
1281 // center of gravity
1283 c.fX[0]=fInput->Segmentation(0)->GetAnod(c.fX[0]);
1286 c.fX[1]=fInput->Segmentation(0)->GetAnod(c.fX[1]);
1288 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[0],c.fX[0],c.fY[0]);
1289 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[1],c.fX[1],c.fY[1]);
1295 fitted=SingleMathiesonFit(&c, 0);
1296 c.fX[0]=fInput->Segmentation(0)->GetAnod(c.fX[0]);
1297 fitted=SingleMathiesonFit(&c, 1);
1298 c.fX[1]=fInput->Segmentation(1)->GetAnod(c.fX[1]);
1301 // Analyse cluster and decluster if necessary
1304 c.fNcluster[1]=fNRawClusters;
1305 c.fClusterType=c.PhysicsContribution();
1311 // AddRawCluster(c);
1314 // reset Cluster object
1315 { // begin local scope
1316 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1317 } // end local scope
1319 { // begin local scope
1320 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1321 } // end local scope
1323 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1327 } // end loop cathodes
1332 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1335 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1337 clusterInput.Fitter()->SetFCN(fcnS1);
1338 clusterInput.Fitter()->mninit(2,10,7);
1339 Double_t arglist[20];
1342 // clusterInput.Fitter()->mnexcm("SET ERR",arglist,1,ierflag);
1343 // Set starting values
1344 static Double_t vstart[2];
1349 // lower and upper limits
1350 static Double_t lower[2], upper[2];
1352 fInput->Segmentation(cath)->GetPadI(c->fX[cath], c->fY[cath], 0, ix, iy);
1353 Int_t isec=fInput->Segmentation(cath)->Sector(ix, iy);
1354 lower[0]=vstart[0]-fInput->Segmentation(cath)->Dpx(isec)/2;
1355 lower[1]=vstart[1]-fInput->Segmentation(cath)->Dpy(isec)/2;
1357 upper[0]=lower[0]+fInput->Segmentation(cath)->Dpx(isec);
1358 upper[1]=lower[1]+fInput->Segmentation(cath)->Dpy(isec);
1361 static Double_t step[2]={0.0005, 0.0005};
1363 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1364 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1365 // ready for minimisation
1366 clusterInput.Fitter()->SetPrintLevel(1);
1367 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1371 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1372 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1373 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1374 Double_t fmin, fedm, errdef;
1375 Int_t npari, nparx, istat;
1377 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1381 // Get fitted parameters
1382 Double_t xrec, yrec;
1384 Double_t epxz, b1, b2;
1386 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1387 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1393 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1395 // Perform combined Mathieson fit on both cathode planes
1397 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1398 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1399 clusterInput.Fitter()->mninit(2,10,7);
1400 Double_t arglist[20];
1403 static Double_t vstart[2];
1404 vstart[0]=fXInit[0];
1405 vstart[1]=fYInit[0];
1408 // lower and upper limits
1409 static Double_t lower[2], upper[2];
1411 fInput->Segmentation(0)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1412 isec=fInput->Segmentation(0)->Sector(ix, iy);
1413 Float_t dpy=fInput->Segmentation(0)->Dpy(isec)/2;
1414 fInput->Segmentation(1)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1415 isec=fInput->Segmentation(1)->Sector(ix, iy);
1416 Float_t dpx=fInput->Segmentation(1)->Dpx(isec)/2;
1419 lower[0]=vstart[0]-dpx;
1420 lower[1]=vstart[1]-dpy;
1422 upper[0]=vstart[0]+dpx;
1423 upper[1]=vstart[1]+dpy;
1426 static Double_t step[2]={0.00001, 0.0001};
1428 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1429 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1430 // ready for minimisation
1431 clusterInput.Fitter()->SetPrintLevel(1);
1432 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1436 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1437 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1438 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1439 Double_t fmin, fedm, errdef;
1440 Int_t npari, nparx, istat;
1442 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1446 // Get fitted parameters
1447 Double_t xrec, yrec;
1449 Double_t epxz, b1, b2;
1451 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1452 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1458 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1461 // Initialise global variables for fit
1462 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1463 clusterInput.Fitter()->SetFCN(fcnS2);
1464 clusterInput.Fitter()->mninit(5,10,7);
1465 Double_t arglist[20];
1468 // Set starting values
1469 static Double_t vstart[5];
1470 vstart[0]=fX[fIndLocal[0][cath]][cath];
1471 vstart[1]=fY[fIndLocal[0][cath]][cath];
1472 vstart[2]=fX[fIndLocal[1][cath]][cath];
1473 vstart[3]=fY[fIndLocal[1][cath]][cath];
1474 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1475 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1476 // lower and upper limits
1477 static Double_t lower[5], upper[5];
1478 Int_t isec=fInput->Segmentation(cath)->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1479 lower[0]=vstart[0]-fInput->Segmentation(cath)->Dpx(isec);
1480 lower[1]=vstart[1]-fInput->Segmentation(cath)->Dpy(isec);
1482 upper[0]=lower[0]+2.*fInput->Segmentation(cath)->Dpx(isec);
1483 upper[1]=lower[1]+2.*fInput->Segmentation(cath)->Dpy(isec);
1485 isec=fInput->Segmentation(cath)->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1486 lower[2]=vstart[2]-fInput->Segmentation(cath)->Dpx(isec)/2;
1487 lower[3]=vstart[3]-fInput->Segmentation(cath)->Dpy(isec)/2;
1489 upper[2]=lower[2]+fInput->Segmentation(cath)->Dpx(isec);
1490 upper[3]=lower[3]+fInput->Segmentation(cath)->Dpy(isec);
1495 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1497 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1498 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1499 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1500 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1501 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1502 // ready for minimisation
1503 clusterInput.Fitter()->SetPrintLevel(-1);
1504 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1508 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1509 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1510 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1511 // Get fitted parameters
1512 Double_t xrec[2], yrec[2], qfrac;
1514 Double_t epxz, b1, b2;
1516 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1517 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1518 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1519 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1520 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1522 Double_t fmin, fedm, errdef;
1523 Int_t npari, nparx, istat;
1525 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1530 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1533 // Perform combined double Mathieson fit on both cathode planes
1535 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1536 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1537 clusterInput.Fitter()->mninit(6,10,7);
1538 Double_t arglist[20];
1541 // Set starting values
1542 static Double_t vstart[6];
1543 vstart[0]=fXInit[0];
1544 vstart[1]=fYInit[0];
1545 vstart[2]=fXInit[1];
1546 vstart[3]=fYInit[1];
1547 vstart[4]=fQrInit[0];
1548 vstart[5]=fQrInit[1];
1549 // lower and upper limits
1550 static Double_t lower[6], upper[6];
1554 fInput->Segmentation(1)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1555 isec=fInput->Segmentation(1)->Sector(ix, iy);
1556 dpx=fInput->Segmentation(1)->Dpx(isec);
1558 fInput->Segmentation(0)->GetPadI(fXInit[0], fYInit[0], 0, ix, iy);
1559 isec=fInput->Segmentation(0)->Sector(ix, iy);
1560 dpy=fInput->Segmentation(0)->Dpy(isec);
1562 lower[0]=vstart[0]-dpx;
1563 lower[1]=vstart[1]-dpy;
1564 upper[0]=vstart[0]+dpx;
1565 upper[1]=vstart[1]+dpy;
1568 fInput->Segmentation(1)->GetPadI(fXInit[1], fYInit[1], 0, ix, iy);
1569 isec=fInput->Segmentation(1)->Sector(ix, iy);
1570 dpx=fInput->Segmentation(1)->Dpx(isec);
1571 fInput->Segmentation(0)->GetPadI(fXInit[1], fYInit[1], 0, ix, iy);
1572 isec=fInput->Segmentation(0)->Sector(ix, iy);
1573 dpy=fInput->Segmentation(0)->Dpy(isec);
1575 lower[2]=vstart[2]-dpx;
1576 lower[3]=vstart[3]-dpy;
1577 upper[2]=vstart[2]+dpx;
1578 upper[3]=vstart[3]+dpy;
1587 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1589 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1590 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1591 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1592 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1593 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1594 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1595 // ready for minimisation
1596 clusterInput.Fitter()->SetPrintLevel(-1);
1597 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1601 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1602 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1603 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1604 // Get fitted parameters
1606 Double_t epxz, b1, b2;
1608 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1609 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1610 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1611 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1612 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1613 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1615 Double_t fmin, fedm, errdef;
1616 Int_t npari, nparx, istat;
1618 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1626 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1629 // One cluster for each maximum
1632 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1633 for (j=0; j<2; j++) {
1634 AliMUONRawCluster cnew;
1635 for (cath=0; cath<2; cath++) {
1636 cnew.fChi2[cath]=fChi2[0];
1639 cnew.fNcluster[0]=-1;
1640 cnew.fNcluster[1]=fNRawClusters;
1642 cnew.fNcluster[0]=fNPeaks;
1643 cnew.fNcluster[1]=0;
1645 cnew.fMultiplicity[cath]=0;
1646 cnew.fX[cath]=Float_t(fXFit[j]);
1647 cnew.fY[cath]=Float_t(fYFit[j]);
1649 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
1651 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
1653 fInput->Segmentation(cath)->SetHit(fXFit[j],fYFit[j],0);
1654 for (i=0; i<fMul[cath]; i++) {
1655 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1656 c->fIndexMap[i][cath];
1657 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
1658 Float_t q1=fInput->Response()->IntXY(fInput->Segmentation(cath));
1659 cnew.fContMap[i][cath]
1660 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1661 cnew.fMultiplicity[cath]++;
1662 // printf(" fXFIT %f fYFIT %f Multiplicite %d\n",cnew.fX[cath],cnew.fY[cath],cnew.fMultiplicity[cath]);
1664 FillCluster(&cnew,0,cath);
1667 cnew.fClusterType=cnew.PhysicsContribution();
1668 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1675 // Minimisation functions
1677 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1679 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1686 for (i=0; i<clusterInput.Nmul(0); i++) {
1687 Float_t q0=clusterInput.Charge(i,0);
1688 Float_t q1=clusterInput.DiscrChargeS1(i,par);
1697 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1699 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1705 // Float_t chi2temp=0;
1707 for (cath=0; cath<2; cath++) {
1709 for (i=0; i<clusterInput.Nmul(cath); i++) {
1710 Float_t q0=clusterInput.Charge(i,cath);
1711 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
1718 // if (cath == 0) chi2temp=chisq/clusterInput.Nbins[cath];
1720 // chisq = chisq/clusterInput.Nbins[1]+chi2temp;
1725 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1727 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1734 for (i=0; i<clusterInput.Nmul(0); i++) {
1736 Float_t q0=clusterInput.Charge(i,0);
1737 Float_t q1=clusterInput.DiscrChargeS2(i,par);
1743 // chisq=chisq+=(qtot-qcont)*(qtot-qcont)*0.5;
1748 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1750 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1756 // Float_t chi2temp=0;
1758 for (cath=0; cath<2; cath++) {
1760 for (i=0; i<clusterInput.Nmul(cath); i++) {
1761 Float_t q0=clusterInput.Charge(i,cath);
1762 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
1769 // if (cath == 0) chi2temp=chisq/clusterInput.Nbins[cath];
1771 // chisq = chisq/clusterInput.Nbins[1]+chi2temp;
1775 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1778 // Add a raw cluster copy to the list
1780 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1781 pMUON->AddRawCluster(fInput->Chamber(),c);
1783 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1786 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
1787 if (fTrack[0]==-1 || fTrack[1]==-1) {
1789 } else if (t==fTrack[0] || t==fTrack[1]) {
1796 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1797 ::operator = (const AliMUONClusterFinderVS& rhs)
1799 // Dummy assignment operator