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.18 2001/04/11 12:33:56 morsch
19 Bug in GetPadC in case of staggered planes corrected. (Thanks to J.P. Cussonneau)
21 Revision 1.17 2001/01/30 12:17:04 morsch
22 Remove obolete print-statement.
24 Revision 1.16 2001/01/30 09:23:14 hristov
25 Streamers removed (R.Brun)
27 Revision 1.15 2001/01/26 21:25:48 morsch
28 Empty default constructors and.
30 Revision 1.14 2000/12/21 22:12:41 morsch
31 Clean-up of coding rule violations,
33 Revision 1.13 2000/12/07 10:41:51 hristov
34 fCorr replaced by fCorrA
36 Revision 1.12 2000/12/06 11:55:41 morsch
37 Introduce SetOffsetY(Float_t off) method as simplified simulation of pad staggering.
38 fOffset is the staggering offset in y.
40 Revision 1.11 2000/11/06 09:20:43 morsch
41 AliMUON delegates part of BuildGeometry() to AliMUONSegmentation using the
42 Draw() method. This avoids code and parameter replication.
44 Revision 1.10 2000/10/18 11:42:06 morsch
45 - AliMUONRawCluster contains z-position.
46 - Some clean-up of useless print statements during initialisations.
48 Revision 1.9 2000/10/18 08:41:32 morsch
49 Make NextPad() and MorePads() to iterate until the end.
51 Revision 1.8 2000/10/03 21:48:07 morsch
52 Adopt to const declaration of some of the methods in AliSegmentation.
54 Revision 1.7 2000/10/02 21:28:09 fca
55 Removal of useless dependecies via forward declarations
57 Revision 1.6 2000/10/02 16:58:29 egangler
58 Cleaning of the code :
61 -> some useless includes removed or replaced by "class" statement
63 Revision 1.5 2000/07/13 16:19:44 fca
64 Mainly coding conventions + some small bug fixes
66 Revision 1.4 2000/07/03 11:54:57 morsch
67 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
68 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
70 Revision 1.3 2000/06/29 12:34:09 morsch
71 AliMUONSegmentation class has been made independent of AliMUONChamber. This makes
72 it usable with any other geometry class. The link to the object to which it belongs is
73 established via an index. This assumes that there exists a global geometry manager
74 from which the pointer to the parent object can be obtained (in our case gAlice).
76 Revision 1.2 2000/06/15 07:58:48 morsch
77 Code from MUON-dev joined
79 Revision 1.1.2.1 2000/06/09 21:37:30 morsch
80 AliMUONSegmentationV01 code from AliMUONSegResV01.cxx
85 /////////////////////////////////////////////////////
86 // Segmentation and Response classes version 01 //
87 /////////////////////////////////////////////////////
93 #include <TGeometry.h>
95 #include <TObjArray.h>
98 #include "AliMUONSegmentationV01.h"
100 #include "AliMUONChamber.h"
105 //___________________________________________
106 ClassImp(AliMUONSegmentationV01)
108 AliMUONSegmentationV01::AliMUONSegmentationV01(const AliMUONSegmentationV01& segmentation)
110 // Dummy copy constructor
113 AliMUONSegmentationV01::AliMUONSegmentationV01()
115 // Default constructor
122 AliMUONSegmentationV01::AliMUONSegmentationV01(Int_t nsec)
124 // Non default constructor
127 fRSec = new TArrayF(fNsec);
128 fNDiv = new TArrayI(fNsec);
129 fDpxD = new TArrayF(fNsec);
132 (*fRSec)[0]=(*fRSec)[1]=(*fRSec)[2]=(*fRSec)[3]=0;
133 (*fNDiv)[0]=(*fNDiv)[1]=(*fNDiv)[2]=(*fNDiv)[3]=0;
134 (*fDpxD)[0]=(*fDpxD)[1]=(*fDpxD)[2]=(*fDpxD)[3]=0;
135 fCorrA = new TObjArray(3);
142 AliMUONSegmentationV01::~AliMUONSegmentationV01()
145 if (fRSec) delete fRSec;
146 if (fNDiv) delete fNDiv;
147 if (fDpxD) delete fDpxD;
155 Float_t AliMUONSegmentationV01::Dpx(Int_t isec) const
158 // Returns x-pad size for given sector isec
159 Float_t dpx = (*fDpxD)[isec];
163 Float_t AliMUONSegmentationV01::Dpy(Int_t isec) const
166 // Returns y-pad size for given sector isec
170 void AliMUONSegmentationV01::SetSegRadii(Float_t r[4])
173 // Set the radii of the segmentation zones
174 for (Int_t i=0; i<4; i++) {
180 void AliMUONSegmentationV01::SetPadDivision(Int_t ndiv[4])
183 // Defines the pad size perp. to the anode wire (y) for different sectors.
184 // Pad sizes are defined as integral fractions ndiv of a basis pad size
187 for (Int_t i=0; i<4; i++) {
194 void AliMUONSegmentationV01::Init(Int_t chamber)
197 // Fill the arrays fCx (x-contour) and fNpxS (ix-contour) for each sector
198 // These arrays help in converting from real to pad co-ordinates and
200 // This version approximates concentric segmentation zones
203 //printf("\n Initialise Segmentation V01\n");
206 fNpy=Int_t((*fRSec)[fNsec-1]/fDpy)+1;
208 (*fDpxD)[fNsec-1]=fDpx;
210 for (Int_t i=fNsec-2; i>=0; i--){
211 (*fDpxD)[i]=(*fDpxD)[fNsec-1]/(*fNDiv)[i];
215 // fill the arrays defining the pad segmentation boundaries
220 // loop over sections
221 for(isec=0; isec<fNsec; isec++) {
223 // loop over pads along the aode wires
224 for (Int_t iy=1; iy<=fNpy; iy++) {
226 Float_t x=iy*fDpy-fDpy/2;
227 if (x > (*fRSec)[isec]) {
231 ry=TMath::Sqrt((*fRSec)[isec]*(*fRSec)[isec]-x*x);
233 dnx= Int_t((ry-fCx[isec-1][iy])/(*fDpxD)[isec]);
234 if (isec < fNsec-1) {
235 if (TMath::Odd((Long_t)dnx)) dnx++;
237 fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
238 fCx[isec][iy]=fCx[isec-1][iy]+dnx*(*fDpxD)[isec];
239 } else if (isec == 1) {
240 dnx= Int_t((ry-fCx[isec-1][iy])/(*fDpxD)[isec]);
241 fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
242 add=4 - (fNpxS[isec][iy])%4;
243 if (add < 4) fNpxS[isec][iy]+=add;
244 dnx=fNpxS[isec][iy]-fNpxS[isec-1][iy];
245 fCx[isec][iy]=fCx[isec-1][iy]+dnx*(*fDpxD)[isec];
247 dnx=Int_t(ry/(*fDpxD)[isec]);
249 fCx[isec][iy]=dnx*(*fDpxD)[isec];
254 // reference to chamber
255 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
256 fChamber=&(pMUON->Chamber(chamber));
261 Int_t AliMUONSegmentationV01::Sector(Int_t ix, Int_t iy)
263 // Returns sector number for given pad position
265 Int_t absix=TMath::Abs(ix);
266 Int_t absiy=TMath::Abs(iy);
268 for (Int_t i=0; i<fNsec; i++) {
269 if (absix<=fNpxS[i][absiy]){
277 void AliMUONSegmentationV01::
278 GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
280 // Returns pad coordinates (ix,iy) for given real coordinates (x,y)
282 iy = (y-fOffsetY >0)?
283 Int_t((y-fOffsetY)/fDpy)+1
285 Int_t((y-fOffsetY)/fDpy)-1;
287 if (iy > fNpy) iy= fNpy;
288 if (iy < -fNpy) iy=-fNpy;
292 Float_t absx=TMath::Abs(x);
293 Int_t absiy=TMath::Abs(iy);
294 for (Int_t i=0; i < fNsec; i++) {
295 if (absx <= fCx[i][absiy]) {
301 ix= Int_t((absx-fCx[isec-1][absiy])/(*fDpxD)[isec])
302 +fNpxS[isec-1][absiy]+1;
303 } else if (isec == 0) {
304 ix= Int_t(absx/(*fDpxD)[isec])+1;
306 ix=fNpxS[fNsec-1][absiy]+1;
311 void AliMUONSegmentationV01::
312 GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
314 // Returns real coordinates (x,y) for given pad coordinates (ix,iy)
317 Float_t(iy*fDpy)-fDpy/2.+fOffsetY
319 Float_t(iy*fDpy)+fDpy/2.+fOffsetY;
323 Int_t isec=AliMUONSegmentationV01::Sector(ix,iy);
325 Int_t absix=TMath::Abs(ix);
326 Int_t absiy=TMath::Abs(iy);
328 x=fCx[isec-1][absiy]+(absix-fNpxS[isec-1][absiy])*(*fDpxD)[isec];
329 x=(ix>0) ? x-(*fDpxD)[isec]/2 : -x+(*fDpxD)[isec]/2;
335 void AliMUONSegmentationV01::
336 SetPad(Int_t ix, Int_t iy)
339 // Sets virtual pad coordinates, needed for evaluating pad response
340 // outside the tracking program
341 GetPadC(ix,iy,fX,fY);
342 fSector=Sector(ix,iy);
346 void AliMUONSegmentationV01::
347 FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
349 // Initialises iteration over pads for charge distribution algorithm
352 // Find the wire position (center of charge distribution)
353 Float_t x0a=GetAnod(xhit);
358 // and take fNsigma*sigma around this center
359 Float_t x01=x0a - dx;
360 Float_t x02=x0a + dx;
361 Float_t y01=yhit - dy;
362 Float_t y02=yhit + dy;
364 // find the pads over which the charge distributes
366 GetPadI(x01,y01,fIxmin,fIymin);
367 GetPadI(x02,y02,fIxmax,fIymax);
374 // Set current pad to lower left corner
375 if (fIxmax < fIxmin) fIxmax=fIxmin;
376 if (fIymax < fIymin) fIymax=fIymin;
379 GetPadC(fIx,fIy,fX,fY);
383 void AliMUONSegmentationV01::NextPad()
385 // Stepper for the iteration over pads
387 // Step to next pad in the integration region
389 // Step to next pad in integration region
393 // step from left to right
395 if (fX < fXmax && fX != 0) {
399 } else if (fIy != fIymax) {
402 // get y-position of next row (yc), xc not used here
403 GetPadC(fIx,fIy,xc,yc);
404 // get x-pad coordiante for first pad in row (fIx)
405 GetPadI(fXmin,yc,fIx,iyc);
410 GetPadC(fIx,fIy,fX,fY);
411 fSector=Sector(fIx,fIy);
413 (fSector ==-1 || fSector==0))
417 Int_t AliMUONSegmentationV01::MorePads()
420 // Stopping condition for the iterator over pads
422 // Are there more pads in the integration region
423 return (fIx != -1 || fIy != -1);
425 if ((fX >= fXmax && fIy >= fIymax) || fY==0) {
433 void AliMUONSegmentationV01::
434 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
436 // Returns integration limits for current pad
438 x1=fXhit-fX-Dpx(fSector)/2.;
440 y1=fYhit-fY-Dpy(fSector)/2.;
444 void AliMUONSegmentationV01::
445 Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])
447 // Returns list of next neighbours for given Pad (iX, iY)
449 const Float_t kEpsilon=fDpy/1000;
452 Int_t ixx, iyy, isec1;
454 Int_t isec0=AliMUONSegmentationV01::Sector(iX,iY);
459 if (Xlist[i]==0) Xlist[i]++;
464 if (Xlist[i]==0) Xlist[i]--;
468 AliMUONSegmentationV01::GetPadC(iX,iY,x,y);
469 AliMUONSegmentationV01::GetPadI(x+kEpsilon,y+fDpy,ixx,iyy);
472 isec1=AliMUONSegmentationV01::Sector(ixx,iyy);
475 // no sector boundary crossing
481 } else if (isec1 < isec0) {
482 // finer segmentation
492 // coarser segmenation
494 if (TMath::Odd(iX-fNpxS[isec1-1][iY+1])) {
506 AliMUONSegmentationV01::GetPadC(iX,iY,x,y);
507 AliMUONSegmentationV01::GetPadI(x+kEpsilon,y-fDpy,ixx,iyy);
510 isec1=AliMUONSegmentationV01::Sector(ixx,iyy);
513 // no sector boundary crossing
521 } else if (isec1 < isec0) {
522 // finer segmentation
532 // coarser segmentation
534 if (TMath::Odd(iX-fNpxS[isec1-1][iY-1])) {
546 void AliMUONSegmentationV01::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) const
548 // Returns test point on the pad plane.
549 // Used during determination of the segmoid correction of the COG-method
552 x[0]=((*fRSec)[0]+(*fRSec)[1])/2/TMath::Sqrt(2.);
554 x[1]=((*fRSec)[1]+(*fRSec)[2])/2/TMath::Sqrt(2.);
556 x[2]=((*fRSec)[2]+(*fRSec)[3])/2/TMath::Sqrt(2.);
560 void AliMUONSegmentationV01::Draw(const char* opt) const
563 // Draws the segmentation zones
565 if (!strcmp(opt,"eventdisplay")) {
566 const int kColorMUON = kBlue;
568 TRotMatrix* rot000 = new TRotMatrix("Rot000"," ", 90, 0, 90, 90, 0, 0);
569 TRotMatrix* rot090 = new TRotMatrix("Rot090"," ", 90, 90, 90,180, 0, 0);
570 TRotMatrix* rot180 = new TRotMatrix("Rot180"," ", 90,180, 90,270, 0, 0);
571 TRotMatrix* rot270 = new TRotMatrix("Rot270"," ", 90,270, 90, 0, 0, 0);
573 char nameChamber[9], nameSense[9], nameFrame[9], nameNode[9];
574 char nameSense1[9], nameSense2[9];
577 sprintf(nameChamber,"C_MUON%d",fId+1);
578 sprintf(nameSense,"S_MUON%d",fId+1);
579 sprintf(nameSense1,"S1_MUON%d",fId+1);
580 sprintf(nameSense2,"S2_MUON%d",fId+1);
581 sprintf(nameFrame,"F_MUON%d",fId+1);
583 TNode* top=gAlice->GetGeometry()->GetNode("alice");
585 Float_t rmin = (*fRSec)[0]-3;
586 Float_t rmax = (*fRSec)[3]+3;
587 new TTUBE(nameChamber,"Mother","void",rmin,rmax,0.25,1.);
590 new TTUBE(nameSense,"Sens. region","void",rmin,rmax,0.25, 1.);
591 Float_t dx=(rmax-rmin)/2;
594 TBRIK* frMUON = new TBRIK(nameFrame,"Frame","void",dx,dy,dz);
596 sprintf(nameNode,"MUON%d",100+fId+1);
597 node = new TNode(nameNode,"ChamberNode",nameChamber,0,0,fChamber->Z(),"");
598 node->SetLineColor(kColorMUON);
599 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
600 (pMUON->Nodes())->Add(node);
602 sprintf(nameNode,"MUON%d",200+fId+1);
603 node = new TNode(nameNode,"Sens. Region Node",nameSense,0,0,0,"");
604 node->SetLineColor(kColorMUON);
607 sprintf(nameNode,"MUON%d",300+fId+1);
608 nodeF = new TNode(nameNode,"Frame0",frMUON,dr, 0, 0,rot000,"");
609 nodeF->SetLineColor(kColorMUON);
611 sprintf(nameNode,"MUON%d",400+fId+1);
612 nodeF = new TNode(nameNode,"Frame1",frMUON,0 ,dr,0,rot090,"");
613 nodeF->SetLineColor(kColorMUON);
615 sprintf(nameNode,"MUON%d",500+fId+1);
616 nodeF = new TNode(nameNode,"Frame2",frMUON,-dr,0,0,rot180,"");
617 nodeF->SetLineColor(kColorMUON);
619 sprintf(nameNode,"MUON%d",600+fId+1);
620 nodeF = new TNode(nameNode,"Frame3",frMUON,0,-dr,0,rot270,"");
621 nodeF->SetLineColor(kColorMUON);
625 Float_t dx=0.95/fCx[3][1]/2;
626 Float_t dy=0.95/(Float_t(Npy()))/2;
631 for (Int_t iy=1; iy<Npy(); iy++) {
632 for (Int_t isec=0; isec<4; isec++) {
637 x0=fCx[isec-1][iy]*dx;
642 box=new TBox(x0+xc,y0+yc,x1+xc,y1+yc);
643 box->SetFillColor(isec+1);
646 box=new TBox(-x1+xc,y0+yc,-x0+xc,y1+yc);
647 box->SetFillColor(isec+1);
650 box=new TBox(x0+xc,-y1+yc,x1+xc,-y0+yc);
651 box->SetFillColor(isec+1);
654 box=new TBox(-x1+xc,-y1+yc,-x0+xc,-y0+yc);
655 box->SetFillColor(isec+1);
661 void AliMUONSegmentationV01::SetCorrFunc(Int_t isec, TF1* func)
663 // Set the correction function
664 (*fCorrA)[isec]=func;
667 TF1* AliMUONSegmentationV01::CorrFunc(Int_t isec) const
669 // Get correction function
670 return (TF1*) (*fCorrA)[isec];
673 AliMUONSegmentationV01& AliMUONSegmentationV01::operator
674 =(const AliMUONSegmentationV01 & rhs)
676 // Dummy assignment operator