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