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.16 2001/01/30 09:23:14 hristov
19 Streamers removed (R.Brun)
21 Revision 1.15 2001/01/26 21:25:48 morsch
22 Empty default constructors and.
24 Revision 1.14 2000/12/21 22:12:41 morsch
25 Clean-up of coding rule violations,
27 Revision 1.13 2000/12/07 10:41:51 hristov
28 fCorr replaced by fCorrA
30 Revision 1.12 2000/12/06 11:55:41 morsch
31 Introduce SetOffsetY(Float_t off) method as simplified simulation of pad staggering.
32 fOffset is the staggering offset in y.
34 Revision 1.11 2000/11/06 09:20:43 morsch
35 AliMUON delegates part of BuildGeometry() to AliMUONSegmentation using the
36 Draw() method. This avoids code and parameter replication.
38 Revision 1.10 2000/10/18 11:42:06 morsch
39 - AliMUONRawCluster contains z-position.
40 - Some clean-up of useless print statements during initialisations.
42 Revision 1.9 2000/10/18 08:41:32 morsch
43 Make NextPad() and MorePads() to iterate until the end.
45 Revision 1.8 2000/10/03 21:48:07 morsch
46 Adopt to const declaration of some of the methods in AliSegmentation.
48 Revision 1.7 2000/10/02 21:28:09 fca
49 Removal of useless dependecies via forward declarations
51 Revision 1.6 2000/10/02 16:58:29 egangler
52 Cleaning of the code :
55 -> some useless includes removed or replaced by "class" statement
57 Revision 1.5 2000/07/13 16:19:44 fca
58 Mainly coding conventions + some small bug fixes
60 Revision 1.4 2000/07/03 11:54:57 morsch
61 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
62 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
64 Revision 1.3 2000/06/29 12:34:09 morsch
65 AliMUONSegmentation class has been made independent of AliMUONChamber. This makes
66 it usable with any other geometry class. The link to the object to which it belongs is
67 established via an index. This assumes that there exists a global geometry manager
68 from which the pointer to the parent object can be obtained (in our case gAlice).
70 Revision 1.2 2000/06/15 07:58:48 morsch
71 Code from MUON-dev joined
73 Revision 1.1.2.1 2000/06/09 21:37:30 morsch
74 AliMUONSegmentationV01 code from AliMUONSegResV01.cxx
79 /////////////////////////////////////////////////////
80 // Segmentation and Response classes version 01 //
81 /////////////////////////////////////////////////////
87 #include <TGeometry.h>
89 #include <TObjArray.h>
92 #include "AliMUONSegmentationV01.h"
94 #include "AliMUONChamber.h"
99 //___________________________________________
100 ClassImp(AliMUONSegmentationV01)
102 AliMUONSegmentationV01::AliMUONSegmentationV01(const AliMUONSegmentationV01& segmentation)
104 // Dummy copy constructor
107 AliMUONSegmentationV01::AliMUONSegmentationV01()
109 // Default constructor
116 AliMUONSegmentationV01::AliMUONSegmentationV01(Int_t nsec)
118 // Non default constructor
121 fRSec = new TArrayF(fNsec);
122 fNDiv = new TArrayI(fNsec);
123 fDpxD = new TArrayF(fNsec);
126 (*fRSec)[0]=(*fRSec)[1]=(*fRSec)[2]=(*fRSec)[3]=0;
127 (*fNDiv)[0]=(*fNDiv)[1]=(*fNDiv)[2]=(*fNDiv)[3]=0;
128 (*fDpxD)[0]=(*fDpxD)[1]=(*fDpxD)[2]=(*fDpxD)[3]=0;
129 fCorrA = new TObjArray(3);
136 AliMUONSegmentationV01::~AliMUONSegmentationV01()
139 if (fRSec) delete fRSec;
140 if (fNDiv) delete fNDiv;
141 if (fDpxD) delete fDpxD;
149 Float_t AliMUONSegmentationV01::Dpx(Int_t isec) const
152 // Returns x-pad size for given sector isec
153 Float_t dpx = (*fDpxD)[isec];
157 Float_t AliMUONSegmentationV01::Dpy(Int_t isec) const
160 // Returns y-pad size for given sector isec
164 void AliMUONSegmentationV01::SetSegRadii(Float_t r[4])
167 // Set the radii of the segmentation zones
168 for (Int_t i=0; i<4; i++) {
174 void AliMUONSegmentationV01::SetPadDivision(Int_t ndiv[4])
177 // Defines the pad size perp. to the anode wire (y) for different sectors.
178 // Pad sizes are defined as integral fractions ndiv of a basis pad size
181 for (Int_t i=0; i<4; i++) {
188 void AliMUONSegmentationV01::Init(Int_t chamber)
191 // Fill the arrays fCx (x-contour) and fNpxS (ix-contour) for each sector
192 // These arrays help in converting from real to pad co-ordinates and
194 // This version approximates concentric segmentation zones
197 printf("\n Initialise Segmentation V01\n");
200 fNpy=Int_t((*fRSec)[fNsec-1]/fDpy)+1;
202 (*fDpxD)[fNsec-1]=fDpx;
204 for (Int_t i=fNsec-2; i>=0; i--){
205 (*fDpxD)[i]=(*fDpxD)[fNsec-1]/(*fNDiv)[i];
209 // fill the arrays defining the pad segmentation boundaries
214 // loop over sections
215 for(isec=0; isec<fNsec; isec++) {
217 // loop over pads along the aode wires
218 for (Int_t iy=1; iy<=fNpy; iy++) {
220 Float_t x=iy*fDpy-fDpy/2;
221 if (x > (*fRSec)[isec]) {
225 ry=TMath::Sqrt((*fRSec)[isec]*(*fRSec)[isec]-x*x);
227 dnx= Int_t((ry-fCx[isec-1][iy])/(*fDpxD)[isec]);
228 if (isec < fNsec-1) {
229 if (TMath::Odd((Long_t)dnx)) dnx++;
231 fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
232 fCx[isec][iy]=fCx[isec-1][iy]+dnx*(*fDpxD)[isec];
233 } else if (isec == 1) {
234 dnx= Int_t((ry-fCx[isec-1][iy])/(*fDpxD)[isec]);
235 fNpxS[isec][iy]=fNpxS[isec-1][iy]+dnx;
236 add=4 - (fNpxS[isec][iy])%4;
237 if (add < 4) fNpxS[isec][iy]+=add;
238 dnx=fNpxS[isec][iy]-fNpxS[isec-1][iy];
239 fCx[isec][iy]=fCx[isec-1][iy]+dnx*(*fDpxD)[isec];
241 dnx=Int_t(ry/(*fDpxD)[isec]);
243 fCx[isec][iy]=dnx*(*fDpxD)[isec];
248 // reference to chamber
249 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
250 fChamber=&(pMUON->Chamber(chamber));
255 Int_t AliMUONSegmentationV01::Sector(Int_t ix, Int_t iy)
257 // Returns sector number for given pad position
259 Int_t absix=TMath::Abs(ix);
260 Int_t absiy=TMath::Abs(iy);
262 for (Int_t i=0; i<fNsec; i++) {
263 if (absix<=fNpxS[i][absiy]){
271 void AliMUONSegmentationV01::
272 GetPadI(Float_t x, Float_t y, Int_t &ix, Int_t &iy)
274 // Returns pad coordinates (ix,iy) for given real coordinates (x,y)
276 iy = (y-fOffsetY >0)?
277 Int_t((y-fOffsetY)/fDpy)+1
279 Int_t((y-fOffsetY)/fDpy)-1;
281 if (iy > fNpy) iy= fNpy;
282 if (iy < -fNpy) iy=-fNpy;
286 Float_t absx=TMath::Abs(x);
287 Int_t absiy=TMath::Abs(iy);
288 for (Int_t i=0; i < fNsec; i++) {
289 if (absx <= fCx[i][absiy]) {
295 ix= Int_t((absx-fCx[isec-1][absiy])/(*fDpxD)[isec])
296 +fNpxS[isec-1][absiy]+1;
297 } else if (isec == 0) {
298 ix= Int_t(absx/(*fDpxD)[isec])+1;
300 ix=fNpxS[fNsec-1][absiy]+1;
305 void AliMUONSegmentationV01::
306 GetPadC(Int_t ix, Int_t iy, Float_t &x, Float_t &y)
308 // Returns real coordinates (x,y) for given pad coordinates (ix,iy)
311 Float_t(iy*fDpy)-fDpy/2.+fOffsetY
313 Float_t(iy*fDpy)+fDpy/2.-fOffsetY;
316 Int_t isec=AliMUONSegmentationV01::Sector(ix,iy);
318 Int_t absix=TMath::Abs(ix);
319 Int_t absiy=TMath::Abs(iy);
321 x=fCx[isec-1][absiy]+(absix-fNpxS[isec-1][absiy])*(*fDpxD)[isec];
322 x=(ix>0) ? x-(*fDpxD)[isec]/2 : -x+(*fDpxD)[isec]/2;
328 void AliMUONSegmentationV01::
329 SetPad(Int_t ix, Int_t iy)
332 // Sets virtual pad coordinates, needed for evaluating pad response
333 // outside the tracking program
334 GetPadC(ix,iy,fX,fY);
335 fSector=Sector(ix,iy);
339 void AliMUONSegmentationV01::
340 FirstPad(Float_t xhit, Float_t yhit, Float_t dx, Float_t dy)
342 // Initialises iteration over pads for charge distribution algorithm
345 // Find the wire position (center of charge distribution)
346 Float_t x0a=GetAnod(xhit);
351 // and take fNsigma*sigma around this center
352 Float_t x01=x0a - dx;
353 Float_t x02=x0a + dx;
354 Float_t y01=yhit - dy;
355 Float_t y02=yhit + dy;
357 // find the pads over which the charge distributes
359 GetPadI(x01,y01,fIxmin,fIymin);
360 GetPadI(x02,y02,fIxmax,fIymax);
367 // Set current pad to lower left corner
368 if (fIxmax < fIxmin) fIxmax=fIxmin;
369 if (fIymax < fIymin) fIymax=fIymin;
372 GetPadC(fIx,fIy,fX,fY);
376 void AliMUONSegmentationV01::NextPad()
378 // Stepper for the iteration over pads
380 // Step to next pad in the integration region
382 // Step to next pad in integration region
386 // step from left to right
388 if (fX < fXmax && fX != 0) {
392 } else if (fIy != fIymax) {
395 // get y-position of next row (yc), xc not used here
396 GetPadC(fIx,fIy,xc,yc);
397 // get x-pad coordiante for first pad in row (fIx)
398 GetPadI(fXmin,yc,fIx,iyc);
403 GetPadC(fIx,fIy,fX,fY);
404 fSector=Sector(fIx,fIy);
406 (fSector ==-1 || fSector==0))
410 Int_t AliMUONSegmentationV01::MorePads()
413 // Stopping condition for the iterator over pads
415 // Are there more pads in the integration region
416 return (fIx != -1 || fIy != -1);
418 if ((fX >= fXmax && fIy >= fIymax) || fY==0) {
426 void AliMUONSegmentationV01::
427 IntegrationLimits(Float_t& x1,Float_t& x2,Float_t& y1, Float_t& y2)
429 // Returns integration limits for current pad
431 x1=fXhit-fX-Dpx(fSector)/2.;
433 y1=fYhit-fY-Dpy(fSector)/2.;
437 void AliMUONSegmentationV01::
438 Neighbours(Int_t iX, Int_t iY, Int_t* Nlist, Int_t Xlist[10], Int_t Ylist[10])
440 // Returns list of next neighbours for given Pad (iX, iY)
442 const Float_t kEpsilon=fDpy/1000;
445 Int_t ixx, iyy, isec1;
447 Int_t isec0=AliMUONSegmentationV01::Sector(iX,iY);
452 if (Xlist[i]==0) Xlist[i]++;
457 if (Xlist[i]==0) Xlist[i]--;
461 AliMUONSegmentationV01::GetPadC(iX,iY,x,y);
462 AliMUONSegmentationV01::GetPadI(x+kEpsilon,y+fDpy,ixx,iyy);
465 isec1=AliMUONSegmentationV01::Sector(ixx,iyy);
468 // no sector boundary crossing
474 } else if (isec1 < isec0) {
475 // finer segmentation
485 // coarser segmenation
487 if (TMath::Odd(iX-fNpxS[isec1-1][iY+1])) {
499 AliMUONSegmentationV01::GetPadC(iX,iY,x,y);
500 AliMUONSegmentationV01::GetPadI(x+kEpsilon,y-fDpy,ixx,iyy);
503 isec1=AliMUONSegmentationV01::Sector(ixx,iyy);
506 // no sector boundary crossing
514 } else if (isec1 < isec0) {
515 // finer segmentation
525 // coarser segmentation
527 if (TMath::Odd(iX-fNpxS[isec1-1][iY-1])) {
539 void AliMUONSegmentationV01::GiveTestPoints(Int_t &n, Float_t *x, Float_t *y) const
541 // Returns test point on the pad plane.
542 // Used during determination of the segmoid correction of the COG-method
545 x[0]=((*fRSec)[0]+(*fRSec)[1])/2/TMath::Sqrt(2.);
547 x[1]=((*fRSec)[1]+(*fRSec)[2])/2/TMath::Sqrt(2.);
549 x[2]=((*fRSec)[2]+(*fRSec)[3])/2/TMath::Sqrt(2.);
553 void AliMUONSegmentationV01::Draw(const char* opt) const
556 // Draws the segmentation zones
558 if (!strcmp(opt,"eventdisplay")) {
559 const int kColorMUON = kBlue;
561 TRotMatrix* rot000 = new TRotMatrix("Rot000"," ", 90, 0, 90, 90, 0, 0);
562 TRotMatrix* rot090 = new TRotMatrix("Rot090"," ", 90, 90, 90,180, 0, 0);
563 TRotMatrix* rot180 = new TRotMatrix("Rot180"," ", 90,180, 90,270, 0, 0);
564 TRotMatrix* rot270 = new TRotMatrix("Rot270"," ", 90,270, 90, 0, 0, 0);
566 char nameChamber[9], nameSense[9], nameFrame[9], nameNode[9];
567 char nameSense1[9], nameSense2[9];
570 sprintf(nameChamber,"C_MUON%d",fId+1);
571 sprintf(nameSense,"S_MUON%d",fId+1);
572 sprintf(nameSense1,"S1_MUON%d",fId+1);
573 sprintf(nameSense2,"S2_MUON%d",fId+1);
574 sprintf(nameFrame,"F_MUON%d",fId+1);
576 TNode* top=gAlice->GetGeometry()->GetNode("alice");
578 Float_t rmin = (*fRSec)[0]-3;
579 Float_t rmax = (*fRSec)[3]+3;
580 new TTUBE(nameChamber,"Mother","void",rmin,rmax,0.25,1.);
583 new TTUBE(nameSense,"Sens. region","void",rmin,rmax,0.25, 1.);
584 Float_t dx=(rmax-rmin)/2;
587 TBRIK* frMUON = new TBRIK(nameFrame,"Frame","void",dx,dy,dz);
589 sprintf(nameNode,"MUON%d",100+fId+1);
590 node = new TNode(nameNode,"ChamberNode",nameChamber,0,0,fChamber->Z(),"");
591 node->SetLineColor(kColorMUON);
592 AliMUON *pMUON = (AliMUON *) gAlice->GetModule("MUON");
593 (pMUON->Nodes())->Add(node);
595 sprintf(nameNode,"MUON%d",200+fId+1);
596 node = new TNode(nameNode,"Sens. Region Node",nameSense,0,0,0,"");
597 node->SetLineColor(kColorMUON);
600 sprintf(nameNode,"MUON%d",300+fId+1);
601 nodeF = new TNode(nameNode,"Frame0",frMUON,dr, 0, 0,rot000,"");
602 nodeF->SetLineColor(kColorMUON);
604 sprintf(nameNode,"MUON%d",400+fId+1);
605 nodeF = new TNode(nameNode,"Frame1",frMUON,0 ,dr,0,rot090,"");
606 nodeF->SetLineColor(kColorMUON);
608 sprintf(nameNode,"MUON%d",500+fId+1);
609 nodeF = new TNode(nameNode,"Frame2",frMUON,-dr,0,0,rot180,"");
610 nodeF->SetLineColor(kColorMUON);
612 sprintf(nameNode,"MUON%d",600+fId+1);
613 nodeF = new TNode(nameNode,"Frame3",frMUON,0,-dr,0,rot270,"");
614 nodeF->SetLineColor(kColorMUON);
618 Float_t dx=0.95/fCx[3][1]/2;
619 Float_t dy=0.95/(Float_t(Npy()))/2;
624 for (Int_t iy=1; iy<Npy(); iy++) {
625 for (Int_t isec=0; isec<4; isec++) {
630 x0=fCx[isec-1][iy]*dx;
635 box=new TBox(x0+xc,y0+yc,x1+xc,y1+yc);
636 box->SetFillColor(isec+1);
639 box=new TBox(-x1+xc,y0+yc,-x0+xc,y1+yc);
640 box->SetFillColor(isec+1);
643 box=new TBox(x0+xc,-y1+yc,x1+xc,-y0+yc);
644 box->SetFillColor(isec+1);
647 box=new TBox(-x1+xc,-y1+yc,-x0+xc,-y0+yc);
648 box->SetFillColor(isec+1);
654 void AliMUONSegmentationV01::SetCorrFunc(Int_t isec, TF1* func)
656 // Set the correction function
657 (*fCorrA)[isec]=func;
660 TF1* AliMUONSegmentationV01::CorrFunc(Int_t isec) const
662 // Get correction function
663 return (TF1*) (*fCorrA)[isec];
666 AliMUONSegmentationV01& AliMUONSegmentationV01::operator
667 =(const AliMUONSegmentationV01 & rhs)
669 // Dummy assignment operator