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.14 2000/12/21 22:12:41 morsch
19 Clean-up of coding rule violations,
21 Revision 1.13 2000/12/07 10:41:51 hristov
22 fCorr replaced by fCorrA
24 Revision 1.12 2000/12/06 11:55:41 morsch
25 Introduce SetOffsetY(Float_t off) method as simplified simulation of pad staggering.
26 fOffset is the staggering offset in y.
28 Revision 1.11 2000/11/06 09:20:43 morsch
29 AliMUON delegates part of BuildGeometry() to AliMUONSegmentation using the
30 Draw() method. This avoids code and parameter replication.
32 Revision 1.10 2000/10/18 11:42:06 morsch
33 - AliMUONRawCluster contains z-position.
34 - Some clean-up of useless print statements during initialisations.
36 Revision 1.9 2000/10/18 08:41:32 morsch
37 Make NextPad() and MorePads() to iterate until the end.
39 Revision 1.8 2000/10/03 21:48:07 morsch
40 Adopt to const declaration of some of the methods in AliSegmentation.
42 Revision 1.7 2000/10/02 21:28:09 fca
43 Removal of useless dependecies via forward declarations
45 Revision 1.6 2000/10/02 16:58:29 egangler
46 Cleaning of the code :
49 -> some useless includes removed or replaced by "class" statement
51 Revision 1.5 2000/07/13 16:19:44 fca
52 Mainly coding conventions + some small bug fixes
54 Revision 1.4 2000/07/03 11:54:57 morsch
55 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
56 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
58 Revision 1.3 2000/06/29 12:34:09 morsch
59 AliMUONSegmentation class has been made independent of AliMUONChamber. This makes
60 it usable with any other geometry class. The link to the object to which it belongs is
61 established via an index. This assumes that there exists a global geometry manager
62 from which the pointer to the parent object can be obtained (in our case gAlice).
64 Revision 1.2 2000/06/15 07:58:48 morsch
65 Code from MUON-dev joined
67 Revision 1.1.2.1 2000/06/09 21:37:30 morsch
68 AliMUONSegmentationV01 code from AliMUONSegResV01.cxx
73 /////////////////////////////////////////////////////
74 // Segmentation and Response classes version 01 //
75 /////////////////////////////////////////////////////
81 #include <TGeometry.h>
83 #include <TObjArray.h>
86 #include "AliMUONSegmentationV01.h"
88 #include "AliMUONChamber.h"
93 //___________________________________________
94 ClassImp(AliMUONSegmentationV01)
96 AliMUONSegmentationV01::AliMUONSegmentationV01(const AliMUONSegmentationV01& segmentation)
98 // Dummy copy constructor
101 AliMUONSegmentationV01::AliMUONSegmentationV01()
103 // Default constructor
104 printf("\n Calling Default Constructor");
110 AliMUONSegmentationV01::AliMUONSegmentationV01(Int_t nsec)
112 // Non default constructor
115 fRSec = new TArrayF(fNsec);
116 fNDiv = new TArrayI(fNsec);
117 fDpxD = new TArrayF(fNsec);
120 (*fRSec)[0]=(*fRSec)[1]=(*fRSec)[2]=(*fRSec)[3]=0;
121 (*fNDiv)[0]=(*fNDiv)[1]=(*fNDiv)[2]=(*fNDiv)[3]=0;
122 (*fDpxD)[0]=(*fDpxD)[1]=(*fDpxD)[2]=(*fDpxD)[3]=0;
123 fCorrA = new TObjArray(3);
130 AliMUONSegmentationV01::~AliMUONSegmentationV01()
133 if (fRSec) delete fRSec;
134 if (fNDiv) delete fNDiv;
135 if (fDpxD) delete fDpxD;
143 Float_t AliMUONSegmentationV01::Dpx(Int_t isec) const
146 // Returns x-pad size for given sector isec
147 Float_t dpx = (*fDpxD)[isec];
151 Float_t AliMUONSegmentationV01::Dpy(Int_t isec) const
154 // Returns y-pad size for given sector isec
158 void AliMUONSegmentationV01::SetSegRadii(Float_t r[4])
161 // Set the radii of the segmentation zones
162 for (Int_t i=0; i<4; i++) {
168 void AliMUONSegmentationV01::SetPadDivision(Int_t ndiv[4])
171 // Defines the pad size perp. to the anode wire (y) for different sectors.
172 // Pad sizes are defined as integral fractions ndiv of a basis pad size
175 for (Int_t i=0; i<4; i++) {
182 void AliMUONSegmentationV01::Init(Int_t chamber)
185 // Fill the arrays fCx (x-contour) and fNpxS (ix-contour) for each sector
186 // These arrays help in converting from real to pad co-ordinates and
188 // This version approximates concentric segmentation zones
191 printf("\n Initialise Segmentation V01\n");
194 fNpy=Int_t((*fRSec)[fNsec-1]/fDpy)+1;
196 (*fDpxD)[fNsec-1]=fDpx;
198 for (Int_t i=fNsec-2; i>=0; i--){
199 (*fDpxD)[i]=(*fDpxD)[fNsec-1]/(*fNDiv)[i];
203 // fill the arrays defining the pad segmentation boundaries
208 // loop over sections
209 for(isec=0; isec<fNsec; isec++) {
211 // loop over pads along the aode wires
212 for (Int_t iy=1; iy<=fNpy; iy++) {
214 Float_t x=iy*fDpy-fDpy/2;
215 if (x > (*fRSec)[isec]) {
219 ry=TMath::Sqrt((*fRSec)[isec]*(*fRSec)[isec]-x*x);
221 dnx= Int_t((ry-fCx[isec-1][iy])/(*fDpxD)[isec]);
222 if (isec < fNsec-1) {
223 if (TMath::Odd((Long_t)dnx)) dnx++;
225 fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
226 fCx[isec][iy]=fCx[isec-1][iy]+dnx*(*fDpxD)[isec];
227 } else if (isec == 1) {
228 dnx= Int_t((ry-fCx[isec-1][iy])/(*fDpxD)[isec]);
229 fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
230 add=4 - (fNpxS[isec][iy])%4;
231 if (add < 4) fNpxS[isec][iy]+=add;
232 dnx=fNpxS[isec][iy]-fNpxS[isec-1][iy];
233 fCx[isec][iy]=fCx[isec-1][iy]+dnx*(*fDpxD)[isec];
235 dnx=Int_t(ry/(*fDpxD)[isec]);
237 fCx[isec][iy]=dnx*(*fDpxD)[isec];
242 // reference to chamber
243 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
244 fChamber=&(pMUON->Chamber(chamber));
249 Int_t AliMUONSegmentationV01::Sector(Int_t ix, Int_t iy)
251 // Returns sector number for given pad position
253 Int_t absix=TMath::Abs(ix);
254 Int_t absiy=TMath::Abs(iy);
256 for (Int_t i=0; i<fNsec; i++) {
257 if (absix<=fNpxS[i][absiy]){
265 void AliMUONSegmentationV01::
266 GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
268 // Returns pad coordinates (ix,iy) for given real coordinates (x,y)
270 iy = (y-fOffsetY >0)?
271 Int_t((y-fOffsetY)/fDpy)+1
273 Int_t((y-fOffsetY)/fDpy)-1;
275 if (iy > fNpy) iy= fNpy;
276 if (iy < -fNpy) iy=-fNpy;
280 Float_t absx=TMath::Abs(x);
281 Int_t absiy=TMath::Abs(iy);
282 for (Int_t i=0; i < fNsec; i++) {
283 if (absx <= fCx[i][absiy]) {
289 ix= Int_t((absx-fCx[isec-1][absiy])/(*fDpxD)[isec])
290 +fNpxS[isec-1][absiy]+1;
291 } else if (isec == 0) {
292 ix= Int_t(absx/(*fDpxD)[isec])+1;
294 ix=fNpxS[fNsec-1][absiy]+1;
299 void AliMUONSegmentationV01::
300 GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
302 // Returns real coordinates (x,y) for given pad coordinates (ix,iy)
305 Float_t(iy*fDpy)-fDpy/2.+fOffsetY
307 Float_t(iy*fDpy)+fDpy/2.-fOffsetY;
310 Int_t isec=AliMUONSegmentationV01::Sector(ix,iy);
312 Int_t absix=TMath::Abs(ix);
313 Int_t absiy=TMath::Abs(iy);
315 x=fCx[isec-1][absiy]+(absix-fNpxS[isec-1][absiy])*(*fDpxD)[isec];
316 x=(ix>0) ? x-(*fDpxD)[isec]/2 : -x+(*fDpxD)[isec]/2;
322 void AliMUONSegmentationV01::
323 SetPad(Int_t ix, Int_t iy)
326 // Sets virtual pad coordinates, needed for evaluating pad response
327 // outside the tracking program
328 GetPadC(ix,iy,fX,fY);
329 fSector=Sector(ix,iy);
333 void AliMUONSegmentationV01::
334 FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
336 // Initialises iteration over pads for charge distribution algorithm
339 // Find the wire position (center of charge distribution)
340 Float_t x0a=GetAnod(xhit);
345 // and take fNsigma*sigma around this center
346 Float_t x01=x0a - dx;
347 Float_t x02=x0a + dx;
348 Float_t y01=yhit - dy;
349 Float_t y02=yhit + dy;
351 // find the pads over which the charge distributes
353 GetPadI(x01,y01,fIxmin,fIymin);
354 GetPadI(x02,y02,fIxmax,fIymax);
361 // Set current pad to lower left corner
362 if (fIxmax < fIxmin) fIxmax=fIxmin;
363 if (fIymax < fIymin) fIymax=fIymin;
366 GetPadC(fIx,fIy,fX,fY);
370 void AliMUONSegmentationV01::NextPad()
372 // Stepper for the iteration over pads
374 // Step to next pad in the integration region
376 // Step to next pad in integration region
380 // step from left to right
382 if (fX < fXmax && fX != 0) {
386 } else if (fIy != fIymax) {
389 // get y-position of next row (yc), xc not used here
390 GetPadC(fIx,fIy,xc,yc);
391 // get x-pad coordiante for first pad in row (fIx)
392 GetPadI(fXmin,yc,fIx,iyc);
397 GetPadC(fIx,fIy,fX,fY);
398 fSector=Sector(fIx,fIy);
400 (fSector ==-1 || fSector==0))
404 Int_t AliMUONSegmentationV01::MorePads()
407 // Stopping condition for the iterator over pads
409 // Are there more pads in the integration region
410 return (fIx != -1 || fIy != -1);
412 if ((fX >= fXmax && fIy >= fIymax) || fY==0) {
420 void AliMUONSegmentationV01::
421 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
423 // Returns integration limits for current pad
425 x1=fXhit-fX-Dpx(fSector)/2.;
427 y1=fYhit-fY-Dpy(fSector)/2.;
431 void AliMUONSegmentationV01::
432 Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])
434 // Returns list of next neighbours for given Pad (iX, iY)
436 const Float_t kEpsilon=fDpy/1000;
439 Int_t ixx, iyy, isec1;
441 Int_t isec0=AliMUONSegmentationV01::Sector(iX,iY);
446 if (Xlist[i]==0) Xlist[i]++;
451 if (Xlist[i]==0) Xlist[i]--;
455 AliMUONSegmentationV01::GetPadC(iX,iY,x,y);
456 AliMUONSegmentationV01::GetPadI(x+kEpsilon,y+fDpy,ixx,iyy);
459 isec1=AliMUONSegmentationV01::Sector(ixx,iyy);
462 // no sector boundary crossing
468 } else if (isec1 < isec0) {
469 // finer segmentation
479 // coarser segmenation
481 if (TMath::Odd(iX-fNpxS[isec1-1][iY+1])) {
493 AliMUONSegmentationV01::GetPadC(iX,iY,x,y);
494 AliMUONSegmentationV01::GetPadI(x+kEpsilon,y-fDpy,ixx,iyy);
497 isec1=AliMUONSegmentationV01::Sector(ixx,iyy);
500 // no sector boundary crossing
508 } else if (isec1 < isec0) {
509 // finer segmentation
519 // coarser segmentation
521 if (TMath::Odd(iX-fNpxS[isec1-1][iY-1])) {
533 void AliMUONSegmentationV01::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) const
535 // Returns test point on the pad plane.
536 // Used during determination of the segmoid correction of the COG-method
539 x[0]=((*fRSec)[0]+(*fRSec)[1])/2/TMath::Sqrt(2.);
541 x[1]=((*fRSec)[1]+(*fRSec)[2])/2/TMath::Sqrt(2.);
543 x[2]=((*fRSec)[2]+(*fRSec)[3])/2/TMath::Sqrt(2.);
547 void AliMUONSegmentationV01::Draw(const char* opt) const
550 // Draws the segmentation zones
552 if (!strcmp(opt,"eventdisplay")) {
553 const int kColorMUON = kBlue;
555 TRotMatrix* rot000 = new TRotMatrix("Rot000"," ", 90, 0, 90, 90, 0, 0);
556 TRotMatrix* rot090 = new TRotMatrix("Rot090"," ", 90, 90, 90,180, 0, 0);
557 TRotMatrix* rot180 = new TRotMatrix("Rot180"," ", 90,180, 90,270, 0, 0);
558 TRotMatrix* rot270 = new TRotMatrix("Rot270"," ", 90,270, 90, 0, 0, 0);
560 char nameChamber[9], nameSense[9], nameFrame[9], nameNode[9];
561 char nameSense1[9], nameSense2[9];
564 sprintf(nameChamber,"C_MUON%d",fId+1);
565 sprintf(nameSense,"S_MUON%d",fId+1);
566 sprintf(nameSense1,"S1_MUON%d",fId+1);
567 sprintf(nameSense2,"S2_MUON%d",fId+1);
568 sprintf(nameFrame,"F_MUON%d",fId+1);
570 TNode* top=gAlice->GetGeometry()->GetNode("alice");
572 Float_t rmin = (*fRSec)[0]-3;
573 Float_t rmax = (*fRSec)[3]+3;
574 new TTUBE(nameChamber,"Mother","void",rmin,rmax,0.25,1.);
577 new TTUBE(nameSense,"Sens. region","void",rmin,rmax,0.25, 1.);
578 Float_t dx=(rmax-rmin)/2;
581 TBRIK* frMUON = new TBRIK(nameFrame,"Frame","void",dx,dy,dz);
583 sprintf(nameNode,"MUON%d",100+fId+1);
584 node = new TNode(nameNode,"ChamberNode",nameChamber,0,0,fChamber->Z(),"");
585 node->SetLineColor(kColorMUON);
586 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
587 (pMUON->Nodes())->Add(node);
589 sprintf(nameNode,"MUON%d",200+fId+1);
590 node = new TNode(nameNode,"Sens. Region Node",nameSense,0,0,0,"");
591 node->SetLineColor(kColorMUON);
594 sprintf(nameNode,"MUON%d",300+fId+1);
595 nodeF = new TNode(nameNode,"Frame0",frMUON,dr, 0, 0,rot000,"");
596 nodeF->SetLineColor(kColorMUON);
598 sprintf(nameNode,"MUON%d",400+fId+1);
599 nodeF = new TNode(nameNode,"Frame1",frMUON,0 ,dr,0,rot090,"");
600 nodeF->SetLineColor(kColorMUON);
602 sprintf(nameNode,"MUON%d",500+fId+1);
603 nodeF = new TNode(nameNode,"Frame2",frMUON,-dr,0,0,rot180,"");
604 nodeF->SetLineColor(kColorMUON);
606 sprintf(nameNode,"MUON%d",600+fId+1);
607 nodeF = new TNode(nameNode,"Frame3",frMUON,0,-dr,0,rot270,"");
608 nodeF->SetLineColor(kColorMUON);
612 Float_t dx=0.95/fCx[3][1]/2;
613 Float_t dy=0.95/(Float_t(Npy()))/2;
618 for (Int_t iy=1; iy<Npy(); iy++) {
619 for (Int_t isec=0; isec<4; isec++) {
624 x0=fCx[isec-1][iy]*dx;
629 box=new TBox(x0+xc,y0+yc,x1+xc,y1+yc);
630 box->SetFillColor(isec+1);
633 box=new TBox(-x1+xc,y0+yc,-x0+xc,y1+yc);
634 box->SetFillColor(isec+1);
637 box=new TBox(x0+xc,-y1+yc,x1+xc,-y0+yc);
638 box->SetFillColor(isec+1);
641 box=new TBox(-x1+xc,-y1+yc,-x0+xc,-y0+yc);
642 box->SetFillColor(isec+1);
648 void AliMUONSegmentationV01::SetCorrFunc(Int_t isec, TF1* func)
650 // Set the correction function
651 (*fCorrA)[isec]=func;
654 TF1* AliMUONSegmentationV01::CorrFunc(Int_t isec) const
656 // Get correction function
657 return (TF1*) (*fCorrA)[isec];
660 AliMUONSegmentationV01& AliMUONSegmentationV01::operator
661 =(const AliMUONSegmentationV01 & rhs)
663 // Dummy assignment operator