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 **************************************************************************/
18 /////////////////////////////////////////////////////////
19 // Manager and hits classes for set:MUON version LYON //
20 /////////////////////////////////////////////////////////
23 #include "AliMUONChamber.h"
24 #include "AliMUONSegmentationV1.h"
27 #include "AliMUONChamber.h"
29 //___________________________________________
30 ClassImp(AliMUONSegmentationV1)
32 AliMUONSegmentationV1::AliMUONSegmentationV1(const AliMUONSegmentationV1& segmentation):AliSegmentation(segmentation)
34 // Dummy copy constructor
38 AliMUONSegmentationV1::AliMUONSegmentationV1()
41 // initizalize the class with default settings
45 fDpx=0.0; // forces crash if not initialized by user
52 void AliMUONSegmentationV1::Init(Int_t chamber)
54 // valid only for T5/6
55 // beware : frMin is SENSITIVE radius by definition.
56 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
57 AliMUONChamber* iChamber=&(pMUON->Chamber(chamber));
59 frSensMin2 = (iChamber->RInner())*(iChamber->RInner());
60 frSensMax2 = (iChamber->ROuter())*(iChamber->ROuter());
61 fNpx=(Int_t) (iChamber->ROuter()/fDpx) + 1;
62 fNpy=(Int_t) (iChamber->ROuter()/fDpy) + 1;
71 void AliMUONSegmentationV1::DefaultCut(void)
73 // Set the default cuts
89 Int_t AliMUONSegmentationV1::GetiAnod(Float_t xhit)
92 Int_t kwire=Int_t((TMath::Abs(xhit)-fSensOffset)/fDAnod)+1;
93 return (xhit>0) ? kwire : -kwire ;
96 Float_t AliMUONSegmentationV1::GetAnod(Float_t xhit) const
99 Int_t kwire=Int_t((TMath::Abs(xhit)-fSensOffset)/fDAnod)+1; // to be compatible ...
100 return (xhit>0) ? fDAnod*(kwire-0.5)+fSensOffset : -fDAnod*(kwire-0.5)-fSensOffset ;
104 void AliMUONSegmentationV1::SetPadSize(Float_t p1, Float_t p2)
106 // For chamber T5/6 p1 and p2 should be same for each zone
111 void AliMUONSegmentationV1::
112 GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
114 // returns pad coordinates (ix,iy) for given real coordinates (x,y)
116 ix = (x>0)? Int_t((x-fSensOffset)/fDpx)+1 : Int_t((x+fSensOffset)/fDpx)-1;
117 iy = (y>0)? Int_t((y-fSensOffset)/fDpy)+1 : Int_t((y+fSensOffset)/fDpy)-1;
120 void AliMUONSegmentationV1::
121 GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
123 // returns real coordinates (x,y) for given pad coordinates (ix,iy)
125 x = (ix>0) ? (Float_t(ix)-0.5)*fDpx+fSensOffset : (Float_t(ix)+0.5)*fDpx-fSensOffset;
126 y = (iy>0) ? (Float_t(iy)-0.5)*fDpy+fSensOffset : (Float_t(iy)+0.5)*fDpy-fSensOffset;
129 void AliMUONSegmentationV1::AddCut(Int_t Zone, Int_t nX, Int_t nY)
131 // the pad nX,nY is last INSIDE zone Zone. First pad is labelled 1 and not 0
133 // no cut for last Zone : it is the natural boundary of the chamber
134 printf("AliMUONSegmentationV1::AddCut ==> Zone %d not allowed !\n",Zone);
135 fZoneX[Zone][fNZoneCut[Zone]] = nX;
136 fZoneY[Zone][fNZoneCut[Zone]] = nY;
140 Int_t AliMUONSegmentationV1::GetZone(Float_t X, Float_t Y)
142 // Get segmentation zone
145 return GetZone( iX , iY );
148 Int_t AliMUONSegmentationV1::GetZone(Int_t nX, Int_t nY)
150 // Beware : first pad begins at 1 !!
151 Int_t aX = TMath::Abs(nX);
152 Int_t aY = TMath::Abs(nY);
154 for (Int_t iZone=fNzone-2;iZone>=0;iZone--)
156 for (Int_t iCut=0;iCut<fNZoneCut[iZone];iCut++)
157 if ( aY<=fZoneY[iZone][iCut] && aX<=fZoneX[iZone][iCut] )
166 void AliMUONSegmentationV1::
167 SetHit(Float_t xhit, Float_t yhit)
169 // Find the wire position (center of charge distribution)
174 void AliMUONSegmentationV1::
175 SetPad(Int_t ix, Int_t iy)
177 // Set current pad position
178 GetPadC(ix,iy,fX,fY);
182 void AliMUONSegmentationV1::SetPadCoord(Int_t iX, Int_t iY)
184 // Set current pad coordinates
185 GetPadC(iX,iY,fX,fY);
187 if ( ( (radius2=fX*fX+fY*fY) > frSensMax2 || radius2 < frSensMin2 )
192 void AliMUONSegmentationV1::FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
195 // Find the wire position (center of charge distribution)
196 Float_t x0a=GetAnod(xhit);
200 // and take fNsigma*sigma around this center
201 Float_t x01=x0a - dx;
202 Float_t x02=x0a + dx;
203 Float_t y01=yhit - dy;
204 Float_t y02=yhit + dy;
206 // Do not cross over frames...
208 x01 = TMath::Sign(fSensOffset, x0a);
210 x02 = TMath::Sign(fSensOffset, x0a);
212 y01 = TMath::Sign(fSensOffset, yhit);
214 y02 = TMath::Sign(fSensOffset, yhit);
216 // find the pads over which the charge distributes
217 GetPadI(x01,y01,fIxmin,fIymin);
218 GetPadI(x02,y02,fIxmax,fIymax);
220 // Set current pad to lower left corner
223 SetPadCoord(fIx,fIy);
226 void AliMUONSegmentationV1::NextPad()
229 // Step to next pad in integration region
232 } else if (fIy != fIymax) {
236 printf("\n Error: Stepping outside integration region\n ");
237 SetPadCoord(fIx,fIy);
240 Int_t AliMUONSegmentationV1::MorePads()
243 // Are there more pads in the integration region
245 if (fIx == fIxmax && fIy == fIymax) {
252 Int_t AliMUONSegmentationV1::IsParallel2(Int_t iX, Int_t iY)
254 // test if the pad is read in parallel for zone 2
255 // iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
256 // returns 1 or 2 if read in parallel,
257 // according to the actual number in the chain, 0 else
259 // chainage is result is
260 // 1 2 3 1 2 3 1 1 1 2 2 2 y
261 // 7 8 9 10 11 12 0 0 0 0 0 0 ^
262 // 4 5 6 4 5 6 1 1 1 2 2 2 +->x
265 if (iY%3==1) return 0;
269 Int_t AliMUONSegmentationV1::IsParallel3(Int_t iX, Int_t iY)
271 // test if the pad is read in parallel for zone 3
272 // iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
273 // returns 1,2 or 3 if read in parallel,
274 // according to the actual number in the chain, 0 else
276 // chainage is result is
277 //16 2 3 1 2 3 1 2 3 0 1 1 1 2 2 2 3 3
278 // 7 8 9 10 11 12 13 14 15 0 0 0 0 0 0 0 0 0
279 // 4 5 6 4 5 6 4 5 6 1 1 1 2 2 2 3 3 3
282 if (iY%3==1) return 0;
283 return (iX%9)/3+1 - (iY%3==2 && iX%3==0);
286 Int_t AliMUONSegmentationV1::NParallel2(Int_t /*iX*/, Int_t iY)
288 // returns the number of pads connected in parallel for zone 2
289 // iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
297 if (iY%3==1) return 1;
301 Int_t AliMUONSegmentationV1::NParallel3(Int_t iX, Int_t iY)
303 // test if the pad is read in parallel for zone 3
304 // iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
305 // returns 1,2 or 3 if read in parallel,
306 // according to the actual number in the chain, 0 else
314 if (iY%3==1) return 1;
315 if (iY%3==2 && iX%9==0) return 1;
316 return 3 - (iY%3==2 && iX%3==0);
320 Int_t AliMUONSegmentationV1::Ix(Int_t trueX, Int_t trueY)
322 // returns the X number of pad which corresponds to the logical
323 // channel, expressed in x and y.
325 Int_t wix = TMath::Abs(trueX)-1;
326 Int_t wiy = TMath::Abs(trueY)-1;
327 Int_t zone = GetZone(trueX,trueY);
330 case 0: return trueX;
332 if (IsParallel2(wix,wiy) == 2)
333 return (trueX>0)? trueX-3 : trueX+3 ;
336 if ( (par3= IsParallel3(wix,wiy)) )
337 return (trueX>0) ? trueX-3*(par3-1) : trueX+3*(par3-1) ;
340 printf("Couille dans AliMUONSegmentationV1::ix\n");
345 Int_t AliMUONSegmentationV1::Ix()
347 // returns the X number of pad which has to increment charge
348 // due to parallel read-out
352 Int_t AliMUONSegmentationV1::ISector()
354 // This function is of no use for this kind of segmentation.
355 return GetZone(fIx,fIy);
358 void AliMUONSegmentationV1::SigGenInit(Float_t x,Float_t y,Float_t /*z*/)
361 // Initialises pad and wire position during stepping
364 GetPadI(x,y,fIxt,fIyt);
369 Int_t AliMUONSegmentationV1::SigGenCond(Float_t x,Float_t y,Float_t /*z*/)
372 // Signal will be generated if particle crosses pad boundary or
373 // boundary between two wires.
376 GetPadI(x,y,ixt,iyt);
377 Int_t iwt= GetiAnod(x);
379 if ((ixt != fIxt) || (iyt !=fIyt) || (iwt != fIwt)) {
386 void AliMUONSegmentationV1::
387 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
389 // Get integration limits
396 void AliMUONSegmentationV1::GetNParallelAndOffset(Int_t iX, Int_t iY,Int_t
397 *Nparallel, Int_t* Offset)
400 Int_t wix = TMath::Abs(iX)-1;
401 Int_t wiy = TMath::Abs(iY)-1;
402 Int_t zone = GetZone(iX,iY);
409 *Nparallel = NParallel2(wix,wiy);
410 (iX>0) ? *Offset =3 : *Offset = -3;
411 if (IsParallel2(wix,wiy)>1)
412 printf("GetNParallelAndOffset called for existing channel -> answer is crazy\n");
415 *Nparallel = NParallel3(wix,wiy);
416 (iX>0) ? *Offset =3 : *Offset = -3;
417 if (IsParallel3(wix,wiy)>1)
418 printf("GetNParallelAndOffset called for existing channel -> answer is crazy\n");
424 Float_t AliMUONSegmentationV1::Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y, Int_t *Offset)
427 // Computes the offset for which the physical pad has the minimum distance squared
428 // (returned value) to the given coordinates
431 GetNParallelAndOffset(iX,iY,&nPara,&offset);
433 for (Int_t i=0;i<nPara; i++)
436 GetPadC(iX+i*offset,iY,x,y);
437 Float_t d2=(x-X)*(x-X) + (y-Y)*(y-Y);
447 void AliMUONSegmentationV1::CleanNeighbours(Int_t* Nlist, Int_t *Xlist,
450 // In the raw neighbours list, some pads do not exist
451 // and some others are read in parallel ...
452 // So we prune non-existing neighbours from the list (event if this should be
453 // at last not be a problem due to the clustering algorithm...)
456 for (Int_t nList=0;nList<*Nlist;nList++)
458 // prune if it does not exist
459 if ( Xlist[nList]==0 || Ylist[nList]==0 )
461 // compute true position
462 Xlist[nTot] = Ix(Xlist[nList],Ylist[nList]) ;
463 Ylist[nTot] = Ylist[nList] ;
464 // and prune if it does already exist
466 for (nTest=0;nTest<nTot; nTest++)
468 if ( Xlist[nTest]==Xlist[nTot] && Ylist[nTest]==Ylist[nTot])
478 void AliMUONSegmentationV1::
479 NeighboursNonDiag(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[12], Int_t Ylist[12])
481 // returns the X number of pad which has to increment charge
482 // due to parallel read-out
484 Int_t nParallel, offset;
485 GetNParallelAndOffset(iX,iY,&nParallel,&offset);
487 // now fill raw list of neighbours
489 Xlist[0]=Xlist[1]=iX;Xlist[2]=iX-1;Xlist[3]=iX+1;
490 Ylist[0]=iY-1;Ylist[1]=iY+1;Ylist[2]=Ylist[3]=iY;
492 Xlist[4]=Xlist[5]=iX+offset;Xlist[6]=iX+offset-1;Xlist[7]=iX+offset+1;
493 Ylist[4]=iY-1;Ylist[5]=iY+1;Ylist[6]=Ylist[7]=iY;
495 Xlist[8]=Xlist[9]=iX+2*offset;Xlist[10]=iX+2*offset-1;Xlist[11]=iX+2*offset+1;
496 Ylist[8]=iY-1;Ylist[9]=iY+1;Ylist[10]=Ylist[11]=iY;
499 CleanNeighbours(Nlist,Xlist,Ylist);
502 void AliMUONSegmentationV1::
503 NeighboursDiag(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[24], Int_t Ylist[24])
505 // returns the X number of pad which has to increment charge
506 // due to parallel read-out
508 Int_t nParallel, offset;
509 GetNParallelAndOffset(iX,iY,&nParallel,&offset);
511 // now fill raw list of neighbours
513 for (Int_t i=0;i<nParallel;i++)
514 for (Int_t dx=-1;dx<2;dx++)
515 for (Int_t dy=-1;dy<2;dy++)
519 Xlist[*Nlist] = iX + dx + i*offset;
520 Ylist[*Nlist] = iY + dy;
523 CleanNeighbours(Nlist,Xlist,Ylist);
526 void AliMUONSegmentationV1::Neighbours(Int_t iX, Int_t iY, Int_t* Nlist,
527 Int_t Xlist[24], Int_t Ylist[24])
530 NeighboursDiag(iX,iY,Nlist,Xlist,Ylist);
534 void AliMUONSegmentationV1::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) const
536 // Return a test point
538 x[0]=(TMath::Sqrt(frSensMax2)-TMath::Sqrt(frSensMin2))/2/TMath::Sqrt(2.);
542 AliMUONSegmentationV1& AliMUONSegmentationV1::operator =(const AliMUONSegmentationV1 & /*rhs*/)
544 // Dummy assignment operator