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.19 2001/03/20 13:32:10 egangler
18 Code introduced to remove ghosts with the charge correlation between the 2
19 cathods. A chi2 is performed for the 2 possibilities.
20 If one gets good chi2 (with respect to the fGhostChi2Cut parameter) and the
21 other wrong chi2, the ambiguity is solved
22 If both gets good or both bad chi2, no choice is made
23 By default the fGhostChi2Cut parameter is set to solve about 70% of ghost
24 problems with about 2% errors, with the current version of the code.
27 fGhostChi2Cut is in AliMUONClusterFinderVS, with setters and getters.
28 a fDebugLevel was also introduced to switch off some of the output.
29 When an ambiguity is detected and not solved, the fGhost word in
30 AliMUONRawCluster is set to 1 or 2, depending whether both charge chi2 are
32 a DumpIndex method was also added in AliMUONRawCluster to produce a printout
36 By default, the code makes ghost check. If you want previous behaviour,
37 put in MUONrawclusters the value of SetGhostChi2Cut to infinity (1e.6) is
40 Revision 1.18 2001/01/26 21:37:53 morsch
41 Use access functions to AliMUONDigit member data.
43 Revision 1.17 2001/01/23 18:58:19 hristov
44 Initialisation of some pointers
46 Revision 1.16 2000/12/21 23:27:30 morsch
47 Error in argument list of AddRawCluster corrected.
49 Revision 1.15 2000/12/21 22:14:38 morsch
50 Clean-up of coding rule violations.
52 Revision 1.14 2000/10/23 16:03:45 morsch
53 Correct z-position of all clusters created "on the flight".
55 Revision 1.13 2000/10/23 13:38:23 morsch
56 Set correct z-coordinate when cluster is split.
58 Revision 1.12 2000/10/18 11:42:06 morsch
59 - AliMUONRawCluster contains z-position.
60 - Some clean-up of useless print statements during initialisations.
62 Revision 1.11 2000/10/06 09:04:05 morsch
63 - Dummy z-arguments in GetPadI, SetHit, FirstPad replaced by real z-coordinate
64 to make code work with slat chambers (AM)
65 - Replace GetPadI calls with unchecked x,y coordinates by pad iterator calls wherever possible.
67 Revision 1.10 2000/10/03 13:51:57 egangler
68 Removal of useless dependencies via forward declarations
70 Revision 1.9 2000/10/02 16:58:29 egangler
71 Cleaning of the code :
74 -> some useless includes removed or replaced by "class" statement
76 Revision 1.8 2000/07/03 11:54:57 morsch
77 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
78 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
80 Revision 1.7 2000/06/28 15:16:35 morsch
81 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
82 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
83 framework. The changes should have no side effects (mostly dummy arguments).
84 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
85 of chambers with overlapping modules (MakePadHits, Disintegration).
87 Revision 1.6 2000/06/28 12:19:18 morsch
88 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
89 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
90 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
91 It requires two cathode planes. Small modifications in the code will make it usable for
92 one cathode plane and, hence, more general (for test beam data).
93 AliMUONClusterFinder is now obsolete.
95 Revision 1.5 2000/06/28 08:06:10 morsch
96 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
97 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
98 It also naturally takes care of the TMinuit instance.
100 Revision 1.4 2000/06/27 16:18:47 gosset
101 Finally correct implementation of xm, ym, ixm, iym sizes
102 when at least three local maxima on cathode 1 or on cathode 2
104 Revision 1.3 2000/06/22 14:02:45 morsch
105 Parameterised size of xm[], ym[], ixm[], iym[] correctly implemented (PH)
106 Some HP scope problems corrected (PH)
108 Revision 1.2 2000/06/15 07:58:48 morsch
109 Code from MUON-dev joined
111 Revision 1.1.2.3 2000/06/09 21:58:33 morsch
112 Most coding rule violations corrected.
114 Revision 1.1.2.2 2000/02/15 08:33:52 morsch
115 Error in calculation of contribution map for double clusters (Split method) corrected (A.M.)
116 Error in determination of track list for double cluster (FillCluster method) corrected (A.M.)
117 Revised and extended SplitByLocalMaxima method (Isabelle Chevrot):
118 - For clusters with more than 2 maxima on one of the cathode planes all valid
119 combinations of maxima on the two cathodes are preserved. The position of the maxima is
120 taken as the hit position.
121 - New FillCluster method with 2 arguments to find tracks associated to the clusters
122 defined above added. (Method destinction by argument list not very elegant in this case,
123 should be revides (A.M.)
124 - Bug in if-statement to handle maximum 1 maximum per plane corrected
125 - Two cluster per cathode but only 1 combination valid is handled.
126 - More rigerous treatment of 1-2 and 2-1 combinations of maxima.
130 #include "AliMUONClusterFinderVS.h"
131 #include "AliMUONDigit.h"
132 #include "AliMUONRawCluster.h"
133 #include "AliSegmentation.h"
134 #include "AliMUONResponse.h"
135 #include "AliMUONClusterInput.h"
136 #include "AliMUONHitMapA1.h"
145 #include <TPostScript.h>
150 #include <iostream.h>
152 //_____________________________________________________________________
153 // This function is minimized in the double-Mathieson fit
154 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
155 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
156 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
157 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag);
159 ClassImp(AliMUONClusterFinderVS)
161 AliMUONClusterFinderVS::AliMUONClusterFinderVS()
163 // Default constructor
164 fInput=AliMUONClusterInput::Instance();
167 fTrack[0]=fTrack[1]=-1;
168 fDebugLevel = 0; // make silent default
169 fGhostChi2Cut = 1e6; // nothing done by default
172 for(Int_t i=0; i<100; i++) {
173 for (Int_t j=0; j<2; j++) {
179 AliMUONClusterFinderVS::AliMUONClusterFinderVS(
180 const AliMUONClusterFinderVS & clusterFinder)
182 // Dummy copy Constructor
186 void AliMUONClusterFinderVS::Decluster(AliMUONRawCluster *cluster)
188 // Decluster by local maxima
189 SplitByLocalMaxima(cluster);
192 void AliMUONClusterFinderVS::SplitByLocalMaxima(AliMUONRawCluster *c)
194 // Split complex cluster by local maxima
197 fInput->SetCluster(c);
199 fMul[0]=c->fMultiplicity[0];
200 fMul[1]=c->fMultiplicity[1];
203 // dump digit information into arrays
208 for (cath=0; cath<2; cath++) {
210 for (i=0; i<fMul[cath]; i++)
213 fDig[i][cath]=fInput->Digit(cath, c->fIndexMap[i][cath]);
215 fIx[i][cath]= fDig[i][cath]->PadX();
216 fIy[i][cath]= fDig[i][cath]->PadY();
218 fQ[i][cath] = fDig[i][cath]->Signal();
219 // pad centre coordinates
221 GetPadC(fIx[i][cath], fIy[i][cath], fX[i][cath], fY[i][cath], fZ[i][cath]);
222 } // loop over cluster digits
223 } // loop over cathodes
229 // Initialise and perform mathieson fits
230 Float_t chi2, oldchi2;
231 // ++++++++++++++++++*************+++++++++++++++++++++
232 // (1) No more than one local maximum per cathode plane
233 // +++++++++++++++++++++++++++++++*************++++++++
234 if ((fNLocal[0]==1 && (fNLocal[1]==0 || fNLocal[1]==1)) ||
235 (fNLocal[0]==0 && fNLocal[1]==1)) {
236 // Perform combined single Mathieson fit
237 // Initial values for coordinates (x,y)
239 // One local maximum on cathodes 1 and 2 (X->cathode 2, Y->cathode 1)
240 if (fNLocal[0]==1 && fNLocal[1]==1) {
243 // One local maximum on cathode 1 (X,Y->cathode 1)
244 } else if (fNLocal[0]==1) {
247 // One local maximum on cathode 2 (X,Y->cathode 2)
253 fprintf(stderr,"\n cas (1) CombiSingleMathiesonFit(c)\n");
254 chi2=CombiSingleMathiesonFit(c);
255 // Int_t ndf = fgNbins[0]+fgNbins[1]-2;
256 // Float_t prob = TMath::Prob(Double_t(chi2),ndf);
257 // prob1->Fill(prob);
258 // chi2_1->Fill(chi2);
261 fprintf(stderr," chi2 %f ",chi2);
271 c->fX[0]=fSeg[0]->GetAnod(c->fX[0]);
272 c->fX[1]=fSeg[1]->GetAnod(c->fX[1]);
274 // If reasonable chi^2 add result to the list of rawclusters
277 // If not try combined double Mathieson Fit
279 fprintf(stderr," MAUVAIS CHI2 !!!\n");
280 if (fNLocal[0]==1 && fNLocal[1]==1) {
281 fXInit[0]=fX[fIndLocal[0][1]][1];
282 fYInit[0]=fY[fIndLocal[0][0]][0];
283 fXInit[1]=fX[fIndLocal[0][1]][1];
284 fYInit[1]=fY[fIndLocal[0][0]][0];
285 } else if (fNLocal[0]==1) {
286 fXInit[0]=fX[fIndLocal[0][0]][0];
287 fYInit[0]=fY[fIndLocal[0][0]][0];
288 fXInit[1]=fX[fIndLocal[0][0]][0];
289 fYInit[1]=fY[fIndLocal[0][0]][0];
291 fXInit[0]=fX[fIndLocal[0][1]][1];
292 fYInit[0]=fY[fIndLocal[0][1]][1];
293 fXInit[1]=fX[fIndLocal[0][1]][1];
294 fYInit[1]=fY[fIndLocal[0][1]][1];
297 // Initial value for charge ratios
301 fprintf(stderr,"\n cas (1) CombiDoubleMathiesonFit(c)\n");
302 chi2=CombiDoubleMathiesonFit(c);
303 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
304 // Float_t prob = TMath::Prob(chi2,ndf);
305 // prob2->Fill(prob);
306 // chi2_2->Fill(chi2);
308 // Was this any better ??
309 fprintf(stderr," Old and new chi2 %f %f ", oldchi2, chi2);
310 if (fFitStat!=0 && chi2>0 && (2.*chi2 < oldchi2)) {
311 fprintf(stderr," Split\n");
312 // Split cluster into two according to fit result
315 fprintf(stderr," Don't Split\n");
321 // +++++++++++++++++++++++++++++++++++++++
322 // (2) Two local maxima per cathode plane
323 // +++++++++++++++++++++++++++++++++++++++
324 } else if (fNLocal[0]==2 && fNLocal[1]==2) {
326 // Let's look for ghosts first
328 Float_t xm[4][2], ym[4][2];
329 Float_t dpx, dpy, dx, dy;
330 Int_t ixm[4][2], iym[4][2];
331 Int_t isec, im1, im2, ico;
333 // Form the 2x2 combinations
334 // 0-0, 0-1, 1-0, 1-1
336 for (im1=0; im1<2; im1++) {
337 for (im2=0; im2<2; im2++) {
338 xm[ico][0]=fX[fIndLocal[im1][0]][0];
339 ym[ico][0]=fY[fIndLocal[im1][0]][0];
340 xm[ico][1]=fX[fIndLocal[im2][1]][1];
341 ym[ico][1]=fY[fIndLocal[im2][1]][1];
343 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
344 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
345 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
346 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
350 // ico = 0 : first local maximum on cathodes 1 and 2
351 // ico = 1 : fisrt local maximum on cathode 1 and second on cathode 2
352 // ico = 2 : second local maximum on cathode 1 and first on cathode 1
353 // ico = 3 : second local maximum on cathodes 1 and 2
355 // Analyse the combinations and keep those that are possible !
356 // For each combination check consistency in x and y
359 Float_t dr[4] = {1.e4, 1.e4, 1.e4, 1.e4};
362 // In case of staggering maxima are displaced by exactly half the pad-size in y.
363 // We have to take into account the numerical precision in the consistency check;
366 for (ico=0; ico<4; ico++) {
367 accepted[ico]=kFALSE;
368 // cathode one: x-coordinate
369 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
370 dpx=fSeg[0]->Dpx(isec)/2.;
371 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
372 // cathode two: y-coordinate
373 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
374 dpy=fSeg[1]->Dpy(isec)/2.;
375 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
377 printf("\n %i %f %f %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy, dx, dpx );
378 if ((dx <= dpx) && (dy <= dpy+eps)) {
381 dr[ico] = TMath::Sqrt(dx*dx+dy*dy);
385 accepted[ico]=kFALSE;
388 printf("\n iacc= %d:\n", iacc);
390 if (accepted[0] && accepted[1]) {
391 if (dr[0] >= dr[1]) {
398 if (accepted[2] && accepted[3]) {
399 if (dr[2] >= dr[3]) {
406 // eliminate one candidate
410 for (ico=0; ico<4; ico++) {
411 if (accepted[ico] && dr[ico] > drmax) {
417 accepted[icobad] = kFALSE;
423 printf("\n iacc= %d:\n", iacc);
426 fprintf(stderr,"\n iacc=2: No problem ! \n");
427 } else if (iacc==4) {
428 fprintf(stderr,"\n iacc=4: Ok, but ghost problem !!! \n");
429 } else if (iacc==0) {
430 fprintf(stderr,"\n iacc=0: I don't know what to do with this !!!!!!!!! \n");
434 // Initial value for charge ratios
435 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
436 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
437 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
438 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
440 // ******* iacc = 0 *******
441 // No combinations found between the 2 cathodes
442 // We keep the center of gravity of the cluster
447 // ******* iacc = 1 *******
448 // Only one combination found between the 2 cathodes
450 // Initial values for the 2 maxima (x,y)
452 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
453 // 1 maximum is initialised with the other maximum of the first cathode
455 fprintf(stderr,"ico=0\n");
460 } else if (accepted[1]){
461 fprintf(stderr,"ico=1\n");
466 } else if (accepted[2]){
467 fprintf(stderr,"ico=2\n");
472 } else if (accepted[3]){
473 fprintf(stderr,"ico=3\n");
480 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
481 chi2=CombiDoubleMathiesonFit(c);
482 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
483 // Float_t prob = TMath::Prob(chi2,ndf);
484 // prob2->Fill(prob);
485 // chi2_2->Fill(chi2);
487 fprintf(stderr," chi2 %f\n",chi2);
489 // If reasonable chi^2 add result to the list of rawclusters
494 // 1 maximum is initialised with the maximum of the combination found (X->cathode 2, Y->cathode 1)
495 // 1 maximum is initialised with the other maximum of the second cathode
497 fprintf(stderr,"ico=0\n");
502 } else if (accepted[1]){
503 fprintf(stderr,"ico=1\n");
508 } else if (accepted[2]){
509 fprintf(stderr,"ico=2\n");
514 } else if (accepted[3]){
515 fprintf(stderr,"ico=3\n");
522 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
523 chi2=CombiDoubleMathiesonFit(c);
524 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
525 // Float_t prob = TMath::Prob(chi2,ndf);
526 // prob2->Fill(prob);
527 // chi2_2->Fill(chi2);
529 fprintf(stderr," chi2 %f\n",chi2);
531 // If reasonable chi^2 add result to the list of rawclusters
535 //We keep only the combination found (X->cathode 2, Y->cathode 1)
536 for (Int_t ico=0; ico<2; ico++) {
538 AliMUONRawCluster cnew;
540 for (cath=0; cath<2; cath++) {
541 cnew.fX[cath]=Float_t(xm[ico][1]);
542 cnew.fY[cath]=Float_t(ym[ico][0]);
543 cnew.fZ[cath]=fZPlane;
545 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
546 for (i=0; i<fMul[cath]; i++) {
547 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
548 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
550 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
551 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
552 FillCluster(&cnew,cath);
554 cnew.fClusterType=cnew.PhysicsContribution();
563 // ******* iacc = 2 *******
564 // Two combinations found between the 2 cathodes
566 // Was the same maximum taken twice
567 if ((accepted[0]&&accepted[1]) || (accepted[2]&&accepted[3])) {
568 fprintf(stderr,"\n Maximum taken twice !!!\n");
570 // Have a try !! with that
571 if (accepted[0]&&accepted[3]) {
583 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
584 chi2=CombiDoubleMathiesonFit(c);
585 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
586 // Float_t prob = TMath::Prob(chi2,ndf);
587 // prob2->Fill(prob);
588 // chi2_2->Fill(chi2);
592 // No ghosts ! No Problems ! - Perform one fit only !
593 if (accepted[0]&&accepted[3]) {
605 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
606 chi2=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(chi2);
612 fprintf(stderr," chi2 %f\n",chi2);
616 // ******* iacc = 4 *******
617 // Four combinations found between the 2 cathodes
619 } else if (iacc==4) {
620 // Perform fits for the two possibilities !!
621 // Accept if charges are compatible on both cathodes
622 // If none are compatible, keep everything
628 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
629 chi2=CombiDoubleMathiesonFit(c);
630 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
631 // Float_t prob = TMath::Prob(chi2,ndf);
632 // prob2->Fill(prob);
633 // chi2_2->Fill(chi2);
635 fprintf(stderr," chi2 %f\n",chi2);
636 // store results of fit and postpone decision
637 Double_t sXFit[2],sYFit[2],sQrFit[2];
639 for (Int_t i=0;i<2;i++) {
650 fprintf(stderr,"\n cas (2) CombiDoubleMathiesonFit(c)\n");
651 chi2=CombiDoubleMathiesonFit(c);
652 // ndf = fgNbins[0]+fgNbins[1]-6;
653 // prob = TMath::Prob(chi2,ndf);
654 // prob2->Fill(prob);
655 // chi2_2->Fill(chi2);
657 fprintf(stderr," chi2 %f\n",chi2);
658 // We have all informations to perform the decision
659 // Compute the chi2 for the 2 possibilities
660 Float_t chi2fi,chi2si,chi2f,chi2s;
662 chi2f = (TMath::Log(fInput->TotalCharge(0)*fQrFit[0]
663 / (fInput->TotalCharge(1)*fQrFit[1]) )
664 / fInput->Response()->ChargeCorrel() );
666 chi2fi = (TMath::Log(fInput->TotalCharge(0)*(1-fQrFit[0])
667 / (fInput->TotalCharge(1)*(1-fQrFit[1])) )
668 / fInput->Response()->ChargeCorrel() );
669 chi2f += chi2fi*chi2fi;
671 chi2s = (TMath::Log(fInput->TotalCharge(0)*sQrFit[0]
672 / (fInput->TotalCharge(1)*sQrFit[1]) )
673 / fInput->Response()->ChargeCorrel() );
675 chi2si = (TMath::Log(fInput->TotalCharge(0)*(1-sQrFit[0])
676 / (fInput->TotalCharge(1)*(1-sQrFit[1])) )
677 / fInput->Response()->ChargeCorrel() );
678 chi2s += chi2si*chi2si;
680 // usefull to store the charge matching chi2 in the cluster
681 // fChi2[0]=sChi2[1]=chi2f;
682 // fChi2[1]=sChi2[0]=chi2s;
684 if (chi2f<=fGhostChi2Cut && chi2s<=fGhostChi2Cut)
686 if (chi2f>fGhostChi2Cut && chi2s>fGhostChi2Cut) {
692 if (chi2f<=fGhostChi2Cut)
694 if (chi2s<=fGhostChi2Cut) {
695 // retreive saved values
696 for (Int_t i=0;i<2;i++) {
707 } else if (fNLocal[0]==2 && fNLocal[1]==1) {
708 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
709 // (3) Two local maxima on cathode 1 and one maximum on cathode 2
710 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
712 Float_t xm[4][2], ym[4][2];
713 Float_t dpx, dpy, dx, dy;
714 Int_t ixm[4][2], iym[4][2];
715 Int_t isec, im1, ico;
717 // Form the 2x2 combinations
718 // 0-0, 0-1, 1-0, 1-1
720 for (im1=0; im1<2; im1++) {
721 xm[ico][0]=fX[fIndLocal[im1][0]][0];
722 ym[ico][0]=fY[fIndLocal[im1][0]][0];
723 xm[ico][1]=fX[fIndLocal[0][1]][1];
724 ym[ico][1]=fY[fIndLocal[0][1]][1];
726 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
727 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
728 ixm[ico][1]=fIx[fIndLocal[0][1]][1];
729 iym[ico][1]=fIy[fIndLocal[0][1]][1];
732 // ico = 0 : first local maximum on cathodes 1 and 2
733 // ico = 1 : second local maximum on cathode 1 and first on cathode 2
735 // Analyse the combinations and keep those that are possible !
736 // For each combination check consistency in x and y
740 // In case of staggering maxima are displaced by exactly half the pad-size in y.
741 // We have to take into account the numerical precision in the consistency check;
744 for (ico=0; ico<2; ico++) {
745 accepted[ico]=kFALSE;
746 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
747 dpx=fSeg[0]->Dpx(isec)/2.;
748 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
749 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
750 dpy=fSeg[1]->Dpy(isec)/2.;
751 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
753 printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
754 if ((dx <= dpx) && (dy <= dpy+eps)) {
760 accepted[ico]=kFALSE;
768 // Initial value for charge ratios
769 fQrInit[0]=Float_t(fQ[fIndLocal[0][0]][0])/
770 Float_t(fQ[fIndLocal[0][0]][0]+fQ[fIndLocal[1][0]][0]);
771 fQrInit[1]=fQrInit[0];
773 if (accepted[0] && accepted[1]) {
775 fXInit[0]=0.5*(xm[0][1]+xm[0][0]);
777 fXInit[1]=0.5*(xm[0][1]+xm[1][0]);
781 chi23=CombiDoubleMathiesonFit(c);
790 } else if (accepted[0]) {
795 chi21=CombiDoubleMathiesonFit(c);
796 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
797 // Float_t prob = TMath::Prob(chi2,ndf);
798 // prob2->Fill(prob);
799 // chi2_2->Fill(chi21);
801 fprintf(stderr," chi2 %f\n",chi21);
802 if (chi21<10) Split(c);
803 } else if (accepted[1]) {
808 chi22=CombiDoubleMathiesonFit(c);
809 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
810 // Float_t prob = TMath::Prob(chi2,ndf);
811 // prob2->Fill(prob);
812 // chi2_2->Fill(chi22);
814 fprintf(stderr," chi2 %f\n",chi22);
815 if (chi22<10) Split(c);
818 if (chi21 > 10 && chi22 > 10) {
819 // We keep only the combination found (X->cathode 2, Y->cathode 1)
820 for (Int_t ico=0; ico<2; ico++) {
822 AliMUONRawCluster cnew;
824 for (cath=0; cath<2; cath++) {
825 cnew.fX[cath]=Float_t(xm[ico][1]);
826 cnew.fY[cath]=Float_t(ym[ico][0]);
827 cnew.fZ[cath]=fZPlane;
828 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
829 for (i=0; i<fMul[cath]; i++) {
830 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
831 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
833 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
834 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
835 FillCluster(&cnew,cath);
837 cnew.fClusterType=cnew.PhysicsContribution();
844 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
845 // (3') One local maximum on cathode 1 and two maxima on cathode 2
846 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
847 } else if (fNLocal[0]==1 && fNLocal[1]==2) {
848 Float_t xm[4][2], ym[4][2];
849 Float_t dpx, dpy, dx, dy;
850 Int_t ixm[4][2], iym[4][2];
851 Int_t isec, im1, ico;
853 // Form the 2x2 combinations
854 // 0-0, 0-1, 1-0, 1-1
856 for (im1=0; im1<2; im1++) {
857 xm[ico][0]=fX[fIndLocal[0][0]][0];
858 ym[ico][0]=fY[fIndLocal[0][0]][0];
859 xm[ico][1]=fX[fIndLocal[im1][1]][1];
860 ym[ico][1]=fY[fIndLocal[im1][1]][1];
862 ixm[ico][0]=fIx[fIndLocal[0][0]][0];
863 iym[ico][0]=fIy[fIndLocal[0][0]][0];
864 ixm[ico][1]=fIx[fIndLocal[im1][1]][1];
865 iym[ico][1]=fIy[fIndLocal[im1][1]][1];
868 // ico = 0 : first local maximum on cathodes 1 and 2
869 // ico = 1 : first local maximum on cathode 1 and second on cathode 2
871 // Analyse the combinations and keep those that are possible !
872 // For each combination check consistency in x and y
876 // In case of staggering maxima are displaced by exactly half the pad-size in y.
877 // We have to take into account the numerical precision in the consistency check;
881 for (ico=0; ico<2; ico++) {
882 accepted[ico]=kFALSE;
883 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
884 dpx=fSeg[0]->Dpx(isec)/2.;
885 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
886 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
887 dpy=fSeg[1]->Dpy(isec)/2.;
888 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
890 printf("\n %i %f %f %f %f \n", ico, ym[ico][0], ym[ico][1], dy, dpy );
891 if ((dx <= dpx) && (dy <= dpy+eps)) {
894 fprintf(stderr,"ico %d\n",ico);
898 accepted[ico]=kFALSE;
906 fQrInit[1]=Float_t(fQ[fIndLocal[0][1]][1])/
907 Float_t(fQ[fIndLocal[0][1]][1]+fQ[fIndLocal[1][1]][1]);
909 fQrInit[0]=fQrInit[1];
912 if (accepted[0] && accepted[1]) {
914 fYInit[0]=0.5*(ym[0][0]+ym[0][1]);
916 fYInit[1]=0.5*(ym[0][0]+ym[1][1]);
919 chi23=CombiDoubleMathiesonFit(c);
928 } else if (accepted[0]) {
933 chi21=CombiDoubleMathiesonFit(c);
934 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
935 // Float_t prob = TMath::Prob(chi2,ndf);
936 // prob2->Fill(prob);
937 // chi2_2->Fill(chi21);
939 fprintf(stderr," chi2 %f\n",chi21);
940 if (chi21<10) Split(c);
941 } else if (accepted[1]) {
946 chi22=CombiDoubleMathiesonFit(c);
947 // Int_t ndf = fgNbins[0]+fgNbins[1]-6;
948 // Float_t prob = TMath::Prob(chi2,ndf);
949 // prob2->Fill(prob);
950 // chi2_2->Fill(chi22);
952 fprintf(stderr," chi2 %f\n",chi22);
953 if (chi22<10) Split(c);
956 if (chi21 > 10 && chi22 > 10 && chi23 > 10) {
957 //We keep only the combination found (X->cathode 2, Y->cathode 1)
958 for (Int_t ico=0; ico<2; ico++) {
960 AliMUONRawCluster cnew;
962 for (cath=0; cath<2; cath++) {
963 cnew.fX[cath]=Float_t(xm[ico][1]);
964 cnew.fY[cath]=Float_t(ym[ico][0]);
965 cnew.fZ[cath]=fZPlane;
966 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
967 for (i=0; i<fMul[cath]; i++) {
968 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
969 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
971 fprintf(stderr,"\nRawCluster %d cath %d\n",ico,cath);
972 fprintf(stderr,"mult_av %d\n",c->fMultiplicity[cath]);
973 FillCluster(&cnew,cath);
975 cnew.fClusterType=cnew.PhysicsContribution();
982 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
983 // (4) At least three local maxima on cathode 1 or on cathode 2
984 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
985 } else if (fNLocal[0]>2 || fNLocal[1]>2) {
986 Int_t param = fNLocal[0]*fNLocal[1];
989 Float_t ** xm = new Float_t * [param];
990 for (ii=0; ii<param; ii++) xm[ii]=new Float_t [2];
991 Float_t ** ym = new Float_t * [param];
992 for (ii=0; ii<param; ii++) ym[ii]=new Float_t [2];
993 Int_t ** ixm = new Int_t * [param];
994 for (ii=0; ii<param; ii++) ixm[ii]=new Int_t [2];
995 Int_t ** iym = new Int_t * [param];
996 for (ii=0; ii<param; ii++) iym[ii]=new Int_t [2];
999 Float_t dpx, dpy, dx, dy;
1002 for (Int_t im1=0; im1<fNLocal[0]; im1++) {
1003 for (Int_t im2=0; im2<fNLocal[1]; im2++) {
1004 xm[ico][0]=fX[fIndLocal[im1][0]][0];
1005 ym[ico][0]=fY[fIndLocal[im1][0]][0];
1006 xm[ico][1]=fX[fIndLocal[im2][1]][1];
1007 ym[ico][1]=fY[fIndLocal[im2][1]][1];
1009 ixm[ico][0]=fIx[fIndLocal[im1][0]][0];
1010 iym[ico][0]=fIy[fIndLocal[im1][0]][0];
1011 ixm[ico][1]=fIx[fIndLocal[im2][1]][1];
1012 iym[ico][1]=fIy[fIndLocal[im2][1]][1];
1019 fprintf(stderr,"nIco %d\n",nIco);
1020 for (ico=0; ico<nIco; ico++) {
1022 fprintf(stderr,"ico = %d\n",ico);
1023 isec=fSeg[0]->Sector(ixm[ico][0], iym[ico][0]);
1024 dpx=fSeg[0]->Dpx(isec)/2.;
1025 dx=TMath::Abs(xm[ico][0]-xm[ico][1]);
1026 isec=fSeg[1]->Sector(ixm[ico][1], iym[ico][1]);
1027 dpy=fSeg[1]->Dpy(isec)/2.;
1028 dy=TMath::Abs(ym[ico][0]-ym[ico][1]);
1030 fprintf(stderr,"dx %f dpx %f dy %f dpy %f\n",dx,dpx,dy,dpy);
1031 fprintf(stderr," X %f Y %f\n",xm[ico][1],ym[ico][0]);
1033 if ((dx <= dpx) && (dy <= dpy)) {
1035 fprintf(stderr,"ok\n");
1037 AliMUONRawCluster cnew;
1038 for (cath=0; cath<2; cath++) {
1039 cnew.fX[cath]=Float_t(xm[ico][1]);
1040 cnew.fY[cath]=Float_t(ym[ico][0]);
1041 cnew.fZ[cath]=fZPlane;
1042 cnew.fMultiplicity[cath]=c->fMultiplicity[cath];
1043 for (i=0; i<fMul[cath]; i++) {
1044 cnew.fIndexMap[i][cath]=c->fIndexMap[i][cath];
1045 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
1047 FillCluster(&cnew,cath);
1049 cnew.fClusterType=cnew.PhysicsContribution();
1050 AddRawCluster(cnew);
1061 void AliMUONClusterFinderVS::FindLocalMaxima(AliMUONRawCluster* c)
1063 // Find all local maxima of a cluster
1065 printf("\n Find Local maxima !");
1069 Int_t cath, cath1; // loops over cathodes
1070 Int_t i; // loops over digits
1071 Int_t j; // loops over cathodes
1073 // Find local maxima
1075 // counters for number of local maxima
1076 fNLocal[0]=fNLocal[1]=0;
1077 // flags digits as local maximum
1078 Bool_t isLocal[100][2];
1079 for (i=0; i<100;i++) {
1080 isLocal[i][0]=isLocal[i][1]=kFALSE;
1082 // number of next neighbours and arrays to store them
1085 // loop over cathodes
1086 for (cath=0; cath<2; cath++) {
1087 // loop over cluster digits
1088 for (i=0; i<fMul[cath]; i++) {
1089 // get neighbours for that digit and assume that it is local maximum
1090 fSeg[cath]->Neighbours(fIx[i][cath], fIy[i][cath], &nn, x, y);
1091 isLocal[i][cath]=kTRUE;
1092 Int_t isec= fSeg[cath]->Sector(fIx[i][cath], fIy[i][cath]);
1093 Float_t a0 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
1094 // loop over next neighbours, if at least one neighbour has higher charger assumption
1095 // digit is not local maximum
1096 for (j=0; j<nn; j++) {
1097 if (fHitMap[cath]->TestHit(x[j], y[j])==kEmpty) continue;
1098 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(x[j], y[j]);
1099 isec=fSeg[cath]->Sector(x[j], y[j]);
1100 Float_t a1 = fSeg[cath]->Dpx(isec)*fSeg[cath]->Dpy(isec);
1101 if (digt->Signal()/a1 > fQ[i][cath]/a0) {
1102 isLocal[i][cath]=kFALSE;
1105 // handle special case of neighbouring pads with equal signal
1106 } else if (digt->Signal() == fQ[i][cath]) {
1107 if (fNLocal[cath]>0) {
1108 for (Int_t k=0; k<fNLocal[cath]; k++) {
1109 if (x[j]==fIx[fIndLocal[k][cath]][cath]
1110 && y[j]==fIy[fIndLocal[k][cath]][cath])
1112 isLocal[i][cath]=kFALSE;
1114 } // loop over local maxima
1115 } // are there already local maxima
1117 } // loop over next neighbours
1118 if (isLocal[i][cath]) {
1119 fIndLocal[fNLocal[cath]][cath]=i;
1122 } // loop over all digits
1123 } // loop over cathodes
1126 printf("\n Found %d %d %d %d local Maxima\n",
1127 fNLocal[0], fNLocal[1], fMul[0], fMul[1]);
1128 fprintf(stderr,"\n Cathode 1 local Maxima %d Multiplicite %d\n",fNLocal[0], fMul[0]);
1129 fprintf(stderr," Cathode 2 local Maxima %d Multiplicite %d\n",fNLocal[1], fMul[1]);
1135 if (fNLocal[1]==2 && (fNLocal[0]==1 || fNLocal[0]==0)) {
1136 Int_t iback=fNLocal[0];
1138 // Two local maxima on cathode 2 and one maximum on cathode 1
1139 // Look for local maxima considering up and down neighbours on the 1st cathode only
1141 // Loop over cluster digits
1145 for (i=0; i<fMul[cath]; i++) {
1146 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
1147 dpy=fSeg[cath]->Dpy(isec);
1148 dpx=fSeg[cath]->Dpx(isec);
1149 if (isLocal[i][cath]) continue;
1150 // Pad position should be consistent with position of local maxima on the opposite cathode
1151 if ((TMath::Abs(fX[i][cath]-fX[fIndLocal[0][cath1]][cath1]) > dpx/2.) &&
1152 (TMath::Abs(fX[i][cath]-fX[fIndLocal[1][cath1]][cath1]) > dpx/2.))
1155 // get neighbours for that digit and assume that it is local maximum
1156 isLocal[i][cath]=kTRUE;
1157 // compare signal to that on the two neighbours on the left and on the right
1158 // iNN counts the number of neighbours with signal, it should be 1 or 2
1162 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, 0., dpy);
1168 ix = fSeg[cath]->Ix();
1169 iy = fSeg[cath]->Iy();
1170 // skip the current pad
1171 if (iy == fIy[i][cath]) continue;
1173 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
1175 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
1176 if (digt->Signal() > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1178 } // Loop over pad neighbours in y
1179 if (isLocal[i][cath] && iNN>0) {
1180 fIndLocal[fNLocal[cath]][cath]=i;
1183 } // loop over all digits
1184 // if one additional maximum has been found we are happy
1185 // if more maxima have been found restore the previous situation
1188 "\n New search gives %d local maxima for cathode 1 \n",
1191 " %d local maxima for cathode 2 \n",
1194 if (fNLocal[cath]>2) {
1195 fNLocal[cath]=iback;
1198 } // 1,2 local maxima
1200 if (fNLocal[0]==2 && (fNLocal[1]==1 || fNLocal[1]==0)) {
1201 Int_t iback=fNLocal[1];
1203 // Two local maxima on cathode 1 and one maximum on cathode 2
1204 // Look for local maxima considering left and right neighbours on the 2nd cathode only
1207 Float_t eps = 1.e-5;
1210 // Loop over cluster digits
1211 for (i=0; i<fMul[cath]; i++) {
1212 isec=fSeg[cath]->Sector(fIx[i][cath],fIy[i][cath]);
1213 dpx=fSeg[cath]->Dpx(isec);
1214 dpy=fSeg[cath]->Dpy(isec);
1215 if (isLocal[i][cath]) continue;
1216 // Pad position should be consistent with position of local maxima on the opposite cathode
1217 if ((TMath::Abs(fY[i][cath]-fY[fIndLocal[0][cath1]][cath1]) > dpy/2.+eps) &&
1218 (TMath::Abs(fY[i][cath]-fY[fIndLocal[1][cath1]][cath1]) > dpy/2.+eps))
1222 // get neighbours for that digit and assume that it is local maximum
1223 isLocal[i][cath]=kTRUE;
1224 // compare signal to that on the two neighbours on the left and on the right
1226 // iNN counts the number of neighbours with signal, it should be 1 or 2
1229 ->FirstPad(fX[i][cath], fY[i][cath], fZPlane, dpx, 0.);
1236 ix = fSeg[cath]->Ix();
1237 iy = fSeg[cath]->Iy();
1239 // skip the current pad
1240 if (ix == fIx[i][cath]) continue;
1242 if (fHitMap[cath]->TestHit(ix, iy)!=kEmpty) {
1244 digt=(AliMUONDigit*) fHitMap[cath]->GetHit(ix,iy);
1245 if (digt->Signal() > fQ[i][cath]) isLocal[i][cath]=kFALSE;
1247 } // Loop over pad neighbours in x
1248 if (isLocal[i][cath] && iNN>0) {
1249 fIndLocal[fNLocal[cath]][cath]=i;
1252 } // loop over all digits
1253 // if one additional maximum has been found we are happy
1254 // if more maxima have been found restore the previous situation
1256 fprintf(stderr,"\n New search gives %d local maxima for cathode 1 \n",fNLocal[0]);
1257 fprintf(stderr,"\n %d local maxima for cathode 2 \n",fNLocal[1]);
1258 printf("\n New search gives %d %d \n",fNLocal[0],fNLocal[1]);
1260 if (fNLocal[cath]>2) {
1261 fNLocal[cath]=iback;
1263 } // 2,1 local maxima
1267 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t flag, Int_t cath)
1270 // Completes cluster information starting from list of digits
1277 c->fPeakSignal[cath]=c->fPeakSignal[0];
1279 c->fPeakSignal[cath]=0;
1290 fprintf(stderr,"\n fPeakSignal %d\n",c->fPeakSignal[cath]);
1291 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1293 dig= fInput->Digit(cath,c->fIndexMap[i][cath]);
1294 ix=dig->PadX()+c->fOffsetMap[i][cath];
1296 Int_t q=dig->Signal();
1297 if (!flag) q=Int_t(q*c->fContMap[i][cath]);
1298 // fprintf(stderr,"q %d c->fPeakSignal[ %d ] %d\n",q,cath,c->fPeakSignal[cath]);
1299 if (dig->Physics() >= dig->Signal()) {
1300 c->fPhysicsMap[i]=2;
1301 } else if (dig->Physics() == 0) {
1302 c->fPhysicsMap[i]=0;
1303 } else c->fPhysicsMap[i]=1;
1307 fprintf(stderr,"q %d c->fPeakSignal[cath] %d\n",q,c->fPeakSignal[cath]);
1308 // peak signal and track list
1309 if (q>c->fPeakSignal[cath]) {
1310 c->fPeakSignal[cath]=q;
1311 c->fTracks[0]=dig->Hit();
1312 c->fTracks[1]=dig->Track(0);
1313 c->fTracks[2]=dig->Track(1);
1314 // fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->fHit,dig->fTracks[0]);
1318 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1323 } // loop over digits
1325 fprintf(stderr," fin du cluster c\n");
1329 c->fX[cath]/=c->fQ[cath];
1331 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1332 c->fY[cath]/=c->fQ[cath];
1334 // apply correction to the coordinate along the anode wire
1338 fSeg[cath]->GetPadI(x, y, fZPlane, ix, iy);
1339 fSeg[cath]->GetPadC(ix, iy, x, y, z);
1340 Int_t isec=fSeg[cath]->Sector(ix,iy);
1341 TF1* cogCorr = fSeg[cath]->CorrFunc(isec-1);
1344 Float_t yOnPad=(c->fY[cath]-y)/fSeg[cath]->Dpy(isec);
1345 c->fY[cath]=c->fY[cath]-cogCorr->Eval(yOnPad, 0, 0);
1350 void AliMUONClusterFinderVS::FillCluster(AliMUONRawCluster* c, Int_t cath)
1353 // Completes cluster information starting from list of digits
1363 Float_t xpad, ypad, zpad;
1366 for (Int_t i=0; i<c->fMultiplicity[cath]; i++)
1368 dig = fInput->Digit(cath,c->fIndexMap[i][cath]);
1370 GetPadC(dig->PadX(),dig->PadY(),xpad,ypad, zpad);
1372 fprintf(stderr,"x %f y %f cx %f cy %f\n",xpad,ypad,c->fX[0],c->fY[0]);
1373 dx = xpad - c->fX[0];
1374 dy = ypad - c->fY[0];
1375 dr = TMath::Sqrt(dx*dx+dy*dy);
1380 fprintf(stderr," dr %f\n",dr);
1381 Int_t q=dig->Signal();
1382 if (dig->Physics() >= dig->Signal()) {
1383 c->fPhysicsMap[i]=2;
1384 } else if (dig->Physics() == 0) {
1385 c->fPhysicsMap[i]=0;
1386 } else c->fPhysicsMap[i]=1;
1387 c->fPeakSignal[cath]=q;
1388 c->fTracks[0]=dig->Hit();
1389 c->fTracks[1]=dig->Track(0);
1390 c->fTracks[2]=dig->Track(1);
1392 fprintf(stderr," c->fTracks[0] %d c->fTracks[1] %d\n",dig->Hit(),
1396 } // loop over digits
1398 // apply correction to the coordinate along the anode wire
1400 c->fX[cath]=fSeg[cath]->GetAnod(c->fX[cath]);
1403 void AliMUONClusterFinderVS::FindCluster(Int_t i, Int_t j, Int_t cath, AliMUONRawCluster &c){
1407 // Find a super cluster on both cathodes
1410 // Add i,j as element of the cluster
1413 Int_t idx = fHitMap[cath]->GetHitIndex(i,j);
1414 AliMUONDigit* dig = (AliMUONDigit*) fHitMap[cath]->GetHit(i,j);
1415 Int_t q=dig->Signal();
1416 Int_t theX=dig->PadX();
1417 Int_t theY=dig->PadY();
1419 if (q > TMath::Abs(c.fPeakSignal[0]) && q > TMath::Abs(c.fPeakSignal[1])) {
1420 c.fPeakSignal[cath]=q;
1421 c.fTracks[0]=dig->Hit();
1422 c.fTracks[1]=dig->Track(0);
1423 c.fTracks[2]=dig->Track(1);
1427 // Make sure that list of digits is ordered
1429 Int_t mu=c.fMultiplicity[cath];
1430 c.fIndexMap[mu][cath]=idx;
1432 if (dig->Physics() >= dig->Signal()) {
1433 c.fPhysicsMap[mu]=2;
1434 } else if (dig->Physics() == 0) {
1435 c.fPhysicsMap[mu]=0;
1436 } else c.fPhysicsMap[mu]=1;
1440 for (Int_t ind = mu-1; ind >= 0; ind--) {
1441 Int_t ist=(c.fIndexMap)[ind][cath];
1442 Int_t ql=fInput->Digit(cath, ist)->Signal();
1443 Int_t ix=fInput->Digit(cath, ist)->PadX();
1444 Int_t iy=fInput->Digit(cath, ist)->PadY();
1446 if (q>ql || (q==ql && theX > ix && theY < iy)) {
1447 c.fIndexMap[ind][cath]=idx;
1448 c.fIndexMap[ind+1][cath]=ist;
1456 c.fMultiplicity[cath]++;
1457 if (c.fMultiplicity[cath] >= 50 ) {
1458 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity[0]);
1459 c.fMultiplicity[cath]=49;
1462 // Prepare center of gravity calculation
1464 fSeg[cath]->GetPadC(i, j, x, y, z);
1470 // Flag hit as "taken"
1471 fHitMap[cath]->FlagHit(i,j);
1473 // Now look recursively for all neighbours and pad hit on opposite cathode
1475 // Loop over neighbours
1479 Int_t xList[10], yList[10];
1480 fSeg[cath]->Neighbours(i,j,&nn,xList,yList);
1481 for (Int_t in=0; in<nn; in++) {
1485 if (fHitMap[cath]->TestHit(ix,iy)==kUnused) {
1487 printf("\n Neighbours %d %d %d", cath, ix, iy);
1488 FindCluster(ix, iy, cath, c);
1493 Int_t iXopp[50], iYopp[50];
1495 // Neighbours on opposite cathode
1496 // Take into account that several pads can overlap with the present pad
1497 Int_t isec=fSeg[cath]->Sector(i,j);
1503 dx = (fSeg[cath]->Dpx(isec))/2.;
1508 dy = (fSeg[cath]->Dpy(isec))/2;
1510 // loop over pad neighbours on opposite cathode
1511 for (fSeg[iop]->FirstPad(x, y, fZPlane, dx, dy);
1512 fSeg[iop]->MorePads();
1513 fSeg[iop]->NextPad())
1516 ix = fSeg[iop]->Ix(); iy = fSeg[iop]->Iy();
1517 if (fDebugLevel > 1)
1518 printf("\n ix, iy: %f %f %f %d %d %d", x,y,z,ix, iy, fSector);
1519 if (fHitMap[iop]->TestHit(ix,iy)==kUnused){
1522 if (fDebugLevel > 1)
1523 printf("\n Opposite %d %d %d", iop, ix, iy);
1526 } // Loop over pad neighbours
1527 // This had to go outside the loop since recursive calls inside the iterator are not possible
1530 for (jopp=0; jopp<nOpp; jopp++) {
1531 if (fHitMap[iop]->TestHit(iXopp[jopp],iYopp[jopp]) == kUnused)
1532 FindCluster(iXopp[jopp], iYopp[jopp], iop, c);
1536 //_____________________________________________________________________________
1538 void AliMUONClusterFinderVS::FindRawClusters()
1541 // MUON cluster finder from digits -- finds neighbours on both cathodes and
1542 // fills the tree with raw clusters
1545 // Return if no input datad available
1546 if (!fInput->NDigits(0) && !fInput->NDigits(1)) return;
1548 fSeg[0] = fInput->Segmentation(0);
1549 fSeg[1] = fInput->Segmentation(1);
1551 fHitMap[0] = new AliMUONHitMapA1(fSeg[0], fInput->Digits(0));
1552 fHitMap[1] = new AliMUONHitMapA1(fSeg[1], fInput->Digits(1));
1560 fHitMap[0]->FillHits();
1561 fHitMap[1]->FillHits();
1563 // Outer Loop over Cathodes
1564 for (cath=0; cath<2; cath++) {
1565 for (ndig=0; ndig<fInput->NDigits(cath); ndig++) {
1566 dig = fInput->Digit(cath, ndig);
1567 Int_t i=dig->PadX();
1568 Int_t j=dig->PadY();
1569 if (fHitMap[cath]->TestHit(i,j)==kUsed ||fHitMap[0]->TestHit(i,j)==kEmpty) {
1574 fprintf(stderr,"\n CATHODE %d CLUSTER %d\n",cath,ncls);
1575 AliMUONRawCluster c;
1576 c.fMultiplicity[0]=0;
1577 c.fMultiplicity[1]=0;
1578 c.fPeakSignal[cath]=dig->Signal();
1579 c.fTracks[0]=dig->Hit();
1580 c.fTracks[1]=dig->Track(0);
1581 c.fTracks[2]=dig->Track(1);
1582 // tag the beginning of cluster list in a raw cluster
1585 fSeg[cath]->GetPadC(i,j,xcu, ycu, fZPlane);
1586 fSector= fSeg[cath]->Sector(i,j)/100;
1588 printf("\n New Seed %d %d ", i,j);
1590 FindCluster(i,j,cath,c);
1591 // ^^^^^^^^^^^^^^^^^^^^^^^^
1592 // center of gravity
1595 c.fX[0]=fSeg[0]->GetAnod(c.fX[0]);
1599 c.fX[1]=fSeg[0]->GetAnod(c.fX[1]);
1606 fprintf(stderr,"\n Cathode 1 multiplicite %d X(CG) %f Y(CG) %f\n",
1607 c.fMultiplicity[0],c.fX[0],c.fY[0]);
1608 fprintf(stderr," Cathode 2 multiplicite %d X(CG) %f Y(CG) %f\n",
1609 c.fMultiplicity[1],c.fX[1],c.fY[1]);
1611 // Analyse cluster and decluster if necessary
1614 c.fNcluster[1]=fNRawClusters;
1615 c.fClusterType=c.PhysicsContribution();
1622 // reset Cluster object
1623 { // begin local scope
1624 for (int k=0;k<c.fMultiplicity[0];k++) c.fIndexMap[k][0]=0;
1625 } // end local scope
1627 { // begin local scope
1628 for (int k=0;k<c.fMultiplicity[1];k++) c.fIndexMap[k][1]=0;
1629 } // end local scope
1631 c.fMultiplicity[0]=c.fMultiplicity[0]=0;
1635 } // end loop cathodes
1640 Float_t AliMUONClusterFinderVS::SingleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1642 // Performs a single Mathieson fit on one cathode
1644 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1646 clusterInput.Fitter()->SetFCN(fcnS1);
1647 clusterInput.Fitter()->mninit(2,10,7);
1648 Double_t arglist[20];
1651 // Set starting values
1652 static Double_t vstart[2];
1657 // lower and upper limits
1658 static Double_t lower[2], upper[2];
1660 fSeg[cath]->GetPadI(c->fX[cath], c->fY[cath], fZPlane, ix, iy);
1661 Int_t isec=fSeg[cath]->Sector(ix, iy);
1662 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec)/2;
1663 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec)/2;
1665 upper[0]=lower[0]+fSeg[cath]->Dpx(isec);
1666 upper[1]=lower[1]+fSeg[cath]->Dpy(isec);
1669 static Double_t step[2]={0.0005, 0.0005};
1671 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1672 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1673 // ready for minimisation
1674 clusterInput.Fitter()->SetPrintLevel(-1+fDebugLevel);
1676 clusterInput.Fitter()->mnexcm("SET NOW", arglist, 0, ierflag);
1677 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1681 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1682 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1683 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1684 Double_t fmin, fedm, errdef;
1685 Int_t npari, nparx, istat;
1687 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1691 // Get fitted parameters
1692 Double_t xrec, yrec;
1694 Double_t epxz, b1, b2;
1696 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1697 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1703 Float_t AliMUONClusterFinderVS::CombiSingleMathiesonFit(AliMUONRawCluster *c)
1705 // Perform combined Mathieson fit on both cathode planes
1707 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1708 clusterInput.Fitter()->SetFCN(fcnCombiS1);
1709 clusterInput.Fitter()->mninit(2,10,7);
1710 Double_t arglist[20];
1713 static Double_t vstart[2];
1714 vstart[0]=fXInit[0];
1715 vstart[1]=fYInit[0];
1718 // lower and upper limits
1719 static Float_t lower[2], upper[2];
1721 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1722 isec=fSeg[0]->Sector(ix, iy);
1723 Float_t dpy=fSeg[0]->Dpy(isec);
1724 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1725 isec=fSeg[1]->Sector(ix, iy);
1726 Float_t dpx=fSeg[1]->Dpx(isec);
1729 Float_t xdum, ydum, zdum;
1731 // Find save upper and lower limits
1735 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1736 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1738 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1739 fSeg[1]->GetPadC(ix,iy, upper[0], ydum, zdum);
1740 if (icount ==0) lower[0]=upper[0];
1744 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1748 printf("\n single y %f %f", fXInit[0], fYInit[0]);
1750 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1751 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1753 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1754 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1755 if (icount ==0) lower[1]=upper[1];
1758 printf("\n upper lower %d %f %f", icount, upper[1], lower[1]);
1761 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1764 static Double_t step[2]={0.00001, 0.0001};
1766 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1767 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1768 // ready for minimisation
1769 clusterInput.Fitter()->SetPrintLevel(-1+fDebugLevel);
1771 clusterInput.Fitter()->mnexcm("SET NOW", arglist, 0, ierflag);
1772 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1776 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1777 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1778 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1779 Double_t fmin, fedm, errdef;
1780 Int_t npari, nparx, istat;
1782 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1786 // Get fitted parameters
1787 Double_t xrec, yrec;
1789 Double_t epxz, b1, b2;
1791 clusterInput.Fitter()->mnpout(0, chname, xrec, epxz, b1, b2, ierflg);
1792 clusterInput.Fitter()->mnpout(1, chname, yrec, epxz, b1, b2, ierflg);
1798 Bool_t AliMUONClusterFinderVS::DoubleMathiesonFit(AliMUONRawCluster *c, Int_t cath)
1800 // Performs a double Mathieson fit on one cathode
1804 // Initialise global variables for fit
1805 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1806 clusterInput.Fitter()->SetFCN(fcnS2);
1807 clusterInput.Fitter()->mninit(5,10,7);
1808 Double_t arglist[20];
1811 // Set starting values
1812 static Double_t vstart[5];
1813 vstart[0]=fX[fIndLocal[0][cath]][cath];
1814 vstart[1]=fY[fIndLocal[0][cath]][cath];
1815 vstart[2]=fX[fIndLocal[1][cath]][cath];
1816 vstart[3]=fY[fIndLocal[1][cath]][cath];
1817 vstart[4]=Float_t(fQ[fIndLocal[0][cath]][cath])/
1818 Float_t(fQ[fIndLocal[0][cath]][cath]+fQ[fIndLocal[1][cath]][cath]);
1819 // lower and upper limits
1820 static Float_t lower[5], upper[5];
1821 Int_t isec=fSeg[cath]->Sector(fIx[fIndLocal[0][cath]][cath], fIy[fIndLocal[0][cath]][cath]);
1822 lower[0]=vstart[0]-fSeg[cath]->Dpx(isec);
1823 lower[1]=vstart[1]-fSeg[cath]->Dpy(isec);
1825 upper[0]=lower[0]+2.*fSeg[cath]->Dpx(isec);
1826 upper[1]=lower[1]+2.*fSeg[cath]->Dpy(isec);
1828 isec=fSeg[cath]->Sector(fIx[fIndLocal[1][cath]][cath], fIy[fIndLocal[1][cath]][cath]);
1829 lower[2]=vstart[2]-fSeg[cath]->Dpx(isec)/2;
1830 lower[3]=vstart[3]-fSeg[cath]->Dpy(isec)/2;
1832 upper[2]=lower[2]+fSeg[cath]->Dpx(isec);
1833 upper[3]=lower[3]+fSeg[cath]->Dpy(isec);
1838 static Double_t step[5]={0.0005, 0.0005, 0.0005, 0.0005, 0.0001};
1840 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1841 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1842 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1843 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1844 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1845 // ready for minimisation
1846 clusterInput.Fitter()->SetPrintLevel(-1+fDebugLevel);
1848 clusterInput.Fitter()->mnexcm("SET NOW", arglist, 0, ierflag);
1849 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
1853 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
1854 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
1855 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
1856 // Get fitted parameters
1857 Double_t xrec[2], yrec[2], qfrac;
1859 Double_t epxz, b1, b2;
1861 clusterInput.Fitter()->mnpout(0, chname, xrec[0], epxz, b1, b2, ierflg);
1862 clusterInput.Fitter()->mnpout(1, chname, yrec[0], epxz, b1, b2, ierflg);
1863 clusterInput.Fitter()->mnpout(2, chname, xrec[1], epxz, b1, b2, ierflg);
1864 clusterInput.Fitter()->mnpout(3, chname, yrec[1], epxz, b1, b2, ierflg);
1865 clusterInput.Fitter()->mnpout(4, chname, qfrac, epxz, b1, b2, ierflg);
1867 Double_t fmin, fedm, errdef;
1868 Int_t npari, nparx, istat;
1870 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
1875 Float_t AliMUONClusterFinderVS::CombiDoubleMathiesonFit(AliMUONRawCluster *c)
1878 // Perform combined double Mathieson fit on both cathode planes
1880 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
1881 clusterInput.Fitter()->SetFCN(fcnCombiS2);
1882 clusterInput.Fitter()->mninit(6,10,7);
1883 Double_t arglist[20];
1886 // Set starting values
1887 static Double_t vstart[6];
1888 vstart[0]=fXInit[0];
1889 vstart[1]=fYInit[0];
1890 vstart[2]=fXInit[1];
1891 vstart[3]=fYInit[1];
1892 vstart[4]=fQrInit[0];
1893 vstart[5]=fQrInit[1];
1894 // lower and upper limits
1895 static Float_t lower[6], upper[6];
1899 fSeg[1]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1900 isec=fSeg[1]->Sector(ix, iy);
1901 dpx=fSeg[1]->Dpx(isec);
1903 fSeg[0]->GetPadI(fXInit[0], fYInit[0], fZPlane, ix, iy);
1904 isec=fSeg[0]->Sector(ix, iy);
1905 dpy=fSeg[0]->Dpy(isec);
1909 Float_t xdum, ydum, zdum;
1911 printf("\n Cluster Finder: %f %f %f %f ", fXInit[0], fXInit[1],fYInit[0], fYInit[1] );
1913 // Find save upper and lower limits
1916 for (fSeg[1]->FirstPad(fXInit[0], fYInit[0], fZPlane, dpx, 0.);
1917 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1919 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1920 // if (fHitMap[1]->TestHit(ix, iy) == kEmpty) continue;
1921 fSeg[1]->GetPadC(ix,iy,upper[0],ydum,zdum);
1922 if (icount ==0) lower[0]=upper[0];
1925 if (lower[0]>upper[0]) {xdum=lower[0]; lower[0]=upper[0]; upper[0]=xdum;}
1926 // vstart[0] = 0.5*(lower[0]+upper[0]);
1931 for (fSeg[0]->FirstPad(fXInit[0], fYInit[0], fZPlane, 0., dpy);
1932 fSeg[0]->MorePads(); fSeg[0]->NextPad())
1934 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1935 // if (fHitMap[0]->TestHit(ix, iy) == kEmpty) continue;
1936 fSeg[0]->GetPadC(ix,iy,xdum,upper[1],zdum);
1937 if (icount ==0) lower[1]=upper[1];
1941 if (lower[1]>upper[1]) {xdum=lower[1]; lower[1]=upper[1]; upper[1]=xdum;}
1942 // vstart[1] = 0.5*(lower[1]+upper[1]);
1945 fSeg[1]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1946 isec=fSeg[1]->Sector(ix, iy);
1947 dpx=fSeg[1]->Dpx(isec);
1948 fSeg[0]->GetPadI(fXInit[1], fYInit[1], fZPlane, ix, iy);
1949 isec=fSeg[0]->Sector(ix, iy);
1950 dpy=fSeg[0]->Dpy(isec);
1953 // Find save upper and lower limits
1957 for (fSeg[1]->FirstPad(fXInit[1], fYInit[1], fZPlane, dpx, 0);
1958 fSeg[1]->MorePads(); fSeg[1]->NextPad())
1960 ix=fSeg[1]->Ix(); iy=fSeg[1]->Iy();
1961 // if (fHitMap[1]->TestHit(ix, iy) == kEmpty) continue;
1962 fSeg[1]->GetPadC(ix,iy,upper[2],ydum,zdum);
1963 if (icount ==0) lower[2]=upper[2];
1966 if (lower[2]>upper[2]) {xdum=lower[2]; lower[2]=upper[2]; upper[2]=xdum;}
1967 // vstart[2] = 0.5*(lower[2]+upper[2]);
1971 for (fSeg[0]->FirstPad(fXInit[1], fYInit[1], fZPlane, 0, dpy);
1972 fSeg[0]-> MorePads(); fSeg[0]->NextPad())
1974 ix=fSeg[0]->Ix(); iy=fSeg[0]->Iy();
1975 // if (fHitMap[0]->TestHit(ix, iy) != kEmpty) continue;
1977 fSeg[0]->GetPadC(ix,iy,xdum,upper[3],zdum);
1978 if (icount ==0) lower[3]=upper[3];
1982 if (lower[3]>upper[3]) {xdum=lower[3]; lower[3]=upper[3]; upper[3]=xdum;}
1984 // vstart[3] = 0.5*(lower[3]+upper[3]);
1992 static Double_t step[6]={0.0005, 0.0005, 0.0005, 0.0005, 0.001, 0.001};
1993 clusterInput.Fitter()->mnparm(0,"x1",vstart[0],step[0],lower[0],upper[0],ierflag);
1994 clusterInput.Fitter()->mnparm(1,"y1",vstart[1],step[1],lower[1],upper[1],ierflag);
1995 clusterInput.Fitter()->mnparm(2,"x2",vstart[2],step[2],lower[2],upper[2],ierflag);
1996 clusterInput.Fitter()->mnparm(3,"y2",vstart[3],step[3],lower[3],upper[3],ierflag);
1997 clusterInput.Fitter()->mnparm(4,"a0",vstart[4],step[4],lower[4],upper[4],ierflag);
1998 clusterInput.Fitter()->mnparm(5,"a1",vstart[5],step[5],lower[5],upper[5],ierflag);
1999 // ready for minimisation
2000 clusterInput.Fitter()->SetPrintLevel(-1+fDebugLevel);
2002 clusterInput.Fitter()->mnexcm("SET NOW", arglist, 0, ierflag);
2003 clusterInput.Fitter()->mnexcm("SET OUT", arglist, 0, ierflag);
2007 clusterInput.Fitter()->mnexcm("SET NOGR", arglist, 0, ierflag);
2008 clusterInput.Fitter()->mnexcm("MIGRAD", arglist, 0, ierflag);
2009 clusterInput.Fitter()->mnexcm("EXIT" , arglist, 0, ierflag);
2010 // Get fitted parameters
2012 Double_t epxz, b1, b2;
2014 clusterInput.Fitter()->mnpout(0, chname, fXFit[0], epxz, b1, b2, ierflg);
2015 clusterInput.Fitter()->mnpout(1, chname, fYFit[0], epxz, b1, b2, ierflg);
2016 clusterInput.Fitter()->mnpout(2, chname, fXFit[1], epxz, b1, b2, ierflg);
2017 clusterInput.Fitter()->mnpout(3, chname, fYFit[1], epxz, b1, b2, ierflg);
2018 clusterInput.Fitter()->mnpout(4, chname, fQrFit[0], epxz, b1, b2, ierflg);
2019 clusterInput.Fitter()->mnpout(5, chname, fQrFit[1], epxz, b1, b2, ierflg);
2021 Double_t fmin, fedm, errdef;
2022 Int_t npari, nparx, istat;
2024 clusterInput.Fitter()->mnstat(fmin, fedm, errdef, npari, nparx, istat);
2032 void AliMUONClusterFinderVS::Split(AliMUONRawCluster* c)
2035 // One cluster for each maximum
2038 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
2039 for (j=0; j<2; j++) {
2040 AliMUONRawCluster cnew;
2041 cnew.fGhost=c->fGhost;
2042 for (cath=0; cath<2; cath++) {
2043 cnew.fChi2[cath]=fChi2[0];
2044 // ?? why not cnew.fChi2[cath]=fChi2[cath];
2047 cnew.fNcluster[0]=-1;
2048 cnew.fNcluster[1]=fNRawClusters;
2050 cnew.fNcluster[0]=fNPeaks;
2051 cnew.fNcluster[1]=0;
2053 cnew.fMultiplicity[cath]=0;
2054 cnew.fX[cath]=Float_t(fXFit[j]);
2055 cnew.fY[cath]=Float_t(fYFit[j]);
2056 cnew.fZ[cath]=fZPlane;
2058 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*fQrFit[cath]);
2060 cnew.fQ[cath]=Int_t(clusterInput.TotalCharge(cath)*(1-fQrFit[cath]));
2062 fSeg[cath]->SetHit(fXFit[j],fYFit[j],fZPlane);
2063 for (i=0; i<fMul[cath]; i++) {
2064 cnew.fIndexMap[cnew.fMultiplicity[cath]][cath]=
2065 c->fIndexMap[i][cath];
2066 fSeg[cath]->SetPad(fIx[i][cath], fIy[i][cath]);
2067 Float_t q1=fInput->Response()->IntXY(fSeg[cath]);
2068 cnew.fContMap[i][cath]
2069 =(q1*Float_t(cnew.fQ[cath]))/Float_t(fQ[i][cath]);
2070 cnew.fMultiplicity[cath]++;
2072 FillCluster(&cnew,0,cath);
2075 cnew.fClusterType=cnew.PhysicsContribution();
2076 if (cnew.fQ[0]>0 && cnew.fQ[1]>0) AddRawCluster(cnew);
2083 // Minimisation functions
2085 void fcnS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
2087 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
2094 for (i=0; i<clusterInput.Nmul(0); i++) {
2095 Float_t q0=clusterInput.Charge(i,0);
2096 Float_t q1=clusterInput.DiscrChargeS1(i,par);
2105 void fcnCombiS1(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
2107 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
2114 for (cath=0; cath<2; cath++) {
2115 for (i=0; i<clusterInput.Nmul(cath); i++) {
2116 Float_t q0=clusterInput.Charge(i,cath);
2117 Float_t q1=clusterInput.DiscrChargeCombiS1(i,par,cath);
2128 void fcnS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
2130 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
2137 for (i=0; i<clusterInput.Nmul(0); i++) {
2139 Float_t q0=clusterInput.Charge(i,0);
2140 Float_t q1=clusterInput.DiscrChargeS2(i,par);
2150 void fcnCombiS2(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
2152 AliMUONClusterInput& clusterInput = *(AliMUONClusterInput::Instance());
2158 for (cath=0; cath<2; cath++) {
2159 for (i=0; i<clusterInput.Nmul(cath); i++) {
2160 Float_t q0=clusterInput.Charge(i,cath);
2161 Float_t q1=clusterInput.DiscrChargeCombiS2(i,par,cath);
2171 void AliMUONClusterFinderVS::AddRawCluster(const AliMUONRawCluster c)
2174 // Add a raw cluster copy to the list
2176 AliMUON *pMUON=(AliMUON*)gAlice->GetModule("MUON");
2177 pMUON->AddRawCluster(fInput->Chamber(),c);
2180 fprintf(stderr,"\nfNRawClusters %d\n",fNRawClusters);
2183 Bool_t AliMUONClusterFinderVS::TestTrack(Int_t t) {
2184 // Test if track was user selected
2185 if (fTrack[0]==-1 || fTrack[1]==-1) {
2187 } else if (t==fTrack[0] || t==fTrack[1]) {
2194 AliMUONClusterFinderVS& AliMUONClusterFinderVS
2195 ::operator = (const AliMUONClusterFinderVS& rhs)
2197 // Dummy assignment operator