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.6 2000/06/28 12:19:18 morsch
18 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
19 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
20 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
21 It requires two cathode planes. Small modifications in the code will make it usable for
22 one cathode plane and, hence, more general (for test beam data).
23 AliMUONClusterFinder is now obsolete.
25 Revision 1.5 2000/06/28 08:06:10 morsch
26 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
27 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
28 It also naturally takes care of the TMinuit instance.
30 Revision 1.4 2000/06/27 16:18:47 gosset
31 Finally correct implementation of xm, ym, ixm, iym sizes
32 when at least three local maxima on cathode 1 or on cathode 2
34 Revision 1.3 2000/06/22 14:02:45 morsch
35 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
36 Some HP scope problems corrected (PH)
38 Revision 1.2 2000/06/15 07:58:48 morsch
39 Code from MUON-dev joined
41 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
42 Most coding rule violations corrected.
44 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
45 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
46 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
47 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
48 - For clusters with more than 2 maxima on one of the cathode planes all valid
49 combinations of maxima on the two cathodes are preserved. The position of the maxima is
50 taken as the hit position.
51 - New FillCluster method with 2 arguments to find tracks associated to the clusters
52 defined above added. (Method destinction by argument list not very elegant in this case,
53 should be revides (A.M.)
54 - Bug in if-statement to handle maximum 1 maximum per plane corrected
55 - Two cluster per cathode but only 1 combination valid is handled.
56 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
60 #include "AliMUONClusterFinderVS.h"
61 #include "AliMUONDigit.h"
62 #include "AliMUONRawCluster.h"
63 #include "AliMUONSegmentation.h"
64 #include "AliMUONResponse.h"
65 #include "AliMUONHitMap.h"
66 #include "AliMUONHitMapA1.h"
75 #include <TPostScript.h>
80 //_____________________________________________________________________
81 // This function is minimized in the double-Mathieson fit
82 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
83 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
84 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
85 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
87 ClassImp(AliMUONClusterFinderVS)
89 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
91 // Default constructor
92 fInput=AliMUONClusterInput::Instance();
95 fTrack[0]=fTrack[1]=-1;
98 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
99 const AliMUONClusterFinderVS & clusterFinder)
101 // Dummy copy Constructor
105 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
107 // Decluster by local maxima
108 SplitByLocalMaxima(cluster);
111 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
113 // Split complex cluster by local maxima
117 fInput->SetCluster(c);
119 fMul[0]=c->fMultiplicity[0];
120 fMul[1]=c->fMultiplicity[1];
123 // dump digit information into arrays
128 for (cath=0; cath<2; cath++) {
130 for (i=0; i<fMul[cath]; i++)
133 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
135 fIx[i][cath]= fDig[i][cath]->fPadX;
136 fIy[i][cath]= fDig[i][cath]->fPadY;
138 fQ[i][cath] = fDig[i][cath]->fSignal;
139 // pad centre coordinates
140 fInput->Segmentation(cath)->
141 GetPadCxy(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], zdum);
142 } // loop over cluster digits
143 } // loop over cathodes
149 // Initialise and perform mathieson fits
150 Float_t chi2, oldchi2;
151 // ++++++++++++++++++*************+++++++++++++++++++++
152 // (1) No more than one local maximum per cathode plane
153 // +++++++++++++++++++++++++++++++*************++++++++
154 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
155 (fNLocal[0]==0 && fNLocal[1]==1)) {
157 // Perform combined single Mathieson fit
158 // Initial values for coordinates (x,y)
160 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
161 if (fNLocal[0]==1 && fNLocal[1]==1) {
164 // One local maximum on cathode 1 (X,Y->cathode 1)
165 } else if (fNLocal[0]==1) {
168 // One local maximum on cathode 2 (X,Y->cathode 2)
173 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
174 chi2=CombiSingleMathiesonFit(c);
175 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
176 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
177 // prob1->Fill(prob);
178 // chi2_1->Fill(chi2);
180 fprintf(stderr," chi2 %f ",chi2);
189 c->fX[0]=fInput->Segmentation(0)->GetAnod(c->fX[0]);
190 c->fX[1]=fInput->Segmentation(1)->GetAnod(c->fX[1]);
192 // If reasonable chi^2 add result to the list of rawclusters
196 // If not try combined double Mathieson Fit
198 fprintf(stderr," MAUVAIS CHI2 !!!\n");
199 if (fNLocal[0]==1 && fNLocal[1]==1) {
200 fXInit[0]=fX[fIndLocal[0][1]][1];
201 fYInit[0]=fY[fIndLocal[0][0]][0];
202 fXInit[1]=fX[fIndLocal[0][1]][1];
203 fYInit[1]=fY[fIndLocal[0][0]][0];
204 } else if (fNLocal[0]==1) {
205 fXInit[0]=fX[fIndLocal[0][0]][0];
206 fYInit[0]=fY[fIndLocal[0][0]][0];
207 fXInit[1]=fX[fIndLocal[0][0]][0];
208 fYInit[1]=fY[fIndLocal[0][0]][0];
210 fXInit[0]=fX[fIndLocal[0][1]][1];
211 fYInit[0]=fY[fIndLocal[0][1]][1];
212 fXInit[1]=fX[fIndLocal[0][1]][1];
213 fYInit[1]=fY[fIndLocal[0][1]][1];
216 // Initial value for charge ratios
219 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
220 chi2=CombiDoubleMathiesonFit(c);
221 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
222 // Float_t prob = TMath::Prob(chi2,ndf);
223 // prob2->Fill(prob);
224 // chi2_2->Fill(chi2);
226 // Was this any better ??
227 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
228 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
229 fprintf(stderr," Split\n");
230 // Split cluster into two according to fit result
233 fprintf(stderr," Don't Split\n");
239 // +++++++++++++++++++++++++++++++++++++++
240 // (2) Two local maxima per cathode plane
241 // +++++++++++++++++++++++++++++++++++++++
242 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
244 // Let's look for ghosts first
246 Float_t xm[4][2], ym[4][2];
247 Float_t dpx, dpy, dx, dy;
248 Int_t ixm[4][2], iym[4][2];
249 Int_t isec, im1, im2, ico;
251 // Form the 2x2 combinations
252 // 0-0, 0-1, 1-0, 1-1
254 for (im1=0; im1<2; im1++) {
255 for (im2=0; im2<2; im2++) {
256 xm[ico][0]=fX[fIndLocal[im1][0]][0];
257 ym[ico][0]=fY[fIndLocal[im1][0]][0];
258 xm[ico][1]=fX[fIndLocal[im2][1]][1];
259 ym[ico][1]=fY[fIndLocal[im2][1]][1];
261 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
262 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
263 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
264 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
268 // ico = 0 : first local maximum on cathodes 1 and 2
269 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
270 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
271 // ico = 3 : second local maximum on cathodes 1 and 2
273 // Analyse the combinations and keep those that are possible !
274 // For each combination check consistency in x and y
279 for (ico=0; ico<4; ico++) {
280 accepted[ico]=kFALSE;
281 // cathode one: x-coordinate
282 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
283 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
284 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
285 // cathode two: y-coordinate
286 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
287 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
288 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
289 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
290 if ((dx <= dpx) && (dy <= dpy)) {
296 accepted[ico]=kFALSE;
301 fprintf(stderr,"\n iacc=2: No problem ! \n");
302 } else if (iacc==4) {
303 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
304 } else if (iacc==0) {
305 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
308 // Initial value for charge ratios
309 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
310 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
311 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
312 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
314 // ******* iacc = 0 *******
315 // No combinations found between the 2 cathodes
316 // We keep the center of gravity of the cluster
321 // ******* iacc = 1 *******
322 // Only one combination found between the 2 cathodes
325 // Initial values for the 2 maxima (x,y)
327 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
328 // 1 maximum is initialised with the other maximum of the first cathode
330 fprintf(stderr,"ico=0\n");
335 } else if (accepted[1]){
336 fprintf(stderr,"ico=1\n");
341 } else if (accepted[2]){
342 fprintf(stderr,"ico=2\n");
347 } else if (accepted[3]){
348 fprintf(stderr,"ico=3\n");
354 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
355 chi2=CombiDoubleMathiesonFit(c);
356 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
357 // Float_t prob = TMath::Prob(chi2,ndf);
358 // prob2->Fill(prob);
359 // chi2_2->Fill(chi2);
360 fprintf(stderr," chi2 %f\n",chi2);
362 // If reasonable chi^2 add result to the list of rawclusters
367 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
368 // 1 maximum is initialised with the other maximum of the second cathode
370 fprintf(stderr,"ico=0\n");
375 } else if (accepted[1]){
376 fprintf(stderr,"ico=1\n");
381 } else if (accepted[2]){
382 fprintf(stderr,"ico=2\n");
387 } else if (accepted[3]){
388 fprintf(stderr,"ico=3\n");
394 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
395 chi2=CombiDoubleMathiesonFit(c);
396 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
397 // Float_t prob = TMath::Prob(chi2,ndf);
398 // prob2->Fill(prob);
399 // chi2_2->Fill(chi2);
400 fprintf(stderr," chi2 %f\n",chi2);
402 // If reasonable chi^2 add result to the list of rawclusters
406 //We keep only the combination found (X->cathode 2, Y->cathode 1)
407 for (Int_t ico=0; ico<2; ico++) {
409 AliMUONRawCluster cnew;
411 for (cath=0; cath<2; cath++) {
412 cnew.fX[cath]=Float_t(xm[ico][1]);
413 cnew.fY[cath]=Float_t(ym[ico][0]);
414 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
415 for (i=0; i<fMul[cath]; i++) {
416 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
417 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
419 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
420 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
421 FillCluster(&cnew,cath);
423 cnew.fClusterType=cnew.PhysicsContribution();
432 // ******* iacc = 2 *******
433 // Two combinations found between the 2 cathodes
436 // Was the same maximum taken twice
437 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
438 fprintf(stderr,"\n Maximum taken twice !!!\n");
440 // Have a try !! with that
441 if (accepted[0]&&accepted[3]) {
452 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
453 chi2=CombiDoubleMathiesonFit(c);
454 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
455 // Float_t prob = TMath::Prob(chi2,ndf);
456 // prob2->Fill(prob);
457 // chi2_2->Fill(chi2);
461 // No ghosts ! No Problems ! - Perform one fit only !
462 if (accepted[0]&&accepted[3]) {
473 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
474 chi2=CombiDoubleMathiesonFit(c);
475 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
476 // Float_t prob = TMath::Prob(chi2,ndf);
477 // prob2->Fill(prob);
478 // chi2_2->Fill(chi2);
479 fprintf(stderr," chi2 %f\n",chi2);
483 // ******* iacc = 4 *******
484 // Four combinations found between the 2 cathodes
486 } else if (iacc==4) {
487 // Perform fits for the two possibilities !!
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);
504 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
505 chi2=CombiDoubleMathiesonFit(c);
506 // ndf = fgNbins[0]+fgNbins[1]-6;
507 // prob = TMath::Prob(chi2,ndf);
508 // prob2->Fill(prob);
509 // chi2_2->Fill(chi2);
510 fprintf(stderr," chi2 %f\n",chi2);
514 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
515 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
516 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
517 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
519 Float_t xm[4][2], ym[4][2];
520 Float_t dpx, dpy, dx, dy;
521 Int_t ixm[4][2], iym[4][2];
522 Int_t isec, im1, ico;
524 // Form the 2x2 combinations
525 // 0-0, 0-1, 1-0, 1-1
527 for (im1=0; im1<2; im1++) {
528 xm[ico][0]=fX[fIndLocal[im1][0]][0];
529 ym[ico][0]=fY[fIndLocal[im1][0]][0];
530 xm[ico][1]=fX[fIndLocal[0][1]][1];
531 ym[ico][1]=fY[fIndLocal[0][1]][1];
533 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
534 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
535 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
536 iym[ico][1]=fIy[fIndLocal[0][1]][1];
539 // ico = 0 : first local maximum on cathodes 1 and 2
540 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
542 // Analyse the combinations and keep those that are possible !
543 // For each combination check consistency in x and y
548 for (ico=0; ico<2; ico++) {
549 accepted[ico]=kFALSE;
550 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
551 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
552 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
553 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
554 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
555 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
556 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
557 if ((dx <= dpx) && (dy <= dpy)) {
563 accepted[ico]=kFALSE;
575 chi21=CombiDoubleMathiesonFit(c);
576 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
577 // Float_t prob = TMath::Prob(chi2,ndf);
578 // prob2->Fill(prob);
579 // chi2_2->Fill(chi21);
580 fprintf(stderr," chi2 %f\n",chi21);
581 if (chi21<10) Split(c);
582 } else if (accepted[1]) {
587 chi22=CombiDoubleMathiesonFit(c);
588 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
589 // Float_t prob = TMath::Prob(chi2,ndf);
590 // prob2->Fill(prob);
591 // chi2_2->Fill(chi22);
592 fprintf(stderr," chi2 %f\n",chi22);
593 if (chi22<10) Split(c);
596 if (chi21 > 10 && chi22 > 10) {
597 // We keep only the combination found (X->cathode 2, Y->cathode 1)
598 for (Int_t ico=0; ico<2; ico++) {
600 AliMUONRawCluster cnew;
602 for (cath=0; cath<2; cath++) {
603 cnew.fX[cath]=Float_t(xm[ico][1]);
604 cnew.fY[cath]=Float_t(ym[ico][0]);
605 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
606 for (i=0; i<fMul[cath]; i++) {
607 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
608 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
610 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
611 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
612 FillCluster(&cnew,cath);
614 cnew.fClusterType=cnew.PhysicsContribution();
621 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
622 // (3') One local maximum on cathode 1 and two maxima on cathode 2
623 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
624 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
626 Float_t xm[4][2], ym[4][2];
627 Float_t dpx, dpy, dx, dy;
628 Int_t ixm[4][2], iym[4][2];
629 Int_t isec, im1, ico;
631 // Form the 2x2 combinations
632 // 0-0, 0-1, 1-0, 1-1
634 for (im1=0; im1<2; im1++) {
635 xm[ico][0]=fX[fIndLocal[0][0]][0];
636 ym[ico][0]=fY[fIndLocal[0][0]][0];
637 xm[ico][1]=fX[fIndLocal[im1][1]][1];
638 ym[ico][1]=fY[fIndLocal[im1][1]][1];
640 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
641 iym[ico][0]=fIy[fIndLocal[0][0]][0];
642 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
643 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
646 // ico = 0 : first local maximum on cathodes 1 and 2
647 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
649 // Analyse the combinations and keep those that are possible !
650 // For each combination check consistency in x and y
655 for (ico=0; ico<2; ico++) {
656 accepted[ico]=kFALSE;
657 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
658 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
659 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
660 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
661 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
662 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
663 // printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
664 if ((dx <= dpx) && (dy <= dpy)) {
667 fprintf(stderr,"ico %d\n",ico);
671 accepted[ico]=kFALSE;
683 chi21=CombiDoubleMathiesonFit(c);
684 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
685 // Float_t prob = TMath::Prob(chi2,ndf);
686 // prob2->Fill(prob);
687 // chi2_2->Fill(chi21);
688 fprintf(stderr," chi2 %f\n",chi21);
689 if (chi21<10) Split(c);
690 } else if (accepted[1]) {
695 chi22=CombiDoubleMathiesonFit(c);
696 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
697 // Float_t prob = TMath::Prob(chi2,ndf);
698 // prob2->Fill(prob);
699 // chi2_2->Fill(chi22);
700 fprintf(stderr," chi2 %f\n",chi22);
701 if (chi22<10) Split(c);
704 if (chi21 > 10 && chi22 > 10) {
705 //We keep only the combination found (X->cathode 2, Y->cathode 1)
706 for (Int_t ico=0; ico<2; ico++) {
708 AliMUONRawCluster cnew;
710 for (cath=0; cath<2; cath++) {
711 cnew.fX[cath]=Float_t(xm[ico][1]);
712 cnew.fY[cath]=Float_t(ym[ico][0]);
713 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
714 for (i=0; i<fMul[cath]; i++) {
715 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
716 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
718 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
719 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
720 FillCluster(&cnew,cath);
722 cnew.fClusterType=cnew.PhysicsContribution();
729 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
730 // (4) At least three local maxima on cathode 1 or on cathode 2
731 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
732 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
734 Int_t param = fNLocal[0]*fNLocal[1];
737 Float_t ** xm = new Float_t * [param];
738 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
739 Float_t ** ym = new Float_t * [param];
740 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
741 Int_t ** ixm = new Int_t * [param];
742 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
743 Int_t ** iym = new Int_t * [param];
744 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
747 Float_t dpx, dpy, dx, dy;
750 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
751 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
752 xm[ico][0]=fX[fIndLocal[im1][0]][0];
753 ym[ico][0]=fY[fIndLocal[im1][0]][0];
754 xm[ico][1]=fX[fIndLocal[im2][1]][1];
755 ym[ico][1]=fY[fIndLocal[im2][1]][1];
757 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
758 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
759 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
760 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
767 fprintf(stderr,"nIco %d\n",nIco);
768 for (ico=0; ico<nIco; ico++) {
769 fprintf(stderr,"ico = %d\n",ico);
770 isec=fInput->Segmentation(0)->Sector(ixm[ico][0], iym[ico][0]);
771 dpx=fInput->Segmentation(0)->Dpx(isec)/2.;
772 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
773 isec=fInput->Segmentation(1)->Sector(ixm[ico][1], iym[ico][1]);
774 dpy=fInput->Segmentation(1)->Dpy(isec)/2.;
775 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
777 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
778 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
779 if ((dx <= dpx) && (dy <= dpy)) {
780 fprintf(stderr,"ok\n");
782 AliMUONRawCluster cnew;
783 for (cath=0; cath<2; cath++) {
784 cnew.fX[cath]=Float_t(xm[ico][1]);
785 cnew.fY[cath]=Float_t(ym[ico][0]);
786 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
787 for (i=0; i<fMul[cath]; i++) {
788 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
789 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
791 FillCluster(&cnew,cath);
793 cnew.fClusterType=cnew.PhysicsContribution();
805 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
807 // Find all local maxima of a cluster
811 Int_t cath, cath1; // loops over cathodes
812 Int_t i; // loops over digits
813 Int_t j; // loops over cathodes
817 // counters for number of local maxima
818 fNLocal[0]=fNLocal[1]=0;
819 // flags digits as local maximum
820 Bool_t isLocal[100][2];
821 for (i=0; i<100;i++) {
822 isLocal[i][0]=isLocal[i][1]=kFALSE;
824 // number of next neighbours and arrays to store them
827 // loop over cathodes
828 for (cath=0; cath<2; cath++) {
829 // loop over cluster digits
830 for (i=0; i<fMul[cath]; i++) {
831 // get neighbours for that digit and assume that it is local maximum
832 fInput->Segmentation(cath)->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
833 isLocal[i][cath]=kTRUE;
834 Int_t isec= fInput->Segmentation(cath)->Sector(fIx[i][cath], fIy[i][cath]);
835 Float_t a0 = fInput->Segmentation(cath)->Dpx(isec)*fInput->Segmentation(cath)->Dpy(isec);
836 // loop over next neighbours, if at least one neighbour has higher charger assumption
837 // digit is not local maximum
838 for (j=0; j<nn; j++) {
839 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
840 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
841 isec=fInput->Segmentation(cath)->Sector(x[j], y[j]);
842 Float_t a1 = fInput->Segmentation(cath)->Dpx(isec)*fInput->Segmentation(cath)->Dpy(isec);
843 if (digt->fSignal/a1 > fQ[i][cath]/a0) {
844 isLocal[i][cath]=kFALSE;
847 // handle special case of neighbouring pads with equal signal
848 } else if (digt->fSignal == fQ[i][cath]) {
849 if (fNLocal[cath]>0) {
850 for (Int_t k=0; k<fNLocal[cath]; k++) {
851 if (x[j]==fIx[fIndLocal[k][cath]][cath]
852 && y[j]==fIy[fIndLocal[k][cath]][cath])
854 isLocal[i][cath]=kFALSE;
856 } // loop over local maxima
857 } // are there already local maxima
859 } // loop over next neighbours
860 if (isLocal[i][cath]) {
861 fIndLocal[fNLocal[cath]][cath]=i;
864 } // loop over all digits
865 } // loop over cathodes
867 printf("\n Found %d %d %d %d local Maxima\n",
868 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
869 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
870 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
875 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
876 Int_t iback=fNLocal[0];
878 // Two local maxima on cathode 2 and one maximum on cathode 1
879 // Look for local maxima considering up and down neighbours on the 1st cathode only
881 // Loop over cluster digits
885 for (i=0; i<fMul[cath]; i++) {
886 isec=fInput->Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
887 dpy=fInput->Segmentation(cath)->Dpy(isec);
888 dpx=fInput->Segmentation(cath)->Dpx(isec);
889 if (isLocal[i][cath]) continue;
890 // Pad position should be consistent with position of local maxima on the opposite cathode
891 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
892 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
895 // get neighbours for that digit and assume that it is local maximum
896 isLocal[i][cath]=kTRUE;
897 // compare signal to that on the two neighbours on the left and on the right
898 fInput->Segmentation(cath)->GetPadIxy(fX[i][cath],fY[i][cath]+dpy,0,ix,iy);
899 // iNN counts the number of neighbours with signal, it should be 1 or 2
901 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
903 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
904 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
906 fInput->Segmentation(cath)->GetPadIxy(fX[i][cath],fY[i][cath]-dpy,0,ix,iy);
907 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
909 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
910 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
912 if (isLocal[i][cath] && iNN>0) {
913 fIndLocal[fNLocal[cath]][cath]=i;
916 } // loop over all digits
917 // if one additional maximum has been found we are happy
918 // if more maxima have been found restore the previous situation
919 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
920 fprintf(stderr," %d local maxima for cathode 2 \n",fNLocal[1]);
921 if (fNLocal[cath]>2) {
925 } // 1,2 local maxima
927 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
928 Int_t iback=fNLocal[1];
930 // Two local maxima on cathode 1 and one maximum on cathode 2
931 // Look for local maxima considering left and right neighbours on the 2nd cathode only
937 // Loop over cluster digits
938 for (i=0; i<fMul[cath]; i++) {
939 isec=fInput->Segmentation(cath)->Sector(fIx[i][cath],fIy[i][cath]);
940 dpx=fInput->Segmentation(cath)->Dpx(isec);
941 dpy=fInput->Segmentation(cath)->Dpy(isec);
942 if (isLocal[i][cath]) continue;
943 // Pad position should be consistent with position of local maxima on the opposite cathode
944 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.) &&
945 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.))
948 // get neighbours for that digit and assume that it is local maximum
949 isLocal[i][cath]=kTRUE;
950 // compare signal to that on the two neighbours on the left and on the right
951 fInput->Segmentation(cath)->GetPadIxy(fX[i][cath]+dpx,fY[i][cath],0,ix,iy);
952 // iNN counts the number of neighbours with signal, it should be 1 or 2
954 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
956 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
957 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
959 fInput->Segmentation(cath)->GetPadIxy(fX[i][cath]-dpx,fY[i][cath],0,ix,iy);
960 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
962 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
963 if (digt->fSignal > fQ[i][cath]) isLocal[i][cath]=kFALSE;
965 if (isLocal[i][cath] && iNN>0) {
966 fIndLocal[fNLocal[cath]][cath]=i;
969 } // loop over all digits
970 // if one additional maximum has been found we are happy
971 // if more maxima have been found restore the previous situation
972 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
973 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
974 // printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
975 if (fNLocal[cath]>2) {
981 } // 2,1 local maxima
985 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
988 // Completes cluster information starting from list of digits
995 c->fPeakSignal[cath]=c->fPeakSignal[0];
997 c->fPeakSignal[cath]=0;
1007 // fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1008 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1010 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1011 ix=dig->fPadX+c->fOffsetMap[i][cath];
1013 Int_t q=dig->fSignal;
1014 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1015 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1016 if (dig->fPhysics >= dig->fSignal) {
1017 c->fPhysicsMap[i]=2;
1018 } else if (dig->fPhysics == 0) {
1019 c->fPhysicsMap[i]=0;
1020 } else c->fPhysicsMap[i]=1;
1023 // fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1024 // peak signal and track list
1025 if (q>c->fPeakSignal[cath]) {
1026 c->fPeakSignal[cath]=q;
1027 c->fTracks[0]=dig->fHit;
1028 c->fTracks[1]=dig->fTracks[0];
1029 c->fTracks[2]=dig->fTracks[1];
1030 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1034 fInput->Segmentation(cath)->GetPadCxy(ix, iy, x, y, z);
1039 } // loop over digits
1040 // fprintf(stderr," fin du cluster c\n");
1044 c->fX[cath]/=c->fQ[cath];
1045 c->fX[cath]=fInput->Segmentation(cath)->GetAnod(c->fX[cath]);
1046 c->fY[cath]/=c->fQ[cath];
1048 // apply correction to the coordinate along the anode wire
1052 fInput->Segmentation(cath)->GetPadIxy(x, y, 0, ix, iy);
1053 fInput->Segmentation(cath)->GetPadCxy(ix, iy, x, y, z);
1054 Int_t isec=fInput->Segmentation(cath)->Sector(ix,iy);
1055 TF1* cogCorr = fInput->Segmentation(cath)->CorrFunc(isec-1);
1058 Float_t yOnPad=(c->fY[cath]-y)/fInput->Segmentation(cath)->Dpy(isec);
1059 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1064 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1067 // Completes cluster information starting from list of digits
1077 Float_t xpad, ypad, zpad;
1080 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1082 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1083 fInput->Segmentation(cath)->
1084 GetPadCxy(dig->fPadX,dig->fPadY,xpad,ypad, zpad);
1085 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1086 dx = xpad - c->fX[0];
1087 dy = ypad - c->fY[0];
1088 dr = TMath::Sqrt(dx*dx+dy*dy);
1092 fprintf(stderr," dr %f\n",dr);
1093 Int_t q=dig->fSignal;
1094 if (dig->fPhysics >= dig->fSignal) {
1095 c->fPhysicsMap[i]=2;
1096 } else if (dig->fPhysics == 0) {
1097 c->fPhysicsMap[i]=0;
1098 } else c->fPhysicsMap[i]=1;
1099 c->fPeakSignal[cath]=q;
1100 c->fTracks[0]=dig->fHit;
1101 c->fTracks[1]=dig->fTracks[0];
1102 c->fTracks[2]=dig->fTracks[1];
1103 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1106 } // loop over digits
1108 // apply correction to the coordinate along the anode wire
1109 c->fX[cath]=fInput->Segmentation(cath)->GetAnod(c->fX[cath]);
1112 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1117 // Add i,j as element of the cluster
1120 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1121 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1122 Int_t q=dig->fSignal;
1123 Int_t theX=dig->fPadX;
1124 Int_t theY=dig->fPadY;
1125 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1126 c.fPeakSignal[cath]=q;
1127 c.fTracks[0]=dig->fHit;
1128 c.fTracks[1]=dig->fTracks[0];
1129 c.fTracks[2]=dig->fTracks[1];
1133 // Make sure that list of digits is ordered
1135 Int_t mu=c.fMultiplicity[cath];
1136 c.fIndexMap[mu][cath]=idx;
1138 if (dig->fPhysics >= dig->fSignal) {
1139 c.fPhysicsMap[mu]=2;
1140 } else if (dig->fPhysics == 0) {
1141 c.fPhysicsMap[mu]=0;
1142 } else c.fPhysicsMap[mu]=1;
1144 for (Int_t ind=mu-1; ind>=0; ind--) {
1145 Int_t ist=(c.fIndexMap)[ind][cath];
1146 Int_t ql=fInput->Digit(cath, ist)->fSignal;
1147 Int_t ix=fInput->Digit(cath, ist)->fPadX;
1148 Int_t iy=fInput->Digit(cath, ist)->fPadY;
1150 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1151 c.fIndexMap[ind][cath]=idx;
1152 c.fIndexMap[ind+1][cath]=ist;
1159 c.fMultiplicity[cath]++;
1160 if (c.fMultiplicity[cath] >= 50 ) {
1161 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1162 c.fMultiplicity[cath]=49;
1165 // Prepare center of gravity calculation
1167 fInput->Segmentation(cath)->GetPadCxy(i, j, x, y, z);
1172 // Flag hit as taken
1173 fHitMap[cath]->FlagHit(i,j);
1175 // Now look recursively for all neighbours and pad hit on opposite cathode
1177 // Loop over neighbours
1180 Int_t xList[10], yList[10];
1181 fInput->Segmentation(cath)->Neighbours(i,j,&nn,xList,yList);
1182 for (Int_t in=0; in<nn; in++) {
1185 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, cath, c);
1187 // Neighbours on opposite cathode
1188 // Take into account that several pads can overlap with the present pad
1189 Float_t xmin, xmax, ymin, ymax, xc, yc;
1191 Int_t isec=fInput->Segmentation(cath)->Sector(i,j);
1194 xmin=x-fInput->Segmentation(cath)->Dpx(isec);
1195 xmax=x+fInput->Segmentation(cath)->Dpx(isec);
1198 xc+=fInput->Segmentation(iop)->Dpx(isec);
1199 fInput->Segmentation(iop)->GetPadIxy(xc,y,0,ix,iy);
1200 if (ix>=(fInput->Segmentation(iop)->Npx()) || (iy>=fInput->Segmentation(iop)->Npy())) continue;
1201 if (fHitMap[iop]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1205 ymin=y-fInput->Segmentation(cath)->Dpy(isec);
1206 ymax=y+fInput->Segmentation(cath)->Dpy(isec);
1209 yc+=fInput->Segmentation(iop)->Dpy(isec);
1210 fInput->Segmentation(iop)->GetPadIxy(x,yc,0,ix,iy);
1211 if (ix>=(fInput->Segmentation(iop)->Npx()) || (iy>=fInput->Segmentation(iop)->Npy())) continue;
1212 if (fHitMap[iop]->TestHit(ix,iy)==kUnused) FindCluster(ix, iy, iop, c);
1217 //_____________________________________________________________________________
1219 void AliMUONClusterFinderVS::FindRawClusters()
1222 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1223 // fills the tree with raw clusters
1226 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1228 fHitMap[0] = new AliMUONHitMapA1(fInput->Segmentation(0), fInput->Digits(0));
1229 fHitMap[1] = new AliMUONHitMapA1(fInput->Segmentation(1), fInput->Digits(1));
1236 fHitMap[0]->FillHits();
1237 fHitMap[1]->FillHits();
1239 // Outer Loop over Cathodes
1240 for (cath=0; cath<2; cath++) {
1241 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1242 dig = fInput->Digit(cath, ndig);
1245 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1249 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1250 AliMUONRawCluster c;
1251 c.fMultiplicity[0]=0;
1252 c.fMultiplicity[1]=0;
1253 c.fPeakSignal[cath]=dig->fSignal;
1254 c.fTracks[0]=dig->fHit;
1255 c.fTracks[1]=dig->fTracks[0];
1256 c.fTracks[2]=dig->fTracks[1];
1257 // tag the beginning of cluster list in a raw cluster
1260 FindCluster(i,j,cath,c);
1262 // center of gravity
1264 c.fX[0]=fInput->Segmentation(0)->GetAnod(c.fX[0]);
1267 c.fX[1]=fInput->Segmentation(0)->GetAnod(c.fX[1]);
1269 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[0],c.fX[0],c.fY[0]);
1270 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",c.fMultiplicity[1],c.fX[1],c.fY[1]);
1276 fitted=SingleMathiesonFit(&c, 0);
1277 c.fX[0]=fInput->Segmentation(0)->GetAnod(c.fX[0]);
1278 fitted=SingleMathiesonFit(&c, 1);
1279 c.fX[1]=fInput->Segmentation(1)->GetAnod(c.fX[1]);
1282 // Analyse cluster and decluster if necessary
1285 c.fNcluster[1]=fNRawClusters;
1286 c.fClusterType=c.PhysicsContribution();
1292 // AddRawCluster(c);
1295 // reset Cluster object
1296 { // begin local scope
1297 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1298 } // end local scope
1300 { // begin local scope
1301 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1302 } // end local scope
1304 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1308 } // end loop cathodes
1313 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1316 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1318 clusterInput.Fitter()->SetFCN(fcnS1);
1319 clusterInput.Fitter()->mninit(2,10,7);
1320 Double_t arglist[20];
1323 // clusterInput.Fitter()->mnexcm("SET ERR",arglist,1,ierflag);
1324 // Set starting values
1325 static Double_t vstart[2];
1330 // lower and upper limits
1331 static Double_t lower[2], upper[2];
1333 fInput->Segmentation(cath)->GetPadIxy(c->fX[cath], c->fY[cath], 0, ix, iy);
1334 Int_t isec=fInput->Segmentation(cath)->Sector(ix, iy);
1335 lower[0]=vstart[0]-fInput->Segmentation(cath)->Dpx(isec)/2;
1336 lower[1]=vstart[1]-fInput->Segmentation(cath)->Dpy(isec)/2;
1338 upper[0]=lower[0]+fInput->Segmentation(cath)->Dpx(isec);
1339 upper[1]=lower[1]+fInput->Segmentation(cath)->Dpy(isec);
1342 static Double_t step[2]={0.0005, 0.0005};
1344 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1345 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1346 // ready for minimisation
1347 clusterInput.Fitter()->SetPrintLevel(1);
1348 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1352 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1353 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1354 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1355 Double_t fmin, fedm, errdef;
1356 Int_t npari, nparx, istat;
1358 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1362 // Get fitted parameters
1363 Double_t xrec, yrec;
1365 Double_t epxz, b1, b2;
1367 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1368 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1374 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1376 // Perform combined Mathieson fit on both cathode planes
1378 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1379 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1380 clusterInput.Fitter()->mninit(2,10,7);
1381 Double_t arglist[20];
1384 static Double_t vstart[2];
1385 vstart[0]=fXInit[0];
1386 vstart[1]=fYInit[0];
1389 // lower and upper limits
1390 static Double_t lower[2], upper[2];
1392 fInput->Segmentation(0)->GetPadIxy(fXInit[0], fYInit[0], 0, ix, iy);
1393 isec=fInput->Segmentation(0)->Sector(ix, iy);
1394 Float_t dpy=fInput->Segmentation(0)->Dpy(isec)/2;
1395 fInput->Segmentation(1)->GetPadIxy(fXInit[0], fYInit[0], 0, ix, iy);
1396 isec=fInput->Segmentation(1)->Sector(ix, iy);
1397 Float_t dpx=fInput->Segmentation(1)->Dpx(isec)/2;
1400 lower[0]=vstart[0]-dpx;
1401 lower[1]=vstart[1]-dpy;
1403 upper[0]=vstart[0]+dpx;
1404 upper[1]=vstart[1]+dpy;
1407 static Double_t step[2]={0.00001, 0.0001};
1409 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1410 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1411 // ready for minimisation
1412 clusterInput.Fitter()->SetPrintLevel(1);
1413 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1417 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1418 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1419 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1420 Double_t fmin, fedm, errdef;
1421 Int_t npari, nparx, istat;
1423 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1427 // Get fitted parameters
1428 Double_t xrec, yrec;
1430 Double_t epxz, b1, b2;
1432 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1433 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1439 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1442 // Initialise global variables for fit
1443 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1444 clusterInput.Fitter()->SetFCN(fcnS2);
1445 clusterInput.Fitter()->mninit(5,10,7);
1446 Double_t arglist[20];
1449 // Set starting values
1450 static Double_t vstart[5];
1451 vstart[0]=fX[fIndLocal[0][cath]][cath];
1452 vstart[1]=fY[fIndLocal[0][cath]][cath];
1453 vstart[2]=fX[fIndLocal[1][cath]][cath];
1454 vstart[3]=fY[fIndLocal[1][cath]][cath];
1455 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1456 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1457 // lower and upper limits
1458 static Double_t lower[5], upper[5];
1459 Int_t isec=fInput->Segmentation(cath)->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1460 lower[0]=vstart[0]-fInput->Segmentation(cath)->Dpx(isec);
1461 lower[1]=vstart[1]-fInput->Segmentation(cath)->Dpy(isec);
1463 upper[0]=lower[0]+2.*fInput->Segmentation(cath)->Dpx(isec);
1464 upper[1]=lower[1]+2.*fInput->Segmentation(cath)->Dpy(isec);
1466 isec=fInput->Segmentation(cath)->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1467 lower[2]=vstart[2]-fInput->Segmentation(cath)->Dpx(isec)/2;
1468 lower[3]=vstart[3]-fInput->Segmentation(cath)->Dpy(isec)/2;
1470 upper[2]=lower[2]+fInput->Segmentation(cath)->Dpx(isec);
1471 upper[3]=lower[3]+fInput->Segmentation(cath)->Dpy(isec);
1476 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1478 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1479 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1480 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1481 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1482 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1483 // ready for minimisation
1484 clusterInput.Fitter()->SetPrintLevel(-1);
1485 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1489 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1490 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1491 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1492 // Get fitted parameters
1493 Double_t xrec[2], yrec[2], qfrac;
1495 Double_t epxz, b1, b2;
1497 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1498 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1499 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1500 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1501 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1503 Double_t fmin, fedm, errdef;
1504 Int_t npari, nparx, istat;
1506 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1511 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1514 // Perform combined double Mathieson fit on both cathode planes
1516 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1517 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1518 clusterInput.Fitter()->mninit(6,10,7);
1519 Double_t arglist[20];
1522 // Set starting values
1523 static Double_t vstart[6];
1524 vstart[0]=fXInit[0];
1525 vstart[1]=fYInit[0];
1526 vstart[2]=fXInit[1];
1527 vstart[3]=fYInit[1];
1528 vstart[4]=fQrInit[0];
1529 vstart[5]=fQrInit[1];
1530 // lower and upper limits
1531 static Double_t lower[6], upper[6];
1535 fInput->Segmentation(1)->GetPadIxy(fXInit[0], fYInit[0], 0, ix, iy);
1536 isec=fInput->Segmentation(1)->Sector(ix, iy);
1537 dpx=fInput->Segmentation(1)->Dpx(isec);
1539 fInput->Segmentation(0)->GetPadIxy(fXInit[0], fYInit[0], 0, ix, iy);
1540 isec=fInput->Segmentation(0)->Sector(ix, iy);
1541 dpy=fInput->Segmentation(0)->Dpy(isec);
1543 lower[0]=vstart[0]-dpx;
1544 lower[1]=vstart[1]-dpy;
1545 upper[0]=vstart[0]+dpx;
1546 upper[1]=vstart[1]+dpy;
1549 fInput->Segmentation(1)->GetPadIxy(fXInit[1], fYInit[1], 0, ix, iy);
1550 isec=fInput->Segmentation(1)->Sector(ix, iy);
1551 dpx=fInput->Segmentation(1)->Dpx(isec);
1552 fInput->Segmentation(0)->GetPadIxy(fXInit[1], fYInit[1], 0, ix, iy);
1553 isec=fInput->Segmentation(0)->Sector(ix, iy);
1554 dpy=fInput->Segmentation(0)->Dpy(isec);
1556 lower[2]=vstart[2]-dpx;
1557 lower[3]=vstart[3]-dpy;
1558 upper[2]=vstart[2]+dpx;
1559 upper[3]=vstart[3]+dpy;
1568 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1570 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1571 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1572 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1573 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1574 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1575 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1576 // ready for minimisation
1577 clusterInput.Fitter()->SetPrintLevel(-1);
1578 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1582 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1583 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1584 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1585 // Get fitted parameters
1587 Double_t epxz, b1, b2;
1589 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
1590 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
1591 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
1592 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
1593 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
1594 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
1596 Double_t fmin, fedm, errdef;
1597 Int_t npari, nparx, istat;
1599 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1607 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
1610 // One cluster for each maximum
1613 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1614 for (j=0; j<2; j++) {
1615 AliMUONRawCluster cnew;
1616 for (cath=0; cath<2; cath++) {
1617 cnew.fChi2[cath]=fChi2[0];
1620 cnew.fNcluster[0]=-1;
1621 cnew.fNcluster[1]=fNRawClusters;
1623 cnew.fNcluster[0]=fNPeaks;
1624 cnew.fNcluster[1]=0;
1626 cnew.fMultiplicity[cath]=0;
1627 cnew.fX[cath]=Float_t(fXFit[j]);
1628 cnew.fY[cath]=Float_t(fYFit[j]);
1630 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
1632 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
1634 fInput->Segmentation(cath)->SetHit(fXFit[j],fYFit[j],0);
1635 for (i=0; i<fMul[cath]; i++) {
1636 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
1637 c->fIndexMap[i][cath];
1638 fInput->Segmentation(cath)->SetPad(fIx[i][cath], fIy[i][cath]);
1639 Float_t q1=fInput->Response()->IntXY(fInput->Segmentation(cath));
1640 cnew.fContMap[i][cath]
1641 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
1642 cnew.fMultiplicity[cath]++;
1643 // printf(" fXFIT %f fYFIT %f Multiplicite %d\n",cnew.fX[cath],cnew.fY[cath],cnew.fMultiplicity[cath]);
1645 FillCluster(&cnew,0,cath);
1648 cnew.fClusterType=cnew.PhysicsContribution();
1649 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
1656 // Minimisation functions
1658 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1660 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1667 for (i=0; i<clusterInput.Nmul(0); i++) {
1668 Float_t q0=clusterInput.Charge(i,0);
1669 Float_t q1=clusterInput.DiscrChargeS1(i,par);
1678 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1680 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1686 // Float_t chi2temp=0;
1688 for (cath=0; cath<2; cath++) {
1690 for (i=0; i<clusterInput.Nmul(cath); i++) {
1691 Float_t q0=clusterInput.Charge(i,cath);
1692 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
1699 // if (cath == 0) chi2temp=chisq/clusterInput.Nbins[cath];
1701 // chisq = chisq/clusterInput.Nbins[1]+chi2temp;
1706 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1708 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1715 for (i=0; i<clusterInput.Nmul(0); i++) {
1717 Float_t q0=clusterInput.Charge(i,0);
1718 Float_t q1=clusterInput.DiscrChargeS2(i,par);
1724 // chisq=chisq+=(qtot-qcont)*(qtot-qcont)*0.5;
1729 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
1731 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1737 // Float_t chi2temp=0;
1739 for (cath=0; cath<2; cath++) {
1741 for (i=0; i<clusterInput.Nmul(cath); i++) {
1742 Float_t q0=clusterInput.Charge(i,cath);
1743 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
1750 // if (cath == 0) chi2temp=chisq/clusterInput.Nbins[cath];
1752 // chisq = chisq/clusterInput.Nbins[1]+chi2temp;
1756 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
1759 // Add a raw cluster copy to the list
1761 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
1762 pMUON->AddRawCluster(fInput->Chamber(),c);
1764 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
1767 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
1768 if (fTrack[0]==-1 || fTrack[1]==-1) {
1770 } else if (t==fTrack[0] || t==fTrack[1]) {
1777 AliMUONClusterFinderVS& AliMUONClusterFinderVS
1778 ::operator = (const AliMUONClusterFinderVS& rhs)
1780 // Dummy assignment operator