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.15 2001/01/26 21:25:48 morsch
19 Empty default constructors and.
21 Revision 1.14 2000/12/21 22:12:41 morsch
22 Clean-up of coding rule violations,
24 Revision 1.13 2000/12/07 10:41:51 hristov
25 fCorr replaced by fCorrA
27 Revision 1.12 2000/12/06 11:55:41 morsch
28 Introduce SetOffsetY(Float_t off) method as simplified simulation of pad staggering.
29 fOffset is the staggering offset in y.
31 Revision 1.11 2000/11/06 09:20:43 morsch
32 AliMUON delegates part of BuildGeometry() to AliMUONSegmentation using the
33 Draw() method. This avoids code and parameter replication.
35 Revision 1.10 2000/10/18 11:42:06 morsch
36 - AliMUONRawCluster contains z-position.
37 - Some clean-up of useless print statements during initialisations.
39 Revision 1.9 2000/10/18 08:41:32 morsch
40 Make NextPad() and MorePads() to iterate until the end.
42 Revision 1.8 2000/10/03 21:48:07 morsch
43 Adopt to const declaration of some of the methods in AliSegmentation.
45 Revision 1.7 2000/10/02 21:28:09 fca
46 Removal of useless dependecies via forward declarations
48 Revision 1.6 2000/10/02 16:58:29 egangler
49 Cleaning of the code :
52 -> some useless includes removed or replaced by "class" statement
54 Revision 1.5 2000/07/13 16:19:44 fca
55 Mainly coding conventions + some small bug fixes
57 Revision 1.4 2000/07/03 11:54:57 morsch
58 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
59 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
61 Revision 1.3 2000/06/29 12:34:09 morsch
62 AliMUONSegmentation class has been made independent of AliMUONChamber. This makes
63 it usable with any other geometry class. The link to the object to which it belongs is
64 established via an index. This assumes that there exists a global geometry manager
65 from which the pointer to the parent object can be obtained (in our case gAlice).
67 Revision 1.2 2000/06/15 07:58:48 morsch
68 Code from MUON-dev joined
70 Revision 1.1.2.1 2000/06/09 21:37:30 morsch
71 AliMUONSegmentationV01 code from AliMUONSegResV01.cxx
76 /////////////////////////////////////////////////////
77 // Segmentation and Response classes version 01 //
78 /////////////////////////////////////////////////////
84 #include <TGeometry.h>
86 #include <TObjArray.h>
89 #include "AliMUONSegmentationV01.h"
91 #include "AliMUONChamber.h"
96 //___________________________________________
97 ClassImp(AliMUONSegmentationV01)
99 AliMUONSegmentationV01::AliMUONSegmentationV01(const AliMUONSegmentationV01& segmentation)
101 // Dummy copy constructor
104 AliMUONSegmentationV01::AliMUONSegmentationV01()
106 // Default constructor
107 printf("\n Calling Default Constructor");
114 AliMUONSegmentationV01::AliMUONSegmentationV01(Int_t nsec)
116 // Non default constructor
119 fRSec = new TArrayF(fNsec);
120 fNDiv = new TArrayI(fNsec);
121 fDpxD = new TArrayF(fNsec);
124 (*fRSec)[0]=(*fRSec)[1]=(*fRSec)[2]=(*fRSec)[3]=0;
125 (*fNDiv)[0]=(*fNDiv)[1]=(*fNDiv)[2]=(*fNDiv)[3]=0;
126 (*fDpxD)[0]=(*fDpxD)[1]=(*fDpxD)[2]=(*fDpxD)[3]=0;
127 fCorrA = new TObjArray(3);
134 AliMUONSegmentationV01::~AliMUONSegmentationV01()
137 if (fRSec) delete fRSec;
138 if (fNDiv) delete fNDiv;
139 if (fDpxD) delete fDpxD;
147 Float_t AliMUONSegmentationV01::Dpx(Int_t isec) const
150 // Returns x-pad size for given sector isec
151 Float_t dpx = (*fDpxD)[isec];
155 Float_t AliMUONSegmentationV01::Dpy(Int_t isec) const
158 // Returns y-pad size for given sector isec
162 void AliMUONSegmentationV01::SetSegRadii(Float_t r[4])
165 // Set the radii of the segmentation zones
166 for (Int_t i=0; i<4; i++) {
172 void AliMUONSegmentationV01::SetPadDivision(Int_t ndiv[4])
175 // Defines the pad size perp. to the anode wire (y) for different sectors.
176 // Pad sizes are defined as integral fractions ndiv of a basis pad size
179 for (Int_t i=0; i<4; i++) {
186 void AliMUONSegmentationV01::Init(Int_t chamber)
189 // Fill the arrays fCx (x-contour) and fNpxS (ix-contour) for each sector
190 // These arrays help in converting from real to pad co-ordinates and
192 // This version approximates concentric segmentation zones
195 printf("\n Initialise Segmentation V01\n");
198 fNpy=Int_t((*fRSec)[fNsec-1]/fDpy)+1;
200 (*fDpxD)[fNsec-1]=fDpx;
202 for (Int_t i=fNsec-2; i>=0; i--){
203 (*fDpxD)[i]=(*fDpxD)[fNsec-1]/(*fNDiv)[i];
207 // fill the arrays defining the pad segmentation boundaries
212 // loop over sections
213 for(isec=0; isec<fNsec; isec++) {
215 // loop over pads along the aode wires
216 for (Int_t iy=1; iy<=fNpy; iy++) {
218 Float_t x=iy*fDpy-fDpy/2;
219 if (x > (*fRSec)[isec]) {
223 ry=TMath::Sqrt((*fRSec)[isec]*(*fRSec)[isec]-x*x);
225 dnx= Int_t((ry-fCx[isec-1][iy])/(*fDpxD)[isec]);
226 if (isec < fNsec-1) {
227 if (TMath::Odd((Long_t)dnx)) dnx++;
229 fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
230 fCx[isec][iy]=fCx[isec-1][iy]+dnx*(*fDpxD)[isec];
231 } else if (isec == 1) {
232 dnx= Int_t((ry-fCx[isec-1][iy])/(*fDpxD)[isec]);
233 fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
234 add=4 - (fNpxS[isec][iy])%4;
235 if (add < 4) fNpxS[isec][iy]+=add;
236 dnx=fNpxS[isec][iy]-fNpxS[isec-1][iy];
237 fCx[isec][iy]=fCx[isec-1][iy]+dnx*(*fDpxD)[isec];
239 dnx=Int_t(ry/(*fDpxD)[isec]);
241 fCx[isec][iy]=dnx*(*fDpxD)[isec];
246 // reference to chamber
247 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
248 fChamber=&(pMUON->Chamber(chamber));
253 Int_t AliMUONSegmentationV01::Sector(Int_t ix, Int_t iy)
255 // Returns sector number for given pad position
257 Int_t absix=TMath::Abs(ix);
258 Int_t absiy=TMath::Abs(iy);
260 for (Int_t i=0; i<fNsec; i++) {
261 if (absix<=fNpxS[i][absiy]){
269 void AliMUONSegmentationV01::
270 GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
272 // Returns pad coordinates (ix,iy) for given real coordinates (x,y)
274 iy = (y-fOffsetY >0)?
275 Int_t((y-fOffsetY)/fDpy)+1
277 Int_t((y-fOffsetY)/fDpy)-1;
279 if (iy > fNpy) iy= fNpy;
280 if (iy < -fNpy) iy=-fNpy;
284 Float_t absx=TMath::Abs(x);
285 Int_t absiy=TMath::Abs(iy);
286 for (Int_t i=0; i < fNsec; i++) {
287 if (absx <= fCx[i][absiy]) {
293 ix= Int_t((absx-fCx[isec-1][absiy])/(*fDpxD)[isec])
294 +fNpxS[isec-1][absiy]+1;
295 } else if (isec == 0) {
296 ix= Int_t(absx/(*fDpxD)[isec])+1;
298 ix=fNpxS[fNsec-1][absiy]+1;
303 void AliMUONSegmentationV01::
304 GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
306 // Returns real coordinates (x,y) for given pad coordinates (ix,iy)
309 Float_t(iy*fDpy)-fDpy/2.+fOffsetY
311 Float_t(iy*fDpy)+fDpy/2.-fOffsetY;
314 Int_t isec=AliMUONSegmentationV01::Sector(ix,iy);
316 Int_t absix=TMath::Abs(ix);
317 Int_t absiy=TMath::Abs(iy);
319 x=fCx[isec-1][absiy]+(absix-fNpxS[isec-1][absiy])*(*fDpxD)[isec];
320 x=(ix>0) ? x-(*fDpxD)[isec]/2 : -x+(*fDpxD)[isec]/2;
326 void AliMUONSegmentationV01::
327 SetPad(Int_t ix, Int_t iy)
330 // Sets virtual pad coordinates, needed for evaluating pad response
331 // outside the tracking program
332 GetPadC(ix,iy,fX,fY);
333 fSector=Sector(ix,iy);
337 void AliMUONSegmentationV01::
338 FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
340 // Initialises iteration over pads for charge distribution algorithm
343 // Find the wire position (center of charge distribution)
344 Float_t x0a=GetAnod(xhit);
349 // and take fNsigma*sigma around this center
350 Float_t x01=x0a - dx;
351 Float_t x02=x0a + dx;
352 Float_t y01=yhit - dy;
353 Float_t y02=yhit + dy;
355 // find the pads over which the charge distributes
357 GetPadI(x01,y01,fIxmin,fIymin);
358 GetPadI(x02,y02,fIxmax,fIymax);
365 // Set current pad to lower left corner
366 if (fIxmax < fIxmin) fIxmax=fIxmin;
367 if (fIymax < fIymin) fIymax=fIymin;
370 GetPadC(fIx,fIy,fX,fY);
374 void AliMUONSegmentationV01::NextPad()
376 // Stepper for the iteration over pads
378 // Step to next pad in the integration region
380 // Step to next pad in integration region
384 // step from left to right
386 if (fX < fXmax && fX != 0) {
390 } else if (fIy != fIymax) {
393 // get y-position of next row (yc), xc not used here
394 GetPadC(fIx,fIy,xc,yc);
395 // get x-pad coordiante for first pad in row (fIx)
396 GetPadI(fXmin,yc,fIx,iyc);
401 GetPadC(fIx,fIy,fX,fY);
402 fSector=Sector(fIx,fIy);
404 (fSector ==-1 || fSector==0))
408 Int_t AliMUONSegmentationV01::MorePads()
411 // Stopping condition for the iterator over pads
413 // Are there more pads in the integration region
414 return (fIx != -1 || fIy != -1);
416 if ((fX >= fXmax && fIy >= fIymax) || fY==0) {
424 void AliMUONSegmentationV01::
425 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
427 // Returns integration limits for current pad
429 x1=fXhit-fX-Dpx(fSector)/2.;
431 y1=fYhit-fY-Dpy(fSector)/2.;
435 void AliMUONSegmentationV01::
436 Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])
438 // Returns list of next neighbours for given Pad (iX, iY)
440 const Float_t kEpsilon=fDpy/1000;
443 Int_t ixx, iyy, isec1;
445 Int_t isec0=AliMUONSegmentationV01::Sector(iX,iY);
450 if (Xlist[i]==0) Xlist[i]++;
455 if (Xlist[i]==0) Xlist[i]--;
459 AliMUONSegmentationV01::GetPadC(iX,iY,x,y);
460 AliMUONSegmentationV01::GetPadI(x+kEpsilon,y+fDpy,ixx,iyy);
463 isec1=AliMUONSegmentationV01::Sector(ixx,iyy);
466 // no sector boundary crossing
472 } else if (isec1 < isec0) {
473 // finer segmentation
483 // coarser segmenation
485 if (TMath::Odd(iX-fNpxS[isec1-1][iY+1])) {
497 AliMUONSegmentationV01::GetPadC(iX,iY,x,y);
498 AliMUONSegmentationV01::GetPadI(x+kEpsilon,y-fDpy,ixx,iyy);
501 isec1=AliMUONSegmentationV01::Sector(ixx,iyy);
504 // no sector boundary crossing
512 } else if (isec1 < isec0) {
513 // finer segmentation
523 // coarser segmentation
525 if (TMath::Odd(iX-fNpxS[isec1-1][iY-1])) {
537 void AliMUONSegmentationV01::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) const
539 // Returns test point on the pad plane.
540 // Used during determination of the segmoid correction of the COG-method
543 x[0]=((*fRSec)[0]+(*fRSec)[1])/2/TMath::Sqrt(2.);
545 x[1]=((*fRSec)[1]+(*fRSec)[2])/2/TMath::Sqrt(2.);
547 x[2]=((*fRSec)[2]+(*fRSec)[3])/2/TMath::Sqrt(2.);
551 void AliMUONSegmentationV01::Draw(const char* opt) const
554 // Draws the segmentation zones
556 if (!strcmp(opt,"eventdisplay")) {
557 const int kColorMUON = kBlue;
559 TRotMatrix* rot000 = new TRotMatrix("Rot000"," ", 90, 0, 90, 90, 0, 0);
560 TRotMatrix* rot090 = new TRotMatrix("Rot090"," ", 90, 90, 90,180, 0, 0);
561 TRotMatrix* rot180 = new TRotMatrix("Rot180"," ", 90,180, 90,270, 0, 0);
562 TRotMatrix* rot270 = new TRotMatrix("Rot270"," ", 90,270, 90, 0, 0, 0);
564 char nameChamber[9], nameSense[9], nameFrame[9], nameNode[9];
565 char nameSense1[9], nameSense2[9];
568 sprintf(nameChamber,"C_MUON%d",fId+1);
569 sprintf(nameSense,"S_MUON%d",fId+1);
570 sprintf(nameSense1,"S1_MUON%d",fId+1);
571 sprintf(nameSense2,"S2_MUON%d",fId+1);
572 sprintf(nameFrame,"F_MUON%d",fId+1);
574 TNode* top=gAlice->GetGeometry()->GetNode("alice");
576 Float_t rmin = (*fRSec)[0]-3;
577 Float_t rmax = (*fRSec)[3]+3;
578 new TTUBE(nameChamber,"Mother","void",rmin,rmax,0.25,1.);
581 new TTUBE(nameSense,"Sens. region","void",rmin,rmax,0.25, 1.);
582 Float_t dx=(rmax-rmin)/2;
585 TBRIK* frMUON = new TBRIK(nameFrame,"Frame","void",dx,dy,dz);
587 sprintf(nameNode,"MUON%d",100+fId+1);
588 node = new TNode(nameNode,"ChamberNode",nameChamber,0,0,fChamber->Z(),"");
589 node->SetLineColor(kColorMUON);
590 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
591 (pMUON->Nodes())->Add(node);
593 sprintf(nameNode,"MUON%d",200+fId+1);
594 node = new TNode(nameNode,"Sens. Region Node",nameSense,0,0,0,"");
595 node->SetLineColor(kColorMUON);
598 sprintf(nameNode,"MUON%d",300+fId+1);
599 nodeF = new TNode(nameNode,"Frame0",frMUON,dr, 0, 0,rot000,"");
600 nodeF->SetLineColor(kColorMUON);
602 sprintf(nameNode,"MUON%d",400+fId+1);
603 nodeF = new TNode(nameNode,"Frame1",frMUON,0 ,dr,0,rot090,"");
604 nodeF->SetLineColor(kColorMUON);
606 sprintf(nameNode,"MUON%d",500+fId+1);
607 nodeF = new TNode(nameNode,"Frame2",frMUON,-dr,0,0,rot180,"");
608 nodeF->SetLineColor(kColorMUON);
610 sprintf(nameNode,"MUON%d",600+fId+1);
611 nodeF = new TNode(nameNode,"Frame3",frMUON,0,-dr,0,rot270,"");
612 nodeF->SetLineColor(kColorMUON);
616 Float_t dx=0.95/fCx[3][1]/2;
617 Float_t dy=0.95/(Float_t(Npy()))/2;
622 for (Int_t iy=1; iy<Npy(); iy++) {
623 for (Int_t isec=0; isec<4; isec++) {
628 x0=fCx[isec-1][iy]*dx;
633 box=new TBox(x0+xc,y0+yc,x1+xc,y1+yc);
634 box->SetFillColor(isec+1);
637 box=new TBox(-x1+xc,y0+yc,-x0+xc,y1+yc);
638 box->SetFillColor(isec+1);
641 box=new TBox(x0+xc,-y1+yc,x1+xc,-y0+yc);
642 box->SetFillColor(isec+1);
645 box=new TBox(-x1+xc,-y1+yc,-x0+xc,-y0+yc);
646 box->SetFillColor(isec+1);
652 void AliMUONSegmentationV01::SetCorrFunc(Int_t isec, TF1* func)
654 // Set the correction function
655 (*fCorrA)[isec]=func;
658 TF1* AliMUONSegmentationV01::CorrFunc(Int_t isec) const
660 // Get correction function
661 return (TF1*) (*fCorrA)[isec];
664 AliMUONSegmentationV01& AliMUONSegmentationV01::operator
665 =(const AliMUONSegmentationV01 & rhs)
667 // Dummy assignment operator