]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONSegmentationV1.cxx
Made a new abstract base class; AliL3HoughBaseTransformer for different implementations
[u/mrichter/AliRoot.git] / MUON / AliMUONSegmentationV1.cxx
CommitLineData
a9e2aefa 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
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 **************************************************************************/
15
16/*
17$Log$
3f5cf0b3 18Revision 1.7 2000/10/18 11:42:06 morsch
19- AliMUONRawCluster contains z-position.
20- Some clean-up of useless print statements during initialisations.
21
3e1872ed 22Revision 1.6 2000/10/03 21:48:07 morsch
23Adopt to const declaration of some of the methods in AliSegmentation.
24
c3eff6ad 25Revision 1.5 2000/10/02 16:58:29 egangler
26Cleaning of the code :
27-> coding conventions
28-> void Streamers
29-> some useless includes removed or replaced by "class" statement
30
ecfa008b 31Revision 1.4 2000/07/03 11:54:57 morsch
32AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
33The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
34
a30a000f 35Revision 1.3 2000/06/29 12:34:09 morsch
36AliMUONSegmentation class has been made independent of AliMUONChamber. This makes
37it usable with any other geometry class. The link to the object to which it belongs is
38established via an index. This assumes that there exists a global geometry manager
39from which the pointer to the parent object can be obtained (in our case gAlice).
40
d81db581 41Revision 1.2 2000/06/15 07:58:48 morsch
42Code from MUON-dev joined
43
a9e2aefa 44Revision 1.1.2.2 2000/06/12 07:57:43 morsch
45include TMath.cxx
46
47Revision 1.1.2.1 2000/06/09 21:41:29 morsch
48AliMUONSegmentationV1 code from AliMUONSegResV1.cxx
49
50*/
51
52
53/////////////////////////////////////////////////////////
54// Manager and hits classes for set:MUON version LYON //
55/////////////////////////////////////////////////////////
56
57#include <TMath.h>
58#include "AliMUONChamber.h"
59#include "AliMUONSegmentationV1.h"
d81db581 60#include "AliRun.h"
61#include "AliMUON.h"
3e1872ed 62#include "AliMUONChamber.h"
a9e2aefa 63
64//___________________________________________
65ClassImp(AliMUONSegmentationV1)
66
67AliMUONSegmentationV1::AliMUONSegmentationV1(const AliMUONSegmentationV1& segmentation)
68{
69// Dummy copy constructor
70}
71
72
73AliMUONSegmentationV1::AliMUONSegmentationV1()
74
75{
76 // initizalize the class with default settings
77 fNzone=1;
78 fDAnod=0.0;
79 fDpx=0.0;
80 fDpx=0.0; // forces crash if not initialized by user
81 fNZoneCut[0]=0;
82 fSensOffset=0;
3f5cf0b3 83 fCorr = 0;
a9e2aefa 84}
85
86
d81db581 87void AliMUONSegmentationV1::Init(Int_t chamber)
a9e2aefa 88{
89 // valid only for T5/6
90 // beware : frMin is SENSITIVE radius by definition.
d81db581 91 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
92 AliMUONChamber* iChamber=&(pMUON->Chamber(chamber));
93
94 frSensMin2 = (iChamber->RInner())*(iChamber->RInner());
95 frSensMax2 = (iChamber->ROuter())*(iChamber->ROuter());
96 fNpx=(Int_t) (iChamber->ROuter()/fDpx) + 1;
97 fNpy=(Int_t) (iChamber->ROuter()/fDpy) + 1;
a9e2aefa 98 // fNwire=3;
99 DefaultCut();
100 fCorr=0;
3e1872ed 101
102 fZ = iChamber->Z();
103
a9e2aefa 104}
105
106void AliMUONSegmentationV1::DefaultCut(void)
107{
108// Set the default cuts
109 SetNzone(3);
110 AddCut(0,5*6,18*8);
111 AddCut(0,9*6,15*8);
112 AddCut(0,11*6,12*8);
113 AddCut(0,12*6,9*8);
114 AddCut(0,13*6,6*8);
115 AddCut(1,6*6,20*12);
116 AddCut(1,12*6,18*12);
117 AddCut(1,15*6,15*12);
118 AddCut(1,18*6,12*12);
119 AddCut(1,21*6,9*12);
120 SetSensOffset(3.0);
121 SetDAnod(0.325);
122}
123
124Int_t AliMUONSegmentationV1::GetiAnod(Float_t xhit)
125{
126// Get anode number
127 Int_t kwire=Int_t((TMath::Abs(xhit)-fSensOffset)/fDAnod)+1;
128 return (xhit>0) ? kwire : -kwire ;
129}
130
c3eff6ad 131Float_t AliMUONSegmentationV1::GetAnod(Float_t xhit) const
a9e2aefa 132{
133// Get anode position
134 Int_t kwire=Int_t((TMath::Abs(xhit)-fSensOffset)/fDAnod)+1; // to be compatible ...
135 return (xhit>0) ? fDAnod*(kwire-0.5)+fSensOffset : -fDAnod*(kwire-0.5)-fSensOffset ;
136}
137
138
139void AliMUONSegmentationV1::SetPadSize(Float_t p1, Float_t p2)
140{
141// For chamber T5/6 p1 and p2 should be same for each zone
142 fDpx=p1;
143 fDpy=p2;
144}
145
146void AliMUONSegmentationV1::
a30a000f 147GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
a9e2aefa 148{
149// returns pad coordinates (ix,iy) for given real coordinates (x,y)
150//
151 ix = (x>0)? Int_t((x-fSensOffset)/fDpx)+1 : Int_t((x+fSensOffset)/fDpx)-1;
152 iy = (y>0)? Int_t((y-fSensOffset)/fDpy)+1 : Int_t((y+fSensOffset)/fDpy)-1;
153}
154
155void AliMUONSegmentationV1::
a30a000f 156GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
a9e2aefa 157{
158// returns real coordinates (x,y) for given pad coordinates (ix,iy)
159//
160 x = (ix>0) ? (Float_t(ix)-0.5)*fDpx+fSensOffset : (Float_t(ix)+0.5)*fDpx-fSensOffset;
161 y = (iy>0) ? (Float_t(iy)-0.5)*fDpy+fSensOffset : (Float_t(iy)+0.5)*fDpy-fSensOffset;
162}
163
164void AliMUONSegmentationV1::AddCut(Int_t Zone, Int_t nX, Int_t nY)
165{
166// the pad nX,nY is last INSIDE zone Zone. First pad is labelled 1 and not 0
167 if (Zone+1>=fNzone)
168// no cut for last Zone : it is the natural boundary of the chamber
169 printf("AliMUONSegmentationV1::AddCut ==> Zone %d not allowed !\n",Zone);
170 fZoneX[Zone][fNZoneCut[Zone]] = nX;
171 fZoneY[Zone][fNZoneCut[Zone]] = nY;
172 fNZoneCut[Zone]++;
173}
174
175Int_t AliMUONSegmentationV1::GetZone(Float_t X, Float_t Y)
176{
177// Get segmentation zone
178 Int_t iX, iY;
a30a000f 179 GetPadI(X,Y,iX,iY);
a9e2aefa 180 return GetZone( iX , iY );
181}
182
183Int_t AliMUONSegmentationV1::GetZone(Int_t nX, Int_t nY)
184{
185// Beware : first pad begins at 1 !!
186 Int_t aX = TMath::Abs(nX);
187 Int_t aY = TMath::Abs(nY);
188 Int_t zone=fNzone-1;
189 for (Int_t iZone=fNzone-2;iZone>=0;iZone--)
190 {
191 for (Int_t iCut=0;iCut<fNZoneCut[iZone];iCut++)
192 if ( aY<=fZoneY[iZone][iCut] && aX<=fZoneX[iZone][iCut] )
193 {
194 zone=iZone;
195 break;
196 }
197 }
198 return zone;
199}
200
201void AliMUONSegmentationV1::
202SetHit(Float_t xhit, Float_t yhit)
203{
204// Find the wire position (center of charge distribution)
ecfa008b 205 fXhit=xhit;
206 fYhit=yhit;
a9e2aefa 207}
208
209void AliMUONSegmentationV1::
210SetPad(Int_t ix, Int_t iy)
211{
212// Set current pad position
ecfa008b 213 GetPadC(ix,iy,fX,fY);
a9e2aefa 214}
215
216
217void AliMUONSegmentationV1::SetPadCoord(Int_t iX, Int_t iY)
218{
219// Set current pad coordinates
ecfa008b 220GetPadC(iX,iY,fX,fY);
a9e2aefa 221 Float_t radius2;
ecfa008b 222 if ( ( (radius2=fX*fX+fY*fY) > frSensMax2 || radius2 < frSensMin2 )
a9e2aefa 223 && MorePads() )
224 NextPad();
225}
226
227void AliMUONSegmentationV1::FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
228{
229 //
230 // Find the wire position (center of charge distribution)
231 Float_t x0a=GetAnod(xhit);
ecfa008b 232 fXhit=x0a;
233 fYhit=yhit;
a9e2aefa 234 //
235 // and take fNsigma*sigma around this center
236 Float_t x01=x0a - dx;
237 Float_t x02=x0a + dx;
238 Float_t y01=yhit - dy;
239 Float_t y02=yhit + dy;
240
241 // Do not cross over frames...
242 if (x01 * x0a < 0)
243 x01 = TMath::Sign(fSensOffset, x0a);
244 if (x02 * x0a < 0)
245 x02 = TMath::Sign(fSensOffset, x0a);
246 if (y01 * yhit < 0)
247 y01 = TMath::Sign(fSensOffset, yhit);
248 if (y02 * yhit < 0)
249 y02 = TMath::Sign(fSensOffset, yhit);
250 //
251 // find the pads over which the charge distributes
ecfa008b 252 GetPadI(x01,y01,fIxmin,fIymin);
253 GetPadI(x02,y02,fIxmax,fIymax);
a9e2aefa 254 //
255 // Set current pad to lower left corner
ecfa008b 256 fIx=fIxmin;
257 fIy=fIymin;
258 SetPadCoord(fIx,fIy);
a9e2aefa 259}
260
261void AliMUONSegmentationV1::NextPad()
262{
263 //
264 // Step to next pad in integration region
ecfa008b 265 if (fIx != fIxmax) {
266 fIx++;
267 } else if (fIy != fIymax) {
268 fIx=fIxmin;
269 fIy++;
a9e2aefa 270 } else
271 printf("\n Error: Stepping outside integration region\n ");
ecfa008b 272 SetPadCoord(fIx,fIy);
a9e2aefa 273}
274
275Int_t AliMUONSegmentationV1::MorePads()
276{
277//
278// Are there more pads in the integration region
279
ecfa008b 280 if (fIx == fIxmax && fIy == fIymax) {
a9e2aefa 281 return 0;
282 } else {
283 return 1;
284 }
285}
286
287Int_t AliMUONSegmentationV1::IsParallel2(Int_t iX, Int_t iY)
288{
289// test if the pad is read in parallel for zone 2
290// iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
291// returns 1 or 2 if read in parallel,
292// according to the actual number in the chain, 0 else
293//
294// chainage is result is
295// 1 2 3 1 2 3 1 1 1 2 2 2 y
296// 7 8 9 10 11 12 0 0 0 0 0 0 ^
297// 4 5 6 4 5 6 1 1 1 2 2 2 +->x
298//
299
300 if (iY%3==1) return 0;
301 return (iX%6)/3+1;
302}
303
304Int_t AliMUONSegmentationV1::IsParallel3(Int_t iX, Int_t iY)
305{
306// test if the pad is read in parallel for zone 3
307// iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
308// returns 1,2 or 3 if read in parallel,
309// according to the actual number in the chain, 0 else
310//
311// chainage is result is
312//16 2 3 1 2 3 1 2 3 0 1 1 1 2 2 2 3 3
313// 7 8 9 10 11 12 13 14 15 0 0 0 0 0 0 0 0 0
314// 4 5 6 4 5 6 4 5 6 1 1 1 2 2 2 3 3 3
315//
316
317 if (iY%3==1) return 0;
318 return (iX%9)/3+1 - (iY%3==2 && iX%3==0);
319}
320
321Int_t AliMUONSegmentationV1::NParallel2(Int_t iX, Int_t iY)
322{
323// returns the number of pads connected in parallel for zone 2
324// iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
325//
326// result is
327// 2 2 2 2 2 2
328// 1 1 1 1 1 1
329// 2 2 2 2 2 2
330//
331
332 if (iY%3==1) return 1;
333 return 2;
334}
335
336Int_t AliMUONSegmentationV1::NParallel3(Int_t iX, Int_t iY)
337{
338// test if the pad is read in parallel for zone 3
339// iX and iY are assumed to be positive and starting at 0 numbering (cF. iX)
340// returns 1,2 or 3 if read in parallel,
341// according to the actual number in the chain, 0 else
342//
343// result is
344// 1 3 3 2 3 3 2 3 3
345// 1 1 1 1 1 1 1 1 1
346// 3 3 3 3 3 3 3 3 3
347//
348
349 if (iY%3==1) return 1;
350 if (iY%3==2 && iX%9==0) return 1;
351 return 3 - (iY%3==2 && iX%3==0);
352}
353
354
355Int_t AliMUONSegmentationV1::Ix(Int_t trueX, Int_t trueY)
356{
357// returns the X number of pad which corresponds to the logical
358// channel, expressed in x and y.
359
360 Int_t wix = TMath::Abs(trueX)-1;
361 Int_t wiy = TMath::Abs(trueY)-1;
362 Int_t zone = GetZone(trueX,trueY);
363 Int_t par3;
364 switch (zone) {
365 case 0: return trueX;
366 case 1:
367 if (IsParallel2(wix,wiy) == 2)
368 return (trueX>0)? trueX-3 : trueX+3 ;
369 return trueX;
370 case 2:
371 if ( (par3= IsParallel3(wix,wiy)) )
372 return (trueX>0) ? trueX-3*(par3-1) : trueX+3*(par3-1) ;
373 return trueX ;
374 default :
375 printf("Couille dans AliMUONSegmentationV1::ix\n");
376 }
377 return -1;
378}
379
c3eff6ad 380Int_t AliMUONSegmentationV1::Ix()
a9e2aefa 381{
382// returns the X number of pad which has to increment charge
383// due to parallel read-out
c3eff6ad 384 return Ix(fIx,fIy);
a9e2aefa 385}
386
c3eff6ad 387Int_t AliMUONSegmentationV1::ISector()
a9e2aefa 388{
389// This function is of no use for this kind of segmentation.
ecfa008b 390 return GetZone(fIx,fIy);
a9e2aefa 391}
392
393void AliMUONSegmentationV1::SigGenInit(Float_t x,Float_t y,Float_t z)
394{
395//
396// Initialises pad and wire position during stepping
ecfa008b 397 fXt =x;
398 fYt =y;
399 GetPadI(x,y,fIxt,fIyt);
400 fIwt= GetiAnod(x);
a9e2aefa 401
402}
403
404Int_t AliMUONSegmentationV1::SigGenCond(Float_t x,Float_t y,Float_t z)
405{
406//
407// Signal will be generated if particle crosses pad boundary or
408// boundary between two wires.
409 Int_t ixt;
410 Int_t iyt;
a30a000f 411 GetPadI(x,y,ixt,iyt);
a9e2aefa 412 Int_t iwt= GetiAnod(x);
413
ecfa008b 414 if ((ixt != fIxt) || (iyt !=fIyt) || (iwt != fIwt)) {
a9e2aefa 415 return 1;
416 } else {
417 return 0;
418 }
419}
420
421void AliMUONSegmentationV1::
422IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
423{
424// Get integration limits
ecfa008b 425 x1=fXhit-fX-fDpx/2.;
a9e2aefa 426 x2=x1+fDpx;
ecfa008b 427 y1=fYhit-fY-fDpy/2.;
a9e2aefa 428 y2=y1+fDpy;
429}
430
431void AliMUONSegmentationV1::GetNParallelAndOffset(Int_t iX, Int_t iY,Int_t
432*Nparallel, Int_t* Offset)
433{
434// Get parallel pad
435 Int_t wix = TMath::Abs(iX)-1;
436 Int_t wiy = TMath::Abs(iY)-1;
437 Int_t zone = GetZone(iX,iY);
438 switch (zone) {
439 case 0:
440 *Nparallel=1;
441 *Offset=0;
442 break;
443 case 1:
444 *Nparallel = NParallel2(wix,wiy);
445 (iX>0) ? *Offset =3 : *Offset = -3;
446 if (IsParallel2(wix,wiy)>1)
447 printf("GetNParallelAndOffset called for existing channel -> answer is crazy\n");
448 break;
449 case 2:
450 *Nparallel = NParallel3(wix,wiy);
451 (iX>0) ? *Offset =3 : *Offset = -3;
452 if (IsParallel3(wix,wiy)>1)
453 printf("GetNParallelAndOffset called for existing channel -> answer is crazy\n");
454 break;
455 }
456}
457
458
459Float_t AliMUONSegmentationV1::Distance2AndOffset(Int_t iX, Int_t iY, Float_t X, Float_t Y, Int_t *Offset)
460{
461//
462// Computes the offset for which the physical pad has the minimum distance squared
463// (returned value) to the given coordinates
464
465 Int_t nPara,offset;
466 GetNParallelAndOffset(iX,iY,&nPara,&offset);
467 Float_t d2min=1E10;
468 for (Int_t i=0;i<nPara; i++)
469 {
470 Float_t x,y;
a30a000f 471 GetPadC(iX+i*offset,iY,x,y);
a9e2aefa 472 Float_t d2=(x-X)*(x-X) + (y-Y)*(y-Y);
473 if ( d2min > d2)
474 {
475 d2min = d2;
476 *Offset = i*offset;
477 }
478 }
479 return d2min;
480}
481
482void AliMUONSegmentationV1::CleanNeighbours(Int_t* Nlist, Int_t *Xlist,
483 Int_t *Ylist)
484{
485// In the raw neighbours list, some pads do not exist
486// and some others are read in parallel ...
487// So we prune non-existing neighbours from the list (event if this should be
488// at last not be a problem due to the clustering algorithm...)
489
490 Int_t nTot=0;
491 for (Int_t nList=0;nList<*Nlist;nList++)
492 {
493 // prune if it does not exist
494 if ( Xlist[nList]==0 || Ylist[nList]==0 )
495 continue;
496 // compute true position
497 Xlist[nTot] = Ix(Xlist[nList],Ylist[nList]) ;
498 Ylist[nTot] = Ylist[nList] ;
499 // and prune if it does already exist
500 Int_t nTest;
501 for (nTest=0;nTest<nTot; nTest++)
502 {
503 if ( Xlist[nTest]==Xlist[nTot] && Ylist[nTest]==Ylist[nTot])
504 // we found it
505 break ;
506 }
507 if (nTest==nTot)
508 nTot++;
509 }
510 *Nlist = nTot;
511}
512
513void AliMUONSegmentationV1::
514NeighboursNonDiag(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[12], Int_t Ylist[12])
515{
516// returns the X number of pad which has to increment charge
517// due to parallel read-out
518
519 Int_t nParallel, offset;
520 GetNParallelAndOffset(iX,iY,&nParallel,&offset);
521//
522// now fill raw list of neighbours
523 *Nlist=4*nParallel;
524 Xlist[0]=Xlist[1]=iX;Xlist[2]=iX-1;Xlist[3]=iX+1;
525 Ylist[0]=iY-1;Ylist[1]=iY+1;Ylist[2]=Ylist[3]=iY;
526 if (nParallel>1) {
527 Xlist[4]=Xlist[5]=iX+offset;Xlist[6]=iX+offset-1;Xlist[7]=iX+offset+1;
528 Ylist[4]=iY-1;Ylist[5]=iY+1;Ylist[6]=Ylist[7]=iY;
529 if (nParallel>2) {
530 Xlist[8]=Xlist[9]=iX+2*offset;Xlist[10]=iX+2*offset-1;Xlist[11]=iX+2*offset+1;
531 Ylist[8]=iY-1;Ylist[9]=iY+1;Ylist[10]=Ylist[11]=iY;
532 }
533 }
534 CleanNeighbours(Nlist,Xlist,Ylist);
535}
536
537void AliMUONSegmentationV1::
538NeighboursDiag(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[24], Int_t Ylist[24])
539{
540// returns the X number of pad which has to increment charge
541// due to parallel read-out
542
543 Int_t nParallel, offset;
544 GetNParallelAndOffset(iX,iY,&nParallel,&offset);
545//
546// now fill raw list of neighbours
547 *Nlist=0;
548 for (Int_t i=0;i<nParallel;i++)
549 for (Int_t dx=-1;dx<2;dx++)
550 for (Int_t dy=-1;dy<2;dy++)
551 {
552 if (dx==dy && dy==0)
553 continue;
554 Xlist[*Nlist] = iX + dx + i*offset;
555 Ylist[*Nlist] = iY + dy;
556 (*Nlist)++;
557 }
558 CleanNeighbours(Nlist,Xlist,Ylist);
559}
560
561void AliMUONSegmentationV1::Neighbours(Int_t iX, Int_t iY, Int_t* Nlist,
562 Int_t Xlist[24], Int_t Ylist[24])
563{
564// Get neighbours
565NeighboursDiag(iX,iY,Nlist,Xlist,Ylist);
566}
567
568
c3eff6ad 569void AliMUONSegmentationV1::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) const
a9e2aefa 570{
571// Return a test point
572 n=1;
573 x[0]=(TMath::Sqrt(frSensMax2)-TMath::Sqrt(frSensMin2))/2/TMath::Sqrt(2.);
574 y[0]=x[0];
575}
576
577AliMUONSegmentationV1& AliMUONSegmentationV1::operator =(const AliMUONSegmentationV1 & rhs)
578{
579// Dummy assignment operator
580 return *this;
581}