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 **************************************************************************/
20 #include "AliMUONClusterFinderv0.h"
21 #include "AliMUONSegResV1.h"
24 //#include <TCanvas.h>
29 //----------------------------------------------------------
30 ClassImp(AliMUONClusterFinderv0)
32 AliMUONClusterFinderv0::AliMUONClusterFinderv0
33 (AliMUONsegmentation *segmentation, AliMUONresponse *response,
34 TClonesArray *digits, Int_t chamber) : AliMUONClusterFinder(segmentation,response,digits,chamber)
37 AliMUONClusterFinderv0::AliMUONClusterFinderv0():AliMUONClusterFinder()
41 void AliMUONClusterFinder::AddRawCluster(const AliMUONRawCluster c)
44 // Add a raw cluster copy to the list
46 AliMUON *MUON=(AliMUON*)gAlice->GetModule("MUON");
47 MUON->AddRawCluster(fChamber,c);
54 void AliMUONClusterFinderv0::Decluster(AliMUONRawCluster *cluster)
60 printf("Calling decluster\n");
66 Int_t mul = cluster->fMultiplicity;
67 // printf("Decluster - multiplicity %d \n",mul);
70 // printf("\n Nothing special for 1-clusters \n");
72 // Nothing special for 1-clusters
74 AddRawCluster(*cluster);
77 // 2-cluster, compute offset
81 AddRawCluster(*cluster);
84 // 3-cluster, check topology
85 // printf("\n 3-cluster, check topology \n");
87 if (Centered(cluster)) {
89 // ok, cluster is centered
90 // printf("\n ok, cluster is centered \n");
93 // cluster is not centered, split into 2+1
94 // printf("\n cluster is not centered, split into 2+1 \n");
98 if (mul >(50-5)) printf("Decluster - multiplicity %d approaching 50\n",mul);
100 // 4-and more-pad clusters
102 SplitByLocalMaxima(cluster);
106 Int_t AliMUONClusterFinderv0::PeakOffsetAndCoordinates(Int_t DigitIndex, Float_t *X, Float_t *Y)
108 // Computes for which allowed offsets the digit has the highest neighbouring charge
109 // Returns the value of the offset, and sets the pyisical coordinates of that pad
110 // Loop on physical neighbours is specific to AliMUONsegmentationV1
112 Int_t nPara, offset, returnOffset=0 ;
113 AliMUONdigit* dig= (AliMUONdigit*)fDigits->UncheckedAt(DigitIndex);
114 AliMUONsegmentationV1* seg = (AliMUONsegmentationV1*) fSegmentation;
115 seg->GetNParallelAndOffset(dig->fPadX,dig->fPadY,&nPara,&offset);
119 for (Int_t i=0;i<nPara; i++)
121 // Compute the charge on the 9 neighbouring pads
122 // We assume that there are no pads connected in parallel in the neighbourhood
125 for (Int_t dx=-1;dx<2;dx++)
126 for (Int_t dy=-1;dy<2;dy++)
130 Int_t padY=dig->fPadY+dy;
131 Int_t padX=seg->Ix((Int_t) (dig->fPadX+dx+i*offset) , padY);
132 if (fHitMap->TestHit(padX, padY)==empty)
134 AliMUONdigit* digt = (AliMUONdigit*) fHitMap->GetHit(padX,padY);
139 returnOffset=i*offset;
144 fSegmentation->GetPadCxy(dig->fPadX+returnOffset,dig->fPadY,*X,*Y);
149 void AliMUONClusterFinderv0::SetOffset(AliMUONRawCluster *cluster)
150 // compute the offsets assuming that there is only one peak !
152 //DumpCluster(cluster);
154 cluster->fOffsetMap[0]=PeakOffsetAndCoordinates(cluster->fIndexMap[0],&X,&Y);
155 for (Int_t i=1;i<cluster->fMultiplicity;i++) {
156 AliMUONdigit* dig= (AliMUONdigit*)fDigits->UncheckedAt(cluster->fIndexMap[i]);
157 fSegmentation->Distance2AndOffset(dig->fPadX,dig->fPadY,X,Y,&(cluster->fOffsetMap[i]));
161 void AliMUONClusterFinderv0::DumpCluster(AliMUONRawCluster *cluster)
163 printf ("other cluster\n");
164 for (Int_t i=0; i<cluster->fMultiplicity; i++)
166 AliMUONdigit* dig= (AliMUONdigit*)fDigits->UncheckedAt(cluster->fIndexMap[i]);
168 fSegmentation->GetNParallelAndOffset(dig->fPadX,dig->fPadY,&nPara,&offset);
170 printf("X %d Y %d Q %d NPara %d \n",dig->fPadX, dig->fPadY,dig->fSignal, nPara);
174 Bool_t AliMUONClusterFinderv0::Centered(AliMUONRawCluster *cluster)
177 dig= (AliMUONdigit*)fDigits->UncheckedAt(cluster->fIndexMap[0]);
181 Int_t X[kMaxNeighbours], Y[kMaxNeighbours], XN[kMaxNeighbours], YN[kMaxNeighbours];
182 fSegmentation->Neighbours(ix,iy,&nn,X,Y);
185 for (Int_t i=0; i<nn; i++) {
186 if (fHitMap->TestHit(X[i],Y[i]) == used) {
194 // cluster is centered !
196 FillCluster(cluster);
197 AddRawCluster(*cluster);
201 // Highest signal on an edge, split cluster into 2+1
203 // who is the neighbour ?
204 Int_t nind=fHitMap->GetHitIndex(XN[0], YN[0]);
205 Int_t i1= (nind==cluster->fIndexMap[1]) ? 1:2;
206 Int_t i2= (nind==cluster->fIndexMap[1]) ? 2:1;
209 AliMUONRawCluster cnew;
210 cnew.fMultiplicity=2;
211 cnew.fIndexMap[0]=cluster->fIndexMap[0];
212 cnew.fIndexMap[1]=cluster->fIndexMap[i1];
218 cluster->fMultiplicity=1;
219 cluster->fIndexMap[0]=cluster->fIndexMap[i2];
220 cluster->fIndexMap[1]=0;
221 cluster->fIndexMap[2]=0;
222 FillCluster(cluster);
223 AddRawCluster(*cluster);
226 printf("\n Completely screwed up %d !! \n",nd);
234 void AliMUONClusterFinderv0::SplitByLocalMaxima(AliMUONRawCluster *c)
236 AliMUONdigit* dig[50], *digt;
237 Int_t ix[50], iy[50], q[50];
238 Float_t x[50], y[50];
239 Int_t i; // loops over digits
240 Int_t j; // loops over local maxima
242 Int_t mul=c->fMultiplicity;
244 // dump digit information into arrays
246 for (i=0; i<mul; i++)
248 dig[i]= (AliMUONdigit*)fDigits->UncheckedAt(c->fIndexMap[i]);
249 ix[i]= dig[i]->fPadX;
250 iy[i]= dig[i]->fPadY;
251 q[i] = dig[i]->fSignal;
252 fSegmentation->GetPadCxy(ix[i], iy[i], x[i], y[i]);
262 Int_t X[kMaxNeighbours], Y[kMaxNeighbours];
263 for (i=0; i<mul; i++) {
264 fSegmentation->Neighbours(ix[i], iy[i], &nn, X, Y);
266 for (j=0; j<nn; j++) {
267 if (fHitMap->TestHit(X[j], Y[j])==empty) continue;
268 digt=(AliMUONdigit*) fHitMap->GetHit(X[j], Y[j]);
269 if (digt->fSignal > q[i]) {
273 // handle special case of neighbouring pads with equal signal
274 } else if (digt->fSignal == q[i]) {
276 for (Int_t k=0; k<NLocal; k++) {
277 if (X[j]==ix[IndLocal[k]] && Y[j]==iy[IndLocal[k]]){
283 } // loop over next neighbours
286 // New for LYON : we guess which is the actual position of the pad hit
287 // But this would run like that for normal chamber !
288 c->fOffsetMap[i]=PeakOffsetAndCoordinates(c->fIndexMap[i], &(x[i]), &(y[i]));
291 } // loop over all digits
292 // printf("Found %d local Maxima",NLocal);
294 // Check if enough local clusters have been found,
295 // if not add global maxima to the list
297 // But what the hell is that ? (Manu)
299 // Int_t nPerMax=mul/NLocal;
300 // if (nPerMax > 5) {
301 // Int_t nGlob=mul/5-NLocal+1;
304 // for (i=0; i<mul; i++) {
305 // if (!IsLocal[i]) {
306 // IndLocal[NLocal]=i;
311 // if (nnew==nGlob) break;
317 // Associate hits to peaks
319 for (i=0; i<mul; i++) {
326 if (IsLocal[i]) continue;
327 for (j=0; j<NLocal; j++) {
331 Int_t il=IndLocal[j];
332 // Float_t d=TMath::Sqrt((x[i]-x[il])*(x[i]-x[il])
333 // +(y[i]-y[il])*(y[i]-y[il]));
334 // Can run like that for non-Lyon chambers
335 Float_t d = fSegmentation->Distance2AndOffset(ix[i],iy[i],x[il],y[il], &offset);
338 // Select nearest peak
344 c->fOffsetMap[i]=offset;
345 } else if (d==dmin) {
347 // If more than one take highest peak
353 c->fOffsetMap[i]=offset;
356 } // End loop on peaks
357 } // end loop on digits
359 // One cluster for each maximum
361 for (j=0; j<NLocal; j++) {
362 AliMUONRawCluster cnew;
363 cnew.fIndexMap[0]=c->fIndexMap[IndLocal[j]];
364 cnew.fOffsetMap[0]=c->fOffsetMap[IndLocal[j]];
365 cnew.fMultiplicity=1;
366 for (i=0; i<mul; i++) {
367 if (IsLocal[i]) continue;
368 if (AssocPeak[i]==j) {
369 cnew.fIndexMap[cnew.fMultiplicity]=c->fIndexMap[i];
370 cnew.fOffsetMap[cnew.fMultiplicity]=c->fOffsetMap[i];
371 cnew.fMultiplicity++;
380 void AliMUONClusterFinderv0::FillCluster(AliMUONRawCluster* c)
383 // Completes cluster information starting from list of digits
393 for (Int_t i=0; i<c->fMultiplicity; i++)
395 dig= (AliMUONdigit*)fDigits->UncheckedAt(c->fIndexMap[i]);
396 ix=dig->fPadX + c.fOffsetMap[i]; // should be 0 for non-LYON
398 Int_t q=dig->fSignal;
401 // peak signal and track list
402 if (q>c->fPeakSignal) {
404 c->fTracks[0]=dig->fTracks[0];
405 c->fTracks[1]=dig->fTracks[1];
406 c->fTracks[2]=dig->fTracks[2];
410 fSegmentation->GetPadCxy(ix, iy, x, y);
416 // Not valid for inclined tracks in X !!! (Manu)
417 // c->fX=fSegmentation->GetAnod(c->fX);
420 // apply correction to the coordinate along the anode wire
425 fSegmentation->GetPadIxy(x, y, ix, iy);
426 fSegmentation->GetPadCxy(ix, iy, x, y);
427 Float_t YonPad=(c->fY-y)/fSegmentation->Dpy();
428 c->fY=y-fCogCorr->Eval(YonPad, 0, 0);
434 void AliMUONClusterFinder::FindCluster(Int_t i, Int_t j, AliMUONRawCluster &c){
439 // Add i,j as element of the cluster
442 Int_t idx = fHitMap->GetHitIndex(i,j);
443 AliMUONdigit* dig = (AliMUONdigit*) fHitMap->GetHit(i,j);
444 Int_t q=dig->fSignal;
445 if (q > TMath::Abs(c.fPeakSignal)) {
447 c.fTracks[0]=dig->fTracks[0];
448 c.fTracks[1]=dig->fTracks[1];
449 c.fTracks[2]=dig->fTracks[2];
452 // Make sure that list of digits is ordered
454 Int_t mu=c.fMultiplicity;
458 for (Int_t ind=mu-1; ind>=0; ind--) {
459 Int_t ist=(c.fIndexMap)[ind];
460 Int_t ql=((AliMUONdigit*)fDigits
461 ->UncheckedAt(ist))->fSignal;
463 c.fIndexMap[ind]=idx;
464 c.fIndexMap[ind+1]=ist;
473 if (c.fMultiplicity >= 50 ) {
474 printf("FindCluster - multiplicity >50 %d \n",c.fMultiplicity);
475 c.fMultiplicity=50-1;
478 // Prepare center of gravity calculation
480 fSegmentation->GetPadCxy(i, j, x, y);
485 fHitMap->FlagHit(i,j);
487 // Now look recursively for all neighbours
490 Int_t Xlist[kMaxNeighbours], Ylist[kMaxNeighbours];
491 fSegmentation->Neighbours(i,j,&nn,Xlist,Ylist);
492 for (Int_t in=0; in<nn; in++) {
495 if (fHitMap->TestHit(ix,iy)==unused) FindCluster(ix, iy, c);
500 //_____________________________________________________________________________
502 void AliMUONClusterFinderv0::FindRawClusters()
505 // simple MUON cluster finder from digits -- finds neighbours and
506 // fill the tree with raw clusters
508 if (!fNdigits) return;
510 fHitMap = new AliMUONHitMapA1(fSegmentation, fDigits);
518 for (ndig=0; ndig<fNdigits; ndig++) {
519 dig = (AliMUONdigit*)fDigits->UncheckedAt(ndig);
522 if (fHitMap->TestHit(i,j)==used ||fHitMap->TestHit(i,j)==empty) {
528 // c.fPeakSignal=dig->fSignal;
529 // c.fTracks[0]=dig->fTracks[0];
530 // c.fTracks[1]=dig->fTracks[1];
531 // c.fTracks[2]=dig->fTracks[2];
536 c.fX=fSegmentation->GetAnod(c.fX);
539 // apply correction to the coordinate along the anode wire
547 fSegmentation->GetPadIxy(x, y, ix, iy);
548 fSegmentation->GetPadCxy(ix, iy, x, y);
549 Float_t YonPad=(c.fY-y)/fSegmentation->Dpy();
550 c.fY=y-fCogCorr->Eval(YonPad,0,0);
553 // Analyse cluster and decluster if necessary
559 // reset Cluster object
560 for (int k=0;k<c.fMultiplicity;k++) {
571 void AliMUONClusterFinder::
580 fSegmentation->GiveTestPoints(n, x, y);
581 for (i=0; i<n; i++) {
584 SinoidalFit(xtest, ytest, func);
586 fCogCorr = new TF1(func);
592 void AliMUONClusterFinder::
593 SinoidalFit(Float_t x, Float_t y, TF1 &func)
596 static Int_t count=0;
599 sprintf(canvasname,"c%d",count);
601 // MANU : without const, error on HP
603 Float_t xg[ns], yg[ns], xrg[ns], yrg[ns];
604 Float_t xsig[ns], ysig[ns];
606 AliMUONsegmentation *segmentation=fSegmentation;
609 segmentation->GetPadIxy(x,y,ix,iy);
610 segmentation->GetPadCxy(ix,iy,x,y);
611 Int_t isec=segmentation->Sector(ix,iy);
613 Float_t xmin = x-segmentation->GetRealDpx(isec)/2;
614 Float_t ymin = y-segmentation->Dpy()/2;
616 // Integration Limits
617 Float_t dxI=fResponse->Nsigma()*fResponse->ChwX();
618 Float_t dyI=fResponse->Nsigma()*fResponse->ChwY();
628 Float_t dy=segmentation->Dpy()/(ns-1);
630 for (i=0; i<ns; i++) {
636 segmentation->SigGenInit(x, yscan, 0);
638 for (segmentation->FirstPad(x, yscan, dxI, dyI);
639 segmentation->MorePads();
640 segmentation->NextPad())
642 qp=fResponse->IntXY(segmentation);
648 Int_t ixs=segmentation->Ix();
649 Int_t iys=segmentation->Iy();
651 segmentation->GetPadCxy(ixs,iys,xs,ys);
655 Float_t ycog=sum/qcheck;
656 yg[i]=(yscan-y)/segmentation->Dpy();
657 yrg[i]=(ycog-y)/segmentation->Dpy();
664 Float_t dx=segmentation->GetRealDpx(isec)/(ns-1);
666 for (i=0; i<ns; i++) {
672 segmentation->SigGenInit(xscan, y, 0);
674 for (segmentation->FirstPad(xscan, y, dxI, dyI);
675 segmentation->MorePads();
676 segmentation->NextPad())
678 qp=fResponse->IntXY(segmentation);
684 Int_t ixs=segmentation->Ix();
685 Int_t iys=segmentation->Iy();
687 segmentation->GetPadCxy(ixs,iys,xs,ys);
691 Float_t xcog=sum/qcheck;
692 xcog=segmentation->GetAnod(xcog);
694 xg[i]=(xscan-x)/segmentation->GetRealDpx(isec);
695 xrg[i]=(xcog-x)/segmentation->GetRealDpx(isec);
700 TCanvas *c1=new TCanvas(canvasname,canvasname,400,10,600,700);
701 TPad* pad11 = new TPad("pad11"," ",0.01,0.51,0.49,0.99);
702 TPad* pad12 = new TPad("pad12"," ",0.51,0.51,0.99,0.99);
703 TPad* pad13 = new TPad("pad13"," ",0.01,0.01,0.49,0.49);
704 TPad* pad14 = new TPad("pad14"," ",0.51,0.01,0.99,0.49);
705 pad11->SetFillColor(11);
706 pad12->SetFillColor(11);
707 pad13->SetFillColor(11);
708 pad14->SetFillColor(11);
713 TGraph *graphx = new TGraph(ns,xg ,xsig);
714 TGraph *graphxr= new TGraph(ns,xrg,xsig);
715 TGraph *graphy = new TGraph(ns,yg ,ysig);
716 TGraph *graphyr= new TGraph(ns,yrg,ysig);
718 // Creates a Root function based on function sinoid above
719 // and perform the fit
721 Double_t sinoid(Double_t *x, Double_t *par);
722 TF1 *sinoidf = new TF1("sinoidf",sinoid,0.5,0.5,5);
723 graphyr->Fit("sinoidf","V");
728 graphx->SetFillColor(42);
729 graphx->SetMarkerColor(4);
730 graphx->SetMarkerStyle(21);
732 graphx->GetHistogram()->SetXTitle("x on pad");
733 graphx->GetHistogram()->SetYTitle("xcog-x");
737 graphxr->SetFillColor(42);
738 graphxr->SetMarkerColor(4);
739 graphxr->SetMarkerStyle(21);
741 graphxr->GetHistogram()->SetXTitle("xcog on pad");
742 graphxr->GetHistogram()->SetYTitle("xcog-x");
746 graphy->SetFillColor(42);
747 graphy->SetMarkerColor(4);
748 graphy->SetMarkerStyle(21);
750 graphy->GetHistogram()->SetXTitle("y on pad");
751 graphy->GetHistogram()->SetYTitle("ycog-y");
756 graphyr->SetFillColor(42);
757 graphyr->SetMarkerColor(4);
758 graphyr->SetMarkerStyle(21);
760 graphyr->GetHistogram()->SetXTitle("ycog on pad");
761 graphyr->GetHistogram()->SetYTitle("ycog-y");
768 Double_t sinoid(Double_t *x, Double_t *par)
770 Double_t arg = -2*TMath::Pi()*x[0];
771 Double_t fitval= par[0]*TMath::Sin(arg)+
772 par[1]*TMath::Sin(2*arg)+
773 par[2]*TMath::Sin(3*arg)+
774 par[3]*TMath::Sin(4*arg)+
775 par[4]*TMath::Sin(5*arg);