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 Revision 1.5 2000/10/02 16:58:29 egangler
19 Cleaning of the code :
22 -> some useless includes removed or replaced by "class" statement
24 Revision 1.4 2000/07/03 11:54:57 morsch
25 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
26 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
28 Revision 1.3 2000/06/29 12:34:09 morsch
29 AliMUONSegmentation class has been made independent of AliMUONChamber. This makes
30 it usable with any other geometry class. The link to the object to which it belongs is
31 established via an index. This assumes that there exists a global geometry manager
32 from which the pointer to the parent object can be obtained (in our case gAlice).
34 Revision 1.2 2000/06/15 07:58:48 morsch
35 Code from MUON-dev joined
37 Revision 1.1.2.2 2000/06/12 07:57:43 morsch
40 Revision 1.1.2.1 2000/06/09 21:41:29 morsch
41 AliMUONSegmentationV1 code from AliMUONSegResV1.cxx
46 /////////////////////////////////////////////////////////
47 // Manager and hits classes for set:MUON version LYON //
48 /////////////////////////////////////////////////////////
51 #include "AliMUONChamber.h"
52 #include "AliMUONSegmentationV1.h"
56 //___________________________________________
57 ClassImp(AliMUONSegmentationV1)
59 AliMUONSegmentationV1::AliMUONSegmentationV1(const AliMUONSegmentationV1& segmentation)
61 // Dummy copy constructor
65 AliMUONSegmentationV1::AliMUONSegmentationV1()
68 // initizalize the class with default settings
72 fDpx=0.0; // forces crash if not initialized by user
78 void AliMUONSegmentationV1::Init(Int_t chamber)
80 // valid only for T5/6
81 // beware : frMin is SENSITIVE radius by definition.
82 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
83 AliMUONChamber* iChamber=&(pMUON->Chamber(chamber));
85 frSensMin2 = (iChamber->RInner())*(iChamber->RInner());
86 frSensMax2 = (iChamber->ROuter())*(iChamber->ROuter());
87 fNpx=(Int_t) (iChamber->ROuter()/fDpx) + 1;
88 fNpy=(Int_t) (iChamber->ROuter()/fDpy) + 1;
94 void AliMUONSegmentationV1::DefaultCut(void)
96 // Set the default cuts
104 AddCut(1,12*6,18*12);
105 AddCut(1,15*6,15*12);
106 AddCut(1,18*6,12*12);
112 Int_t AliMUONSegmentationV1::GetiAnod(Float_t xhit)
115 Int_t kwire=Int_t((TMath::Abs(xhit)-fSensOffset)/fDAnod)+1;
116 return (xhit>0) ? kwire : -kwire ;
119 Float_t AliMUONSegmentationV1::GetAnod(Float_t xhit) const
121 // Get anode position
122 Int_t kwire=Int_t((TMath::Abs(xhit)-fSensOffset)/fDAnod)+1; // to be compatible ...
123 return (xhit>0) ? fDAnod*(kwire-0.5)+fSensOffset : -fDAnod*(kwire-0.5)-fSensOffset ;
127 void AliMUONSegmentationV1::SetPadSize(Float_t p1, Float_t p2)
129 // For chamber T5/6 p1 and p2 should be same for each zone
134 void AliMUONSegmentationV1::
135 GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
137 // returns pad coordinates (ix,iy) for given real coordinates (x,y)
139 ix = (x>0)? Int_t((x-fSensOffset)/fDpx)+1 : Int_t((x+fSensOffset)/fDpx)-1;
140 iy = (y>0)? Int_t((y-fSensOffset)/fDpy)+1 : Int_t((y+fSensOffset)/fDpy)-1;
143 void AliMUONSegmentationV1::
144 GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
146 // returns real coordinates (x,y) for given pad coordinates (ix,iy)
148 x = (ix>0) ? (Float_t(ix)-0.5)*fDpx+fSensOffset : (Float_t(ix)+0.5)*fDpx-fSensOffset;
149 y = (iy>0) ? (Float_t(iy)-0.5)*fDpy+fSensOffset : (Float_t(iy)+0.5)*fDpy-fSensOffset;
152 void AliMUONSegmentationV1::AddCut(Int_t Zone, Int_t nX, Int_t nY)
154 // the pad nX,nY is last INSIDE zone Zone. First pad is labelled 1 and not 0
156 // no cut for last Zone : it is the natural boundary of the chamber
157 printf("AliMUONSegmentationV1::AddCut ==> Zone %d not allowed !\n",Zone);
158 fZoneX[Zone][fNZoneCut[Zone]] = nX;
159 fZoneY[Zone][fNZoneCut[Zone]] = nY;
163 Int_t AliMUONSegmentationV1::GetZone(Float_t X, Float_t Y)
165 // Get segmentation zone
168 return GetZone( iX , iY );
171 Int_t AliMUONSegmentationV1::GetZone(Int_t nX, Int_t nY)
173 // Beware : first pad begins at 1 !!
174 Int_t aX = TMath::Abs(nX);
175 Int_t aY = TMath::Abs(nY);
177 for (Int_t iZone=fNzone-2;iZone>=0;iZone--)
179 for (Int_t iCut=0;iCut<fNZoneCut[iZone];iCut++)
180 if ( aY<=fZoneY[iZone][iCut] && aX<=fZoneX[iZone][iCut] )
189 void AliMUONSegmentationV1::
190 SetHit(Float_t xhit, Float_t yhit)
192 // Find the wire position (center of charge distribution)
197 void AliMUONSegmentationV1::
198 SetPad(Int_t ix, Int_t iy)
200 // Set current pad position
201 GetPadC(ix,iy,fX,fY);
205 void AliMUONSegmentationV1::SetPadCoord(Int_t iX, Int_t iY)
207 // Set current pad coordinates
208 GetPadC(iX,iY,fX,fY);
210 if ( ( (radius2=fX*fX+fY*fY) > frSensMax2 || radius2 < frSensMin2 )
215 void AliMUONSegmentationV1::FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
218 // Find the wire position (center of charge distribution)
219 Float_t x0a=GetAnod(xhit);
223 // and take fNsigma*sigma around this center
224 Float_t x01=x0a - dx;
225 Float_t x02=x0a + dx;
226 Float_t y01=yhit - dy;
227 Float_t y02=yhit + dy;
229 // Do not cross over frames...
231 x01 = TMath::Sign(fSensOffset, x0a);
233 x02 = TMath::Sign(fSensOffset, x0a);
235 y01 = TMath::Sign(fSensOffset, yhit);
237 y02 = TMath::Sign(fSensOffset, yhit);
239 // find the pads over which the charge distributes
240 GetPadI(x01,y01,fIxmin,fIymin);
241 GetPadI(x02,y02,fIxmax,fIymax);
243 // Set current pad to lower left corner
246 SetPadCoord(fIx,fIy);
249 void AliMUONSegmentationV1::NextPad()
252 // Step to next pad in integration region
255 } else if (fIy != fIymax) {
259 printf("\n Error: Stepping outside integration region\n ");
260 SetPadCoord(fIx,fIy);
263 Int_t AliMUONSegmentationV1::MorePads()
266 // Are there more pads in the integration region
268 if (fIx == fIxmax && fIy == fIymax) {
275 Int_t AliMUONSegmentationV1::IsParallel2(Int_t iX, Int_t iY)
277 // test if the pad is read in parallel for zone 2
278 // iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
279 // returns 1 or 2 if read in parallel,
280 // according to the actual number in the chain, 0 else
282 // chainage is result is
283 // 1 2 3 1 2 3 1 1 1 2 2 2 y
284 // 7 8 9 10 11 12 0 0 0 0 0 0 ^
285 // 4 5 6 4 5 6 1 1 1 2 2 2 +->x
288 if (iY%3==1) return 0;
292 Int_t AliMUONSegmentationV1::IsParallel3(Int_t iX, Int_t iY)
294 // test if the pad is read in parallel for zone 3
295 // iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
296 // returns 1,2 or 3 if read in parallel,
297 // according to the actual number in the chain, 0 else
299 // chainage is result is
300 //16 2 3 1 2 3 1 2 3 0 1 1 1 2 2 2 3 3
301 // 7 8 9 10 11 12 13 14 15 0 0 0 0 0 0 0 0 0
302 // 4 5 6 4 5 6 4 5 6 1 1 1 2 2 2 3 3 3
305 if (iY%3==1) return 0;
306 return (iX%9)/3+1 - (iY%3==2 && iX%3==0);
309 Int_t AliMUONSegmentationV1::NParallel2(Int_t iX, Int_t iY)
311 // returns the number of pads connected in parallel for zone 2
312 // iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
320 if (iY%3==1) return 1;
324 Int_t AliMUONSegmentationV1::NParallel3(Int_t iX, Int_t iY)
326 // test if the pad is read in parallel for zone 3
327 // iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
328 // returns 1,2 or 3 if read in parallel,
329 // according to the actual number in the chain, 0 else
337 if (iY%3==1) return 1;
338 if (iY%3==2 && iX%9==0) return 1;
339 return 3 - (iY%3==2 && iX%3==0);
343 Int_t AliMUONSegmentationV1::Ix(Int_t trueX, Int_t trueY)
345 // returns the X number of pad which corresponds to the logical
346 // channel, expressed in x and y.
348 Int_t wix = TMath::Abs(trueX)-1;
349 Int_t wiy = TMath::Abs(trueY)-1;
350 Int_t zone = GetZone(trueX,trueY);
353 case 0: return trueX;
355 if (IsParallel2(wix,wiy) == 2)
356 return (trueX>0)? trueX-3 : trueX+3 ;
359 if ( (par3= IsParallel3(wix,wiy)) )
360 return (trueX>0) ? trueX-3*(par3-1) : trueX+3*(par3-1) ;
363 printf("Couille dans AliMUONSegmentationV1::ix\n");
368 Int_t AliMUONSegmentationV1::Ix()
370 // returns the X number of pad which has to increment charge
371 // due to parallel read-out
375 Int_t AliMUONSegmentationV1::ISector()
377 // This function is of no use for this kind of segmentation.
378 return GetZone(fIx,fIy);
381 void AliMUONSegmentationV1::SigGenInit(Float_t x,Float_t y,Float_t z)
384 // Initialises pad and wire position during stepping
387 GetPadI(x,y,fIxt,fIyt);
392 Int_t AliMUONSegmentationV1::SigGenCond(Float_t x,Float_t y,Float_t z)
395 // Signal will be generated if particle crosses pad boundary or
396 // boundary between two wires.
399 GetPadI(x,y,ixt,iyt);
400 Int_t iwt= GetiAnod(x);
402 if ((ixt != fIxt) || (iyt !=fIyt) || (iwt != fIwt)) {
409 void AliMUONSegmentationV1::
410 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
412 // Get integration limits
419 void AliMUONSegmentationV1::GetNParallelAndOffset(Int_t iX, Int_t iY,Int_t
420 *Nparallel, Int_t* Offset)
423 Int_t wix = TMath::Abs(iX)-1;
424 Int_t wiy = TMath::Abs(iY)-1;
425 Int_t zone = GetZone(iX,iY);
432 *Nparallel = NParallel2(wix,wiy);
433 (iX>0) ? *Offset =3 : *Offset = -3;
434 if (IsParallel2(wix,wiy)>1)
435 printf("GetNParallelAndOffset called for existing channel -> answer is crazy\n");
438 *Nparallel = NParallel3(wix,wiy);
439 (iX>0) ? *Offset =3 : *Offset = -3;
440 if (IsParallel3(wix,wiy)>1)
441 printf("GetNParallelAndOffset called for existing channel -> answer is crazy\n");
447 Float_t AliMUONSegmentationV1::Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y, Int_t *Offset)
450 // Computes the offset for which the physical pad has the minimum distance squared
451 // (returned value) to the given coordinates
454 GetNParallelAndOffset(iX,iY,&nPara,&offset);
456 for (Int_t i=0;i<nPara; i++)
459 GetPadC(iX+i*offset,iY,x,y);
460 Float_t d2=(x-X)*(x-X) + (y-Y)*(y-Y);
470 void AliMUONSegmentationV1::CleanNeighbours(Int_t* Nlist, Int_t *Xlist,
473 // In the raw neighbours list, some pads do not exist
474 // and some others are read in parallel ...
475 // So we prune non-existing neighbours from the list (event if this should be
476 // at last not be a problem due to the clustering algorithm...)
479 for (Int_t nList=0;nList<*Nlist;nList++)
481 // prune if it does not exist
482 if ( Xlist[nList]==0 || Ylist[nList]==0 )
484 // compute true position
485 Xlist[nTot] = Ix(Xlist[nList],Ylist[nList]) ;
486 Ylist[nTot] = Ylist[nList] ;
487 // and prune if it does already exist
489 for (nTest=0;nTest<nTot; nTest++)
491 if ( Xlist[nTest]==Xlist[nTot] && Ylist[nTest]==Ylist[nTot])
501 void AliMUONSegmentationV1::
502 NeighboursNonDiag(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[12], Int_t Ylist[12])
504 // returns the X number of pad which has to increment charge
505 // due to parallel read-out
507 Int_t nParallel, offset;
508 GetNParallelAndOffset(iX,iY,&nParallel,&offset);
510 // now fill raw list of neighbours
512 Xlist[0]=Xlist[1]=iX;Xlist[2]=iX-1;Xlist[3]=iX+1;
513 Ylist[0]=iY-1;Ylist[1]=iY+1;Ylist[2]=Ylist[3]=iY;
515 Xlist[4]=Xlist[5]=iX+offset;Xlist[6]=iX+offset-1;Xlist[7]=iX+offset+1;
516 Ylist[4]=iY-1;Ylist[5]=iY+1;Ylist[6]=Ylist[7]=iY;
518 Xlist[8]=Xlist[9]=iX+2*offset;Xlist[10]=iX+2*offset-1;Xlist[11]=iX+2*offset+1;
519 Ylist[8]=iY-1;Ylist[9]=iY+1;Ylist[10]=Ylist[11]=iY;
522 CleanNeighbours(Nlist,Xlist,Ylist);
525 void AliMUONSegmentationV1::
526 NeighboursDiag(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[24], Int_t Ylist[24])
528 // returns the X number of pad which has to increment charge
529 // due to parallel read-out
531 Int_t nParallel, offset;
532 GetNParallelAndOffset(iX,iY,&nParallel,&offset);
534 // now fill raw list of neighbours
536 for (Int_t i=0;i<nParallel;i++)
537 for (Int_t dx=-1;dx<2;dx++)
538 for (Int_t dy=-1;dy<2;dy++)
542 Xlist[*Nlist] = iX + dx + i*offset;
543 Ylist[*Nlist] = iY + dy;
546 CleanNeighbours(Nlist,Xlist,Ylist);
549 void AliMUONSegmentationV1::Neighbours(Int_t iX, Int_t iY, Int_t* Nlist,
550 Int_t Xlist[24], Int_t Ylist[24])
553 NeighboursDiag(iX,iY,Nlist,Xlist,Ylist);
557 void AliMUONSegmentationV1::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) const
559 // Return a test point
561 x[0]=(TMath::Sqrt(frSensMax2)-TMath::Sqrt(frSensMin2))/2/TMath::Sqrt(2.);
565 AliMUONSegmentationV1& AliMUONSegmentationV1::operator =(const AliMUONSegmentationV1 & rhs)
567 // Dummy assignment operator