Small correction to prevent crash when hit is at the edge of a slat
[u/mrichter/AliRoot.git] / MUON / AliMUONSegmentationSlat.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.15  2001/09/07 08:38:30  hristov
19 Pointers initialised to 0 in the default constructors
20
21 Revision 1.14  2001/08/30 09:52:12  hristov
22 The operator[] is replaced by At() or AddAt() in case of TObjArray.
23
24 Revision 1.13  2001/07/20 10:03:14  morsch
25 Changes needed to work with Root 3.01 (substitute lhs [] operator). (Jiri Chudoba)
26
27 Revision 1.12  2001/05/16 14:57:17  alibrary
28 New files for folders and Stack
29
30 Revision 1.11  2001/01/26 21:25:48  morsch
31 Empty default constructors and.
32
33 Revision 1.10  2001/01/23 18:58:19  hristov
34 Initialisation of some pointers
35
36 Revision 1.9  2001/01/17 20:53:40  hristov
37 Destructors corrected to avoid memory leaks
38
39 Revision 1.8  2000/12/21 22:12:41  morsch
40 Clean-up of coding rule violations,
41
42 Revision 1.7  2000/11/08 13:01:40  morsch
43 Chamber half-planes of stations 3-5 at different z-positions.
44
45 Revision 1.6  2000/11/06 09:20:43  morsch
46 AliMUON delegates part of BuildGeometry() to AliMUONSegmentation using the
47 Draw() method. This avoids code and parameter replication.
48
49 Revision 1.5  2000/10/23 13:37:40  morsch
50 Correct z-position of slat planes.
51
52 Revision 1.4  2000/10/22 16:55:43  morsch
53 Use only x-symmetry in global to local transformations and delegation.
54
55 Revision 1.3  2000/10/18 11:42:06  morsch
56 - AliMUONRawCluster contains z-position.
57 - Some clean-up of useless print statements during initialisations.
58
59 Revision 1.2  2000/10/09 14:06:18  morsch
60 Some type cast problems of type  (TMath::Sign((Float_t)1.,x)) corrected (P.H.)
61
62 Revision 1.1  2000/10/06 09:00:47  morsch
63 Segmentation class for chambers built out of slats.
64
65 */
66
67 #include "AliMUONSegmentationSlat.h"
68 #include "AliMUONSegmentationSlatModule.h"
69 #include "AliMUON.h"
70 #include "AliMUONChamber.h"
71 #include "TArrayI.h"
72 #include "TObjArray.h"
73 #include "AliRun.h"
74 #include <TMath.h>
75 #include <TBRIK.h>
76 #include <TNode.h>
77 #include <TGeometry.h>
78 #include <iostream.h>
79
80 //___________________________________________
81 ClassImp(AliMUONSegmentationSlat)
82
83 AliMUONSegmentationSlat::AliMUONSegmentationSlat() 
84 {
85 // Default constructor
86   fChamber = 0;
87   fNDiv = 0;
88   fSlats = 0;
89   fCurrentSlat = 0;
90 }
91
92 AliMUONSegmentationSlat::AliMUONSegmentationSlat(Int_t nsec) 
93 {
94 // Non default constructor
95     fSlats=0;            
96     fNDiv = new TArrayI(4);
97     fChamber = 0;
98     fCurrentSlat = 0;
99 }
100
101 AliMUONSegmentationSlat::~AliMUONSegmentationSlat(){
102   //PH Delete TObjArrays
103   if (fSlats) {
104     fSlats->Delete();
105     delete fSlats;
106   }
107
108   if (fNDiv) {
109     delete fNDiv;
110   }
111
112 }
113
114 void AliMUONSegmentationSlat::SetPadSize(Float_t p1, Float_t p2)
115 {
116 //  Sets the pad (strip) size 
117 //  
118     fDpx=p1;
119     fDpy=p2;
120 }
121
122 Float_t AliMUONSegmentationSlat::GetAnod(Float_t xhit) const
123 {
124 // Returns for a hit position xhit the position of the nearest anode wire    
125     Float_t wire= (xhit>0)? Int_t(xhit/fWireD)+0.5:Int_t(xhit/fWireD)-0.5;
126     return fWireD*wire;
127 }
128
129 Float_t AliMUONSegmentationSlat::Dpx(Int_t isec) const
130 {
131 //
132 // Returns x-pad size for given sector isec
133 // isec = 100*islat+iregion
134 //
135     Int_t islat, iregion;
136     islat    = isec/100;
137     iregion  = isec%100;
138     return Slat(islat)->Dpx(iregion);
139 }
140
141 Float_t AliMUONSegmentationSlat::Dpy(Int_t isec) const
142 {
143 //
144 // Returns y-pad (strip)  size for given sector isec
145    return fDpy;
146 }
147
148 void AliMUONSegmentationSlat::SetPadDivision(Int_t ndiv[4])
149 {
150 //
151 // Defines the pad size perp. to the anode wire (y) for different sectors. 
152 // Pad sizes are defined as integral fractions ndiv of a basis pad size
153 // fDpx
154 // 
155     for (Int_t i=0; i<4; i++) {
156         (*fNDiv)[i]=ndiv[i];
157     }
158 }
159
160 void AliMUONSegmentationSlat::GlobalToLocal(
161     Float_t x, Float_t y, Float_t z, Int_t &islat, Float_t &xlocal, Float_t &ylocal)
162 {
163 //
164 // Perform local to global transformation for space coordinates
165 //
166     Float_t zlocal;
167     Int_t i;
168     Int_t index=-1;
169 // Transform According to slat plane z-position: negative side is shifted down 
170 //                                                 positive side is shifted up
171 // by half the overlap
172     zlocal = z-fChamber->Z();
173     zlocal = (x>0) ? zlocal-2.*fDz : zlocal+2.*fDz;
174 //  Set the signs for the symmetry transformation and transform to first quadrant
175     SetSymmetry(x);
176     Float_t xabs=TMath::Abs(x);
177
178     Int_t ifirst = (zlocal < Float_t(0))? 0:1;
179 //
180 // Find slat number                      
181     for (i=ifirst; i<fNSlats; i+=2) {
182         index=i;
183         if ((y >= fYPosition[i]) && (y <= fYPosition[i]+fSlatY)) break;
184     }
185     
186 //
187 // Transform to local coordinate system
188
189     
190     ylocal = y   -fYPosition[index];
191     xlocal = xabs-fXPosition[index];
192     islat  = index;
193     if (i >= fNSlats) {islat = -1; x=-1; y = -1;}
194 }
195
196 void AliMUONSegmentationSlat::GlobalToLocal(
197     Int_t ix, Int_t iy, Int_t &islat, Int_t &ixlocal, Int_t &iylocal)
198 {
199 //
200 // Perform global to local transformation for pad coordinates
201 //
202     Int_t iytemp = iy;
203     Int_t index  =  0;
204     
205     iylocal = iytemp;
206
207 //
208 // Find slat number (index) and iylocal  
209     for (Int_t i=0; i<fNSlats; i++) {
210         iytemp-=Slat(i)->Npy();
211         
212         
213         if (iytemp <= 0) break;
214         iylocal = iytemp;
215         index=i+1;
216     }
217
218     ixlocal=TMath::Abs(ix);
219     islat=index;
220 }
221
222 void AliMUONSegmentationSlat::
223 LocalToGlobal(Int_t islat, Float_t  xlocal, Float_t  ylocal, Float_t  &x, Float_t  &y, Float_t &z)
224 {
225 // Transform from local to global space coordinates
226 //
227 // upper plane (y>0) even slat number is shifted down
228 // upper plane (y>0)  odd slat number is shifted up 
229 // lower plane (y<0) even slat number is shifted up
230 // lower plane (y<0)  odd slat number is shifted down
231 //
232
233     x = (xlocal+fXPosition[islat])*fSym;
234     y=(ylocal+fYPosition[islat]);
235
236     z = (TMath::Even(islat)) ?     -fDz : fDz ; 
237     z = (x>0)                ? z+2.*fDz : z-2.*fDz ; 
238
239     z+=fChamber->Z();
240 }
241
242
243 void AliMUONSegmentationSlat::LocalToGlobal(
244     Int_t islat, Int_t ixlocal, Int_t iylocal, Int_t &ix, Int_t &iy)
245 {
246 // Transform from local to global pad coordinates
247 //
248     Int_t i;
249     iy=iylocal;
250     
251 //
252 // Find slat number (index) and iylocal  
253     for (i=0; i<islat; i++) iy+=Slat(islat)->Npy();
254
255     ix=ixlocal*fSym;
256     iy=iy;
257 }
258
259
260 void AliMUONSegmentationSlat::SetSymmetry(Int_t   ix)
261 {
262 // Set set signs for symmetry transformation
263     fSym=TMath::Sign(1,ix);
264 }
265
266 void AliMUONSegmentationSlat::SetSymmetry(Float_t  x)
267 {
268 // Set set signs for symmetry transformation
269     fSym=Int_t (TMath::Sign((Float_t)1.,x));
270 }
271
272 void AliMUONSegmentationSlat::
273 GetPadI(Float_t x, Float_t y, Float_t z, Int_t &ix, Int_t &iy)
274 {
275 // Returns pad coordinates for given set of space coordinates
276
277     Int_t islat, i;
278     Float_t xlocal, ylocal;
279     
280     GlobalToLocal(x,y,z,islat,xlocal,ylocal);
281     if (islat == -1) {
282         ix=0; iy=0; return;
283     }
284     
285     Slat(islat)->GetPadI(xlocal, ylocal, ix, iy);
286     for (i=0; i<islat; i++) iy+=Slat(islat)->Npy();
287
288     ix=ix*Int_t(TMath::Sign((Float_t)1.,x));    
289 }
290
291
292 void AliMUONSegmentationSlat::
293 GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y, Float_t &z)
294 {
295 //  Returns real coordinates (x,y) for given pad coordinates (ix,iy)
296 //
297     Int_t islat, ixlocal, iylocal;
298 //
299 // Delegation of transforamtion to slat
300     GlobalToLocal(ix,iy,islat,ixlocal,iylocal);
301     Slat(islat)->GetPadC(ixlocal, iylocal, x, y);
302 // Slat offset
303     x+=fXPosition[islat];
304     y+=fYPosition[islat];    
305
306 // Symmetry transformation of half planes
307     x=x*TMath::Sign(1,ix);
308
309 // z-position
310     z = (TMath::Even(islat)) ?      -fDz : fDz ; 
311     z = (x>0)                ?  z+2.*fDz : z-2.*fDz ; 
312     z += fChamber->Z();
313 }
314
315 Int_t AliMUONSegmentationSlat::ISector()
316 {
317 // Returns current sector during tracking
318     Int_t iregion;
319     
320     iregion =  fCurrentSlat->ISector();
321     return 100*fSlatIndex+iregion;
322 }
323
324 Int_t AliMUONSegmentationSlat::Sector(Int_t ix, Int_t iy)
325 {
326 // Returns sector for pad coordiantes (ix,iy)
327     Int_t ixlocal, iylocal, iregion, islat;
328
329     GlobalToLocal(ix,iy,islat,ixlocal,iylocal);
330     
331     iregion =  Slat(islat)->Sector(ixlocal, iylocal);
332     return 100*islat+iregion;
333 }
334
335
336 void AliMUONSegmentationSlat::SetPad(Int_t ix, Int_t iy)
337 {
338     //
339     // Sets virtual pad coordinates, needed for evaluating pad response 
340     // outside the tracking program
341     Int_t islat, ixlocal, iylocal;
342
343     SetSymmetry(ix);
344     
345     GlobalToLocal(ix,iy,islat,ixlocal,iylocal);
346     fSlatIndex=islat;
347     fCurrentSlat=Slat(islat);
348     fCurrentSlat->SetPad(ixlocal, iylocal);
349 }
350
351 void  AliMUONSegmentationSlat::SetHit(Float_t xhit, Float_t yhit, Float_t zhit)
352 {   //
353     // Sets current hit coordinates
354
355     Float_t xlocal, ylocal;
356     Int_t islat;
357
358     
359
360     GlobalToLocal(xhit,yhit,zhit,islat,xlocal,ylocal);
361     fSlatIndex=islat;
362     if (islat < 0) printf("\n SetHit: %d", islat);
363     
364     fCurrentSlat=Slat(islat);
365     fCurrentSlat->SetHit(xlocal, ylocal);
366 }
367
368
369 void AliMUONSegmentationSlat::
370 FirstPad(Float_t xhit, Float_t yhit, Float_t zhit, Float_t dx, Float_t dy)
371 {
372 // Initialises iteration over pads for charge distribution algorithm
373 //
374
375
376
377     Int_t islat;
378     Float_t xlocal, ylocal;
379     GlobalToLocal(xhit, yhit, zhit, islat, xlocal, ylocal);
380     fSlatIndex=islat;
381     fCurrentSlat=Slat(islat);
382     fCurrentSlat->FirstPad(xlocal, ylocal, dx, dy);
383
384 }
385
386
387 void AliMUONSegmentationSlat::NextPad()
388 {
389 // Stepper for the iteration over pads
390 //
391     fCurrentSlat->NextPad();
392 }
393
394
395 Int_t AliMUONSegmentationSlat::MorePads()
396 // Stopping condition for the iterator over pads
397 //
398 // Are there more pads in the integration region
399
400     return fCurrentSlat->MorePads();
401 }
402
403 void AliMUONSegmentationSlat::
404 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
405 {
406 //  Returns integration limits for current pad
407 //
408     
409     fCurrentSlat->IntegrationLimits(x1, x2, y1, y2);
410
411 }
412
413 void AliMUONSegmentationSlat::
414 Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])
415 {
416 // Returns list of neighbours of pad with coordinates iX, iY
417
418     Int_t i, xListLocal[10], yListLocal[10], iXlocal, iYlocal, islat;
419     
420     SetSymmetry(iX);
421
422     GlobalToLocal(iX, iY, islat, iXlocal, iYlocal);
423  
424     Slat(islat)->Neighbours(iXlocal, iYlocal, Nlist, xListLocal, yListLocal);
425     
426     for (i=0; i<*Nlist; i++) LocalToGlobal(islat, xListLocal[i], yListLocal[i], Xlist[i], Ylist[i]);
427
428 }
429
430
431 Int_t  AliMUONSegmentationSlat::Ix()
432 {
433 // Return current pad coordinate ix during stepping
434     Int_t ixl,iyl,ix,iy;
435     ixl=fCurrentSlat->Ix();
436     iyl=fCurrentSlat->Iy();
437     
438     LocalToGlobal(fSlatIndex, ixl, iyl, ix, iy);
439     Int_t ixc, iyc, isc;
440     Float_t xc, yc;
441     GlobalToLocal(ix, iy, isc, ixc, iyc);
442     Slat(isc)->GetPadC(ixc,iyc,xc,yc);
443     return ix;
444 }
445
446
447 Int_t  AliMUONSegmentationSlat::Iy()
448 {
449 // Return current pad coordinate iy during stepping
450     Int_t ixl,iyl,ix,iy;
451     ixl=fCurrentSlat->Ix();
452     iyl=fCurrentSlat->Iy();
453     LocalToGlobal(fSlatIndex, ixl, iyl, ix, iy);
454     return iy;
455 }
456
457
458
459    // Signal Generation Condition during Stepping
460 Int_t AliMUONSegmentationSlat::SigGenCond(Float_t x, Float_t y, Float_t z)
461
462 //
463 //  True if signal generation condition fullfilled
464     Float_t xlocal, ylocal;
465     Int_t islat;
466     GlobalToLocal(x, y, z, islat, xlocal, ylocal);
467     return Slat(islat)->SigGenCond(xlocal, ylocal, z);
468 }
469
470 // Initialise signal generation at coord (x,y,z)
471 void  AliMUONSegmentationSlat::SigGenInit(Float_t x, Float_t y, Float_t z)
472 {
473 // Initialize the signal generation condition
474 //
475     Float_t xlocal, ylocal;
476     Int_t islat;
477
478     GlobalToLocal(x, y, z, islat, xlocal, ylocal);
479     Slat(islat)->SigGenInit(xlocal, ylocal, z);
480 }
481
482
483
484 void AliMUONSegmentationSlat::Init(Int_t chamber)
485 {
486 //    
487 // Initialize slat modules of quadrant +/+    
488 // The other three quadrants are handled through symmetry transformations
489 //
490   //printf("\n Initialise Segmentation Slat \n");
491 //
492
493 // Initialize Slat modules
494     Int_t islat, i;
495     Int_t ndiv[4];
496 // Pad division
497     for (i=0; i<4; i++) ndiv[i]=(*fNDiv)[i];
498 //
499     fDz=0.813;
500 // Slat height    
501     fSlatY=40.;
502     for (i=0; i<15; i++) fSlatX[i]=0.;
503     
504 // Initialize array of slats 
505     fSlats  = new TObjArray(fNSlats);
506 // Maximum number of strips (pads) in x and y
507     fNpy=0;   
508     fNpx=0;
509 // for each slat in the quadrant (+,+)    
510     for (islat=0; islat<fNSlats; islat++) {
511         fSlats->AddAt(CreateSlatModule(),islat);
512
513         AliMUONSegmentationSlatModule *slat =  Slat(islat);
514         // Configure Slat
515         slat->SetId(islat);
516         
517 // Foward pad size
518         slat->SetPadSize(fDpx, fDpy);
519 // Forward wire pitch
520         slat->SetDAnod(fWireD);
521 // Foward segmentation 
522         slat->SetPadDivision(ndiv);
523         slat->SetPcbBoards(fPcb[islat]);
524 // Initialize slat module
525         slat->Init(chamber);
526 // y-position of slat module relative to the first (closest to the beam)
527         fYPosition[islat]= fYPosOrigin+islat*(fSlatY-2.*fShift);
528 //
529         fNpy+=slat->Npy();
530         if (slat->Npx() > fNpx) fNpx=slat->Npx();
531         Int_t isec;
532         for (isec=0; isec< 4; isec++)
533         {
534             fSlatX[islat]+=40.*fPcb[islat][isec];
535         }
536         
537     }
538 // Set parent chamber number
539     AliMUON *pMUON  = (AliMUON *) gAlice->GetModule("MUON");
540     fChamber=&(pMUON->Chamber(chamber));
541     fId=chamber;
542 }
543
544
545
546
547
548 void AliMUONSegmentationSlat::SetNPCBperSector(Int_t *npcb)
549
550     //  PCB distribution for station 4 (6 rows with 1+3 segmentation regions)
551     for (Int_t islat=0; islat<fNSlats; islat++){ 
552         fPcb[islat][0] = *(npcb + 4 * islat);
553         fPcb[islat][1] = *(npcb + 4 * islat + 1);
554         fPcb[islat][2] = *(npcb + 4 * islat + 2);
555         fPcb[islat][3] = *(npcb + 4 * islat + 3);
556     }
557 }
558
559
560 void  AliMUONSegmentationSlat::SetSlatXPositions(Float_t *xpos)
561 {
562 // Set x-positions of Slats
563     for (Int_t islat=0; islat<fNSlats; islat++) fXPosition[islat]=xpos[islat];
564 }
565
566 AliMUONSegmentationSlatModule*  AliMUONSegmentationSlat::Slat(Int_t index) const
567   //PH { return ((AliMUONSegmentationSlatModule*) (*fSlats)[index]);}
568 { return ((AliMUONSegmentationSlatModule*) fSlats->At(index));}
569
570
571 AliMUONSegmentationSlatModule* AliMUONSegmentationSlat::
572 CreateSlatModule()
573 {
574     // Factory method for slat module
575     return new AliMUONSegmentationSlatModule(4);
576 }
577
578
579 void AliMUONSegmentationSlat::Draw(const char* opt) const
580 {
581 // Draw method for event display
582 // 
583   if (!strcmp(opt,"eventdisplay")) { 
584     const int kColorMUON1 = kYellow;
585     const int kColorMUON2 = kBlue; 
586     //
587     //  Drawing Routines for example for Event Display
588     Int_t i,j;
589     Int_t npcb[15];
590     char nameChamber[9], nameSlat[9], nameNode[9];
591     
592     //
593     // Number of modules per slat
594     for (i=0; i<fNSlats; i++) {
595       npcb[i]=0;
596       for (j=0; j<4; j++) npcb[i]+=fPcb[i][j];
597     }  
598     //
599     TNode* top=gAlice->GetGeometry()->GetNode("alice");
600     sprintf(nameChamber,"C_MUON%d",fId+1);
601     new TBRIK(nameChamber,"Mother","void",340,340,5.);
602     top->cd();
603     sprintf(nameNode,"MUON%d",100+fId+1);
604     TNode* node = new TNode(nameNode,"Chambernode",nameChamber,0,0,fChamber->Z(),"");
605     
606     node->SetLineColor(kBlack);
607     AliMUON *pMUON  = (AliMUON *) gAlice->GetModule("MUON");
608     (pMUON->Nodes())->Add(node);
609     TNode* nodeSlat;
610     Int_t color;
611     
612     for (j=0; j<fNSlats; j++)
613       {
614         sprintf(nameSlat,"SLAT%d",100*fId+1+j);
615         Float_t dx = 20.*npcb[j];
616         Float_t dy = 20;
617         new TBRIK(nameSlat,"Slat Module","void",dx,20.,0.25);
618         node->cd();
619         color =  TMath::Even(j) ? kColorMUON1 : kColorMUON2;
620         
621         sprintf(nameNode,"SLAT%d",100*fId+1+j);
622         nodeSlat = 
623           new TNode(nameNode,"Slat Module",nameSlat, dx+fXPosition[j],fYPosition[j]+dy,0,"");
624         nodeSlat->SetLineColor(color);
625         node->cd();
626         sprintf(nameNode,"SLAT%d",100*fId+1+j+fNSlats);
627         nodeSlat = 
628           new TNode(nameNode,"Slat Module",nameSlat,-dx-fXPosition[j],fYPosition[j]+dy,0,"");
629         nodeSlat->SetLineColor(color);
630       }
631   }
632 }
633
634
635