Initialisation of some pointers
[u/mrichter/AliRoot.git] / MUON / AliMUONSegmentationV1.cxx
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$
18 Revision 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
22 Revision 1.6  2000/10/03 21:48:07  morsch
23 Adopt to const declaration of some of the methods in AliSegmentation.
24
25 Revision 1.5  2000/10/02 16:58:29  egangler
26 Cleaning of the code :
27 -> coding conventions
28 -> void Streamers
29 -> some useless includes removed or replaced by "class" statement
30
31 Revision 1.4  2000/07/03 11:54:57  morsch
32 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
33 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
34
35 Revision 1.3  2000/06/29 12:34:09  morsch
36 AliMUONSegmentation class has been made independent of AliMUONChamber. This makes
37 it usable with any other geometry class. The link to the object to which it belongs is
38 established via an index. This assumes that there exists a global geometry manager
39 from which the pointer to the parent object can be obtained (in our case gAlice).
40
41 Revision 1.2  2000/06/15 07:58:48  morsch
42 Code from MUON-dev joined
43
44 Revision 1.1.2.2  2000/06/12 07:57:43  morsch
45 include TMath.cxx
46
47 Revision 1.1.2.1  2000/06/09 21:41:29  morsch
48 AliMUONSegmentationV1 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"
60 #include "AliRun.h"
61 #include "AliMUON.h"
62 #include "AliMUONChamber.h"
63
64 //___________________________________________
65 ClassImp(AliMUONSegmentationV1)
66
67 AliMUONSegmentationV1::AliMUONSegmentationV1(const AliMUONSegmentationV1& segmentation)
68 {
69 // Dummy copy constructor
70 }
71
72
73 AliMUONSegmentationV1::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;
83     fCorr = 0;
84 }
85
86
87 void AliMUONSegmentationV1::Init(Int_t chamber)
88 {
89     // valid only for T5/6
90     // beware : frMin is SENSITIVE radius by definition.
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;
98     //    fNwire=3;
99     DefaultCut();
100     fCorr=0;
101
102     fZ = iChamber->Z();
103
104 }
105
106 void 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
124 Int_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
131 Float_t AliMUONSegmentationV1::GetAnod(Float_t xhit) const
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
139 void 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
146 void AliMUONSegmentationV1::
147 GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
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
155 void AliMUONSegmentationV1::
156 GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
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
164 void 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
175 Int_t AliMUONSegmentationV1::GetZone(Float_t X, Float_t Y)
176 {
177 // Get segmentation zone
178     Int_t iX, iY;
179     GetPadI(X,Y,iX,iY);
180     return GetZone( iX , iY );
181 }
182
183 Int_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
201 void AliMUONSegmentationV1::
202 SetHit(Float_t xhit, Float_t yhit)
203 {
204 // Find the wire position (center of charge distribution)
205     fXhit=xhit;
206     fYhit=yhit;
207 }
208
209 void AliMUONSegmentationV1::
210 SetPad(Int_t ix, Int_t iy)
211 {
212 // Set current pad position
213     GetPadC(ix,iy,fX,fY);
214 }
215
216
217 void AliMUONSegmentationV1::SetPadCoord(Int_t iX, Int_t iY)
218 {    
219 // Set current pad coordinates
220 GetPadC(iX,iY,fX,fY);
221  Float_t radius2;
222  if ( ( (radius2=fX*fX+fY*fY) > frSensMax2 || radius2 < frSensMin2 ) 
223       && MorePads() )
224      NextPad();
225 }
226
227 void 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);
232     fXhit=x0a;
233     fYhit=yhit;
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
252     GetPadI(x01,y01,fIxmin,fIymin);
253     GetPadI(x02,y02,fIxmax,fIymax);
254     // 
255     // Set current pad to lower left corner
256     fIx=fIxmin;
257     fIy=fIymin;
258     SetPadCoord(fIx,fIy);
259 }
260
261 void AliMUONSegmentationV1::NextPad()
262 {
263   // 
264   // Step to next pad in integration region
265     if (fIx != fIxmax) {
266         fIx++;
267     } else if (fIy != fIymax) {
268         fIx=fIxmin;
269         fIy++;
270     } else 
271         printf("\n Error: Stepping outside integration region\n ");
272     SetPadCoord(fIx,fIy);
273 }
274
275 Int_t AliMUONSegmentationV1::MorePads()
276 {
277 //
278 // Are there more pads in the integration region
279
280     if (fIx == fIxmax && fIy == fIymax) {
281         return 0;
282     } else {
283         return 1;       
284     }
285 }
286
287 Int_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
304 Int_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
321 Int_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
336 Int_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
355 Int_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
380 Int_t AliMUONSegmentationV1::Ix() 
381 {
382 // returns the X number of pad which has to increment charge
383 // due to parallel read-out
384     return Ix(fIx,fIy);
385 }
386
387 Int_t AliMUONSegmentationV1::ISector() 
388 {
389 // This function is of no use for this kind of segmentation.
390     return GetZone(fIx,fIy);
391 }
392
393 void AliMUONSegmentationV1::SigGenInit(Float_t x,Float_t y,Float_t z)
394 {
395 //
396 //  Initialises pad and wire position during stepping
397     fXt =x;
398     fYt =y;
399     GetPadI(x,y,fIxt,fIyt);
400     fIwt= GetiAnod(x);
401
402 }
403
404 Int_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;
411     GetPadI(x,y,ixt,iyt);
412     Int_t iwt= GetiAnod(x);
413     
414     if ((ixt != fIxt) || (iyt !=fIyt) || (iwt != fIwt)) {
415         return 1;
416     } else {
417         return 0;
418     }
419 }
420
421 void AliMUONSegmentationV1::
422 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
423 {
424 // Get integration limits
425     x1=fXhit-fX-fDpx/2.;
426     x2=x1+fDpx;
427     y1=fYhit-fY-fDpy/2.;
428     y2=y1+fDpy;    
429 }
430
431 void 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
459 Float_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;
471         GetPadC(iX+i*offset,iY,x,y);
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
482 void 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
513 void AliMUONSegmentationV1::
514 NeighboursNonDiag(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
537 void AliMUONSegmentationV1::
538 NeighboursDiag(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
561 void AliMUONSegmentationV1::Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, 
562                                        Int_t Xlist[24], Int_t Ylist[24])
563 {
564 // Get neighbours
565 NeighboursDiag(iX,iY,Nlist,Xlist,Ylist);
566 }
567
568
569 void AliMUONSegmentationV1::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) const
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
577 AliMUONSegmentationV1& AliMUONSegmentationV1::operator =(const AliMUONSegmentationV1 & rhs)
578 {
579 // Dummy assignment operator
580     return *this;
581 }