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 //_________________________________________________________________________
19 // Geometry class for EMCAL : singleton
20 // EMCAL consists of layers of scintillator and lead
21 // Places the the Barrel Geometry of The EMCAL at Midrapidity
22 // between 80 and 180(or 190) degrees of Phi and
24 // Number of Modules and Layers may be controlled by
25 // the name of the instance defined
26 // EMCAL geometry tree:
27 // EMCAL -> superModule -> module -> tower(cell)
29 // absId -> nSupMod -> nModule -> (nIphi,nIeta)
31 //*-- Author: Sahal Yacoob (LBL / UCT)
32 // and : Yves Schutz (SUBATECH)
33 // and : Jennifer Klay (LBL)
34 // SHASHLYK : Aleksei Pavlinov (WSU)
36 // --- AliRoot header files ---
38 #include <Riostream.h>
42 #include <TObjArray.h>
43 #include <TGeoManager.h>
45 #include <TGeoMatrix.h>
47 #include <TObjString.h>
48 #include <TClonesArray.h>
52 //#include "AliConst.h"
56 #include "AliEMCALGeometry.h"
57 #include "AliEMCALShishKebabTrd1Module.h"
58 #include "AliEMCALRecPoint.h"
59 #include "AliEMCALDigit.h"
60 #include "AliEMCALHistoUtilities.h"
62 ClassImp(AliEMCALGeometry)
64 // these initialisations are needed for a singleton
65 AliEMCALGeometry *AliEMCALGeometry::fgGeom = 0;
66 Bool_t AliEMCALGeometry::fgInit = kFALSE;
69 AliEMCALGeometry::AliEMCALGeometry()
71 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
72 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
73 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
74 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
75 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
76 fNCells(0),fNCellsInSupMod(0),fNCellsInModule(0),fNTRU(0),fNTRUEta(0),fNTRUPhi(0),fTrd1Angle(0.),f2Trd1Dx2(0.),
77 fPhiGapForSM(0.),fKey110DEG(0),fPhiBoundariesOfSM(0), fPhiCentersOfSM(0),fEtaMaxOfTRD1(0),
78 fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fCentersOfCellsEtaDir(0),
79 fCentersOfCellsXDir(0),fCentersOfCellsPhiDir(0),fEtaCentersOfCells(0),fPhiCentersOfCells(0),
80 fShishKebabTrd1Modules(0),fNAdditionalOpts(0)
82 // default ctor only for internal usage (singleton)
83 // must be kept public for root persistency purposes, but should never be called by the outside world
84 // CreateListOfTrd1Modules();
85 AliDebug(2, "AliEMCALGeometry : default ctor ");
87 //______________________________________________________________________
88 AliEMCALGeometry::AliEMCALGeometry(const Text_t* name, const Text_t* title)
89 : AliGeometry(name, title),
90 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
91 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
92 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
93 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
94 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
95 fNCells(0),fNCellsInSupMod(0),fNCellsInModule(0),fNTRU(0),fNTRUEta(0),fNTRUPhi(0),fTrd1Angle(0.),f2Trd1Dx2(0.),
96 fPhiGapForSM(0.),fKey110DEG(0),fPhiBoundariesOfSM(0), fPhiCentersOfSM(0), fEtaMaxOfTRD1(0),
97 fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fCentersOfCellsEtaDir(0),
98 fCentersOfCellsXDir(0),fCentersOfCellsPhiDir(0),fEtaCentersOfCells(0),fPhiCentersOfCells(0),
99 fShishKebabTrd1Modules(0),fNAdditionalOpts(0)
101 // ctor only for internal usage (singleton)
102 AliDebug(2, Form("AliEMCALGeometry(%s,%s) ", name,title));
106 CreateListOfTrd1Modules();
108 if (AliDebugLevel()>=2) {
113 //______________________________________________________________________
114 AliEMCALGeometry::AliEMCALGeometry(const AliEMCALGeometry& geom)
116 fGeoName(geom.fGeoName),
117 fArrayOpts(geom.fArrayOpts),
118 fAlFrontThick(geom.fAlFrontThick),
119 fECPbRadThickness(geom.fECPbRadThickness),
120 fECScintThick(geom.fECScintThick),
121 fNECLayers(geom.fNECLayers),
122 fArm1PhiMin(geom.fArm1PhiMin),
123 fArm1PhiMax(geom.fArm1PhiMax),
124 fArm1EtaMin(geom.fArm1EtaMin),
125 fArm1EtaMax(geom.fArm1EtaMax),
126 fIPDistance(geom.fIPDistance),
127 fShellThickness(geom.fShellThickness),
128 fZLength(geom.fZLength),
129 fGap2Active(geom.fGap2Active),
132 fSampling(geom.fSampling),
133 fNumberOfSuperModules(geom.fNumberOfSuperModules),
134 fSteelFrontThick(geom.fSteelFrontThick),
135 fFrontSteelStrip(geom.fFrontSteelStrip),
136 fLateralSteelStrip(geom.fLateralSteelStrip),
137 fPassiveScintThick(geom.fPassiveScintThick),
138 fPhiModuleSize(geom.fPhiModuleSize),
139 fEtaModuleSize(geom.fEtaModuleSize),
140 fPhiTileSize(geom.fPhiTileSize),
141 fEtaTileSize(geom.fEtaTileSize),
142 fLongModuleSize(geom.fLongModuleSize),
143 fNPhiSuperModule(geom.fNPhiSuperModule),
144 fNPHIdiv(geom.fNPHIdiv),
145 fNETAdiv(geom.fNETAdiv),
146 fNCells(geom.fNCells),
147 fNCellsInSupMod(geom.fNCellsInSupMod),
148 fNCellsInModule(geom.fNCellsInModule),
150 fNTRUEta(geom.fNTRUEta),
151 fNTRUPhi(geom.fNTRUPhi),
152 fTrd1Angle(geom.fTrd1Angle),
153 f2Trd1Dx2(geom.f2Trd1Dx2),
154 fPhiGapForSM(geom.fPhiGapForSM),
155 fKey110DEG(geom.fKey110DEG),
156 fPhiBoundariesOfSM(geom.fPhiBoundariesOfSM),
157 fPhiCentersOfSM(geom.fPhiCentersOfSM),
158 fEtaMaxOfTRD1(geom.fEtaMaxOfTRD1),
159 fTrd2AngleY(geom.fTrd2AngleY),
160 f2Trd2Dy2(geom.f2Trd2Dy2),
161 fEmptySpace(geom.fEmptySpace),
163 fTubsTurnAngle(geom.fTubsTurnAngle),
164 fCentersOfCellsEtaDir(geom.fCentersOfCellsEtaDir),
165 fCentersOfCellsXDir(geom.fCentersOfCellsXDir),
166 fCentersOfCellsPhiDir(geom.fCentersOfCellsPhiDir),
167 fEtaCentersOfCells(geom.fEtaCentersOfCells),
168 fPhiCentersOfCells(geom.fPhiCentersOfCells),
169 fShishKebabTrd1Modules(geom.fShishKebabTrd1Modules),
170 fNAdditionalOpts(geom.fNAdditionalOpts)
175 //______________________________________________________________________
176 AliEMCALGeometry::~AliEMCALGeometry(void){
179 //______________________________________________________________________
180 void AliEMCALGeometry::Init(void){
181 // Initializes the EMCAL parameters
182 // naming convention : GUV_WX_N_ gives the composition of a tower
183 // WX inform about the composition of the EM calorimeter section:
184 // thickness in mm of Pb radiator (W) and of scintillator (X), and number of scintillator layers (N)
185 // New geometry: EMCAL_55_25
186 // 24-aug-04 for shish-kebab
187 // SHISH_25 or SHISH_62
188 // 11-oct-05 - correction for pre final design
189 // Feb 06,2006 - decrease the weight of EMCAL
191 // Oct 30,2006 - SHISH_TRD1_CURRENT_1X1, SHISH_TRD1_CURRENT_2X2 or SHISH_TRD1_CURRENT_3X3;
194 fAdditionalOpts[0] = "nl="; // number of sampling layers (fNECLayers)
195 fAdditionalOpts[1] = "pbTh="; // cm, Thickness of the Pb (fECPbRadThick)
196 fAdditionalOpts[2] = "scTh="; // cm, Thickness of the Sc (fECScintThick)
197 fAdditionalOpts[3] = "latSS="; // cm, Thickness of lateral steel strip (fLateralSteelStrip)
199 fNAdditionalOpts = sizeof(fAdditionalOpts) / sizeof(char*);
201 fgInit = kFALSE; // Assume failed until proven otherwise.
202 fGeoName = GetName();
205 if(fGeoName.Contains("110DEG") || fGeoName.Contains("CURRENT")) fKey110DEG = 1; // for GetAbsCellId
206 fShishKebabTrd1Modules = 0;
207 fTrd2AngleY = f2Trd2Dy2 = fEmptySpace = fTubsR = fTubsTurnAngle = 0;
209 fNZ = 114; // granularity along Z (eta)
210 fNPhi = 168; // granularity in phi (azimuth)
211 fArm1PhiMin = 80.0; // degrees, Starting EMCAL Phi position
212 fArm1PhiMax = 190.0; // degrees, Ending EMCAL Phi position
213 fArm1EtaMin = -0.7; // pseudorapidity, Starting EMCAL Eta position
214 fArm1EtaMax = +0.7; // pseudorapidity, Ending EMCAL Eta position
215 fIPDistance = 454.0; // cm, Radial distance to inner surface of EMCAL
216 fPhiGapForSM = 0.; // cm, only for final TRD1 geometry
217 for(int i=0; i<12; i++) fMatrixOfSM[i] = 0;
220 if(fGeoName.Contains("SHISH")){ // Only shahslyk now
221 // 7-sep-05; integration issue
222 fArm1PhiMin = 80.0; // 60 -> 80
223 fArm1PhiMax = 180.0; // 180 -> 190
225 fNumberOfSuperModules = 10; // 12 = 6 * 2 (6 in phi, 2 in Z);
226 fSteelFrontThick = 2.54; // 9-sep-04
228 fFrontSteelStrip = fPassiveScintThick = 0.0; // 13-may-05
229 fLateralSteelStrip = 0.025; // before MAY 2005
230 fPhiModuleSize = fEtaModuleSize = 11.4;
231 fPhiTileSize = fEtaTileSize = 5.52; // (11.4-5.52*2)/2. = 0.18 cm (wall thickness)
234 fAlFrontThick = fGap2Active = 0;
235 fNPHIdiv = fNETAdiv = 2;
238 fECScintThick = fECPbRadThickness = 0.2;
239 fSampling = 1.; // 30-aug-04 - should be calculated
240 if(fGeoName.Contains("TWIST")) { // all about EMCAL module
241 fNZ = 27; // 16-sep-04
242 } else if(fGeoName.Contains("TRD")) {
243 fIPDistance = 428.0; // 11-may-05
244 fSteelFrontThick = 0.0; // 3.17 -> 0.0; 28-mar-05 : no stell plate
247 fPhiModuleSize = fEtaModuleSize = 12.26;
248 fNZ = 26; // 11-oct-04
249 fTrd1Angle = 1.3; // in degree
250 // 18-nov-04; 1./0.08112=12.327
251 // http://pdsfweb01.nersc.gov/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
252 if(fGeoName.Contains("TRD1")) { // 30-jan-05
254 fPhiGapForSM = 2.; // cm, only for final TRD1 geometry
255 if(fGeoName.Contains("MAY05") || fGeoName.Contains("WSUC") || fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")){
256 fNumberOfSuperModules = 12; // 20-may-05
257 if(fGeoName.Contains("WSUC")) fNumberOfSuperModules = 1; // 27-may-05
258 fNECLayers = 77; // (13-may-05 from V.Petrov)
259 fPhiModuleSize = 12.5; // 20-may-05 - rectangular shape
260 fEtaModuleSize = 11.9;
261 fECScintThick = fECPbRadThickness = 0.16;// (13-may-05 from V.Petrov)
262 fFrontSteelStrip = 0.025;// 0.025cm = 0.25mm (13-may-05 from V.Petrov)
263 fLateralSteelStrip = 0.01; // 0.01cm = 0.1mm (13-may-05 from V.Petrov) - was 0.025
264 fPassiveScintThick = 0.8; // 0.8cm = 8mm (13-may-05 from V.Petrov)
266 fTrd1Angle = 1.5; // 1.3 or 1.5
268 if(fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")) { // 9-sep-05
269 fNumberOfSuperModules = 10;
271 fNumberOfSuperModules = 12;// last two modules have size 10 degree in phi (180<phi<190)
272 fArm1PhiMax = 200.0; // for XEN1 and turn angle of super modules
274 if(fGeoName.Contains("FINAL")) {
275 fPhiModuleSize = 12.26 - fPhiGapForSM / Float_t(fNPhi); // first assumption
276 } else if(fGeoName.Contains("CURRENT")) {
277 fECScintThick = 0.176; // 10% of weight reduction
278 fECPbRadThickness = 0.144; //
279 fLateralSteelStrip = 0.015; // 0.015cm = 0.15mm (Oct 30, from Fred)
280 fPhiModuleSize = 12.00;
281 fPhiGapForSM = (12.26 - fPhiModuleSize)*fNPhi; // have to check
283 fEtaModuleSize = fPhiModuleSize;
284 if(fGeoName.Contains("HUGE")) fNECLayers *= 3; // 28-oct-05 for analysing leakage
287 } else if(fGeoName.Contains("TRD2")) { // 30-jan-05
288 fSteelFrontThick = 0.0; // 11-mar-05
289 fIPDistance+= fSteelFrontThick; // 1-feb-05 - compensate absence of steel plate
290 fTrd1Angle = 1.64; // 1.3->1.64
291 fTrd2AngleY = fTrd1Angle; // symmetric case now
292 fEmptySpace = 0.2; // 2 mm
293 fTubsR = fIPDistance; // 31-jan-05 - as for Fred case
295 fPhiModuleSize = fTubsR*2.*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
296 fPhiModuleSize -= fEmptySpace/2.; // 11-mar-05
297 fEtaModuleSize = fPhiModuleSize; // 20-may-05
300 fNPHIdiv = fNETAdiv = 2; // 13-oct-04 - division again
301 if(fGeoName.Contains("3X3")) { // 23-nov-04
302 fNPHIdiv = fNETAdiv = 3;
303 } else if(fGeoName.Contains("4X4")) {
304 fNPHIdiv = fNETAdiv = 4;
305 } else if(fGeoName.Contains("1X1")) {
306 fNPHIdiv = fNETAdiv = 1;
309 if(fGeoName.Contains("25")){
311 fECScintThick = fECPbRadThickness = 0.5;
313 if(fGeoName.Contains("WSUC")){ // 18-may-05 - about common structure
314 fShellThickness = 30.; // should be change
318 CheckAdditionalOptions();
319 DefineSamplingFraction();
321 fPhiTileSize = fPhiModuleSize/double(fNPHIdiv) - fLateralSteelStrip; // 13-may-05
322 fEtaTileSize = fEtaModuleSize/double(fNETAdiv) - fLateralSteelStrip; // 13-may-05
324 // constant for transition absid <--> indexes
325 fNCellsInModule = fNPHIdiv*fNETAdiv;
326 fNCellsInSupMod = fNCellsInModule*fNPhi*fNZ;
327 fNCells = fNCellsInSupMod*fNumberOfSuperModules;
328 if(GetKey110DEG()) fNCells -= fNCellsInSupMod;
330 fLongModuleSize = fNECLayers*(fECScintThick + fECPbRadThickness);
331 if(fGeoName.Contains("MAY05")) fLongModuleSize += (fFrontSteelStrip + fPassiveScintThick);
334 if(fGeoName.Contains("TRD")) {
335 f2Trd1Dx2 = fEtaModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd1Angle*TMath::DegToRad()/2.);
336 if(fGeoName.Contains("TRD2")) { // 27-jan-05
337 f2Trd2Dy2 = fPhiModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
340 } else Fatal("Init", "%s is an undefined geometry!", fGeoName.Data()) ;
342 fNPhiSuperModule = fNumberOfSuperModules/2;
343 if(fNPhiSuperModule<1) fNPhiSuperModule = 1;
345 fShellThickness = fAlFrontThick + fGap2Active + fNECLayers*GetECScintThick()+(fNECLayers-1)*GetECPbRadThick();
346 if(fGeoName.Contains("SHISH")) {
347 fShellThickness = fSteelFrontThick + fLongModuleSize;
348 if(fGeoName.Contains("TWIST")) { // 13-sep-04
349 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + fPhiModuleSize*fEtaModuleSize);
350 fShellThickness += fSteelFrontThick;
351 } else if(fGeoName.Contains("TRD")) { // 1-oct-04
352 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + f2Trd1Dx2*f2Trd1Dx2);
353 fShellThickness += fSteelFrontThick;
355 fParSM[0] = GetShellThickness()/2.;
356 fParSM[1] = GetPhiModuleSize() * GetNPhi()/2.;
361 fZLength = 2.*ZFromEtaR(fIPDistance+fShellThickness,fArm1EtaMax); // Z coverage
362 fEnvelop[0] = fIPDistance; // mother volume inner radius
363 fEnvelop[1] = fIPDistance + fShellThickness; // mother volume outer r.
364 fEnvelop[2] = 1.00001*fZLength; // add some padding for mother volume.
366 fNumberOfSuperModules = 12;
368 // SM phi boundaries - (0,1),(2,3) .. (10,11) - has the same boundaries; Nov 7, 2006
369 fPhiBoundariesOfSM.Set(fNumberOfSuperModules);
370 fPhiCentersOfSM.Set(fNumberOfSuperModules/2);
371 fPhiBoundariesOfSM[0] = TMath::PiOver2() - TMath::ATan2(fParSM[1] , fIPDistance); // 1th and 2th modules)
372 fPhiBoundariesOfSM[1] = TMath::PiOver2() + TMath::ATan2(fParSM[1] , fIPDistance);
373 fPhiCentersOfSM[0] = TMath::PiOver2();
374 for(int i=1; i<=4; i++) { // from 2th ro 9th
375 fPhiBoundariesOfSM[2*i] = fPhiBoundariesOfSM[0] + 20.*TMath::DegToRad()*i;
376 fPhiBoundariesOfSM[2*i+1] = fPhiBoundariesOfSM[1] + 20.*TMath::DegToRad()*i;
377 fPhiCentersOfSM[i] = fPhiCentersOfSM[0] + 20.*TMath::DegToRad()*i;
379 fPhiBoundariesOfSM[11] = 190.*TMath::DegToRad();
380 fPhiBoundariesOfSM[10] = fPhiBoundariesOfSM[11] - TMath::ATan2((fParSM[1]) , fIPDistance);
381 fPhiCentersOfSM[5] = (fPhiBoundariesOfSM[10]+fPhiBoundariesOfSM[11])/2.;
385 //TRU parameters. These parameters values are not the final ones.
392 void AliEMCALGeometry::PrintGeometry()
394 // Separate routine is callable from broswer; Nov 7,2006
395 printf("\nInit: geometry of EMCAL named %s is as follows:\n", fGeoName.Data());
396 printf("Granularity: %d in eta and %d in phi\n", GetNZ(), GetNPhi()) ;
397 printf("Layout: phi = (%7.1f, %7.1f), eta = (%5.2f, %5.2f), IP = %7.2f -> for EMCAL envelope only\n",
398 GetArm1PhiMin(), GetArm1PhiMax(),GetArm1EtaMin(), GetArm1EtaMax(), GetIPDistance() );
400 printf( " ECAL : %d x (%f cm Pb, %f cm Sc) \n",
401 GetNECLayers(), GetECPbRadThick(), GetECScintThick() ) ;
402 printf(" fSampling %5.2f \n", fSampling );
403 if(fGeoName.Contains("SHISH")){
404 printf(" fIPDistance %6.3f cm \n", fIPDistance);
405 if(fSteelFrontThick>0.)
406 printf(" fSteelFrontThick %6.3f cm \n", fSteelFrontThick);
407 printf(" fNPhi %i | fNZ %i \n", fNPhi, fNZ);
408 printf(" fNCellsInModule %i : fNCellsInSupMod %i : fNCells %i\n",fNCellsInModule, fNCellsInSupMod, fNCells);
409 if(fGeoName.Contains("MAY05")){
410 printf(" fFrontSteelStrip %6.4f cm (thickness of front steel strip)\n",
412 printf(" fLateralSteelStrip %6.4f cm (thickness of lateral steel strip)\n",
414 printf(" fPassiveScintThick %6.4f cm (thickness of front passive Sc tile)\n",
417 printf(" X:Y module size %6.3f , %6.3f cm \n", fPhiModuleSize, fEtaModuleSize);
418 printf(" X:Y tile size %6.3f , %6.3f cm \n", fPhiTileSize, fEtaTileSize);
419 printf(" #of sampling layers %i(fNECLayers) \n", fNECLayers);
420 printf(" fLongModuleSize %6.3f cm \n", fLongModuleSize);
421 printf(" #supermodule in phi direction %i \n", fNPhiSuperModule );
423 if(fGeoName.Contains("TRD")) {
424 printf(" fTrd1Angle %7.4f\n", fTrd1Angle);
425 printf(" f2Trd1Dx2 %7.4f\n", f2Trd1Dx2);
426 if(fGeoName.Contains("TRD2")) {
427 printf(" fTrd2AngleY %7.4f\n", fTrd2AngleY);
428 printf(" f2Trd2Dy2 %7.4f\n", f2Trd2Dy2);
429 printf(" fTubsR %7.2f cm\n", fTubsR);
430 printf(" fTubsTurnAngle %7.4f\n", fTubsTurnAngle);
431 printf(" fEmptySpace %7.4f cm\n", fEmptySpace);
432 } else if(fGeoName.Contains("TRD1")){
433 printf("SM dimensions(TRD1) : dx %7.2f dy %7.2f dz %7.2f (SMOD, BOX)\n",
434 fParSM[0],fParSM[1],fParSM[2]);
435 printf(" fPhiGapForSM %7.4f cm (%7.4f <- phi size in degree)\n",
436 fPhiGapForSM, TMath::ATan2(fPhiGapForSM,fIPDistance)*TMath::RadToDeg());
437 if(GetKey110DEG()) printf(" Last two modules have size 10 degree in phi (180<phi<190)\n");
438 printf(" phi SM boundaries \n");
439 for(int i=0; i<fPhiBoundariesOfSM.GetSize()/2.; i++) {
440 printf(" %i : %7.5f(%7.2f) -> %7.5f(%7.2f) : center %7.5f(%7.2f) \n", i,
441 fPhiBoundariesOfSM[2*i], fPhiBoundariesOfSM[2*i]*TMath::RadToDeg(),
442 fPhiBoundariesOfSM[2*i+1], fPhiBoundariesOfSM[2*i+1]*TMath::RadToDeg(),
443 fPhiCentersOfSM[i], fPhiCentersOfSM[i]*TMath::RadToDeg());
445 printf(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n",
446 fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1);
448 printf("\n Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize());
449 for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
450 printf(" ind %2.2i : z %8.3f : x %8.3f \n", i,
451 fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i));
452 int ind=0; // Nov 21,2006
453 for(Int_t iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
454 ind = iphi*fCentersOfCellsEtaDir.GetSize() + i;
455 printf("%6.4f ", fEtaCentersOfCells[ind]);
456 if((iphi+1)%12 == 0) printf("\n");
461 printf("\n Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize());
462 for(Int_t i=0; i<fCentersOfCellsPhiDir.GetSize(); i++) {
463 double phi=fPhiCentersOfCells.At(i);
464 printf(" ind %2.2i : y %8.3f : phi %7.5f(%6.2f) \n", i, fCentersOfCellsPhiDir.At(i),
465 phi, phi*TMath::RadToDeg());
471 void AliEMCALGeometry::PrintCellIndexes(Int_t absId, int pri, char *tit)
474 Int_t nSupMod, nModule, nIphi, nIeta;
478 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
479 printf(" %s | absId : %i -> nSupMod %i nModule %i nIphi %i nIeta %i \n", tit, absId, nSupMod, nModule, nIphi, nIeta);
481 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
482 printf(" local SM index : iphi %i : ieta %i \n", iphi,ieta);
483 GetGlobal(absId, vg);
484 printf(" vglob : mag %7.2f : perp %7.2f : z %7.2f : eta %6.4f : phi %6.4f(%6.2f) \n",
485 vg.Mag(), vg.Perp(), vg.Z(), vg.Eta(), vg.Phi(), vg.Phi()*TMath::RadToDeg());
489 //______________________________________________________________________
490 void AliEMCALGeometry::CheckAdditionalOptions()
493 //Additional options that
494 //can be used to select
495 //the specific geometry of
498 fArrayOpts = new TObjArray;
499 Int_t nopt = AliEMCALHistoUtilities::ParseString(fGeoName, *fArrayOpts);
500 if(nopt==1) { // no aditional option(s)
501 fArrayOpts->Delete();
506 for(Int_t i=1; i<nopt; i++){
507 TObjString *o = (TObjString*)fArrayOpts->At(i);
509 TString addOpt = o->String();
511 for(Int_t j=0; j<fNAdditionalOpts; j++) {
512 TString opt = fAdditionalOpts[j];
513 if(addOpt.Contains(opt,TString::kIgnoreCase)) {
519 AliDebug(2,Form("<E> option |%s| unavailable : ** look to the file AliEMCALGeometry.h **\n",
523 AliDebug(2,Form("<I> option |%s| is valid : number %i : |%s|\n",
524 addOpt.Data(), indj, fAdditionalOpts[indj]));
525 if (addOpt.Contains("NL=",TString::kIgnoreCase)) {// number of sampling layers
526 sscanf(addOpt.Data(),"NL=%i", &fNECLayers);
527 AliDebug(2,Form(" fNECLayers %i (new) \n", fNECLayers));
528 } else if(addOpt.Contains("PBTH=",TString::kIgnoreCase)) {//Thickness of the Pb(fECPbRadThicknes)
529 sscanf(addOpt.Data(),"PBTH=%f", &fECPbRadThickness);
530 } else if(addOpt.Contains("SCTH=",TString::kIgnoreCase)) {//Thickness of the Sc(fECScintThick)
531 sscanf(addOpt.Data(),"SCTH=%f", &fECScintThick);
532 } else if(addOpt.Contains("LATSS=",TString::kIgnoreCase)) {// Thickness of lateral steel strip (fLateralSteelStrip)
533 sscanf(addOpt.Data(),"LATSS=%f", &fLateralSteelStrip);
534 AliDebug(2,Form(" fLateralSteelStrip %f (new) \n", fLateralSteelStrip));
540 void AliEMCALGeometry::DefineSamplingFraction()
543 // Look http://rhic.physics.wayne.edu/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
544 // Keep for compatibilty
546 if(fNECLayers == 69) { // 10% layer reduction
548 } else if(fNECLayers == 61) { // 20% layer reduction
550 } else if(fNECLayers == 77) {
551 if (fECScintThick>0.175 && fECScintThick<0.177) { // 10% Pb thicknes reduction
552 fSampling = 10.5; // fECScintThick = 0.176, fECPbRadThickness=0.144;
553 } else if(fECScintThick>0.191 && fECScintThick<0.193) { // 20% Pb thicknes reduction
554 fSampling = 8.93; // fECScintThick = 0.192, fECPbRadThickness=0.128;
559 //____________________________________________________________________________
560 void AliEMCALGeometry::FillTRU(const TClonesArray * digits, TClonesArray * ampmatrix, TClonesArray * timeRmatrix) {
563 // Orders digits ampitudes list in fNTRU TRUs (384 cells) per supermodule.
564 // Each TRU is a TMatrixD, and they are kept in TClonesArrays. The number of
565 // TRU in phi is fNTRUPhi, and the number of TRU in eta is fNTRUEta.
566 // Last 2 modules are half size in Phi, I considered that the number of TRU
567 // is maintained for the last modules but decision not taken. If different,
568 // then this must be changed.
573 if(fNTRUEta*fNTRUPhi != fNTRU)
574 Error("FillTRU"," Wrong number of TRUS per Eta or Phi");
576 //Initilize and declare variables
577 //List of TRU matrices initialized to 0.
578 Int_t nCellsPhi = fNPhi*2/fNTRUPhi;
579 Int_t nCellsPhi2 = fNPhi/fNTRUPhi; //HalfSize modules
580 Int_t nCellsEta = fNZ*2/fNTRUEta;
591 //List of TRU matrices initialized to 0.
592 for(Int_t k = 0; k < fNTRU*fNumberOfSuperModules; k++){
593 TMatrixD * amptrus = new TMatrixD(nCellsPhi,nCellsEta) ;
594 TMatrixD * timeRtrus = new TMatrixD(nCellsPhi,nCellsEta) ;
595 for(Int_t i = 0; i < nCellsPhi; i++){
596 for(Int_t j = 0; j < nCellsEta; j++){
597 (*amptrus)(i,j) = 0.0;
598 (*timeRtrus)(i,j) = 0.0;
601 new((*ampmatrix)[k]) TMatrixD(*amptrus) ;
602 new((*timeRmatrix)[k]) TMatrixD(*timeRtrus) ;
605 AliEMCALDigit * dig ;
607 //Digits loop to fill TRU matrices with amplitudes.
608 for(Int_t idig = 0 ; idig < digits->GetEntriesFast() ; idig++){
610 dig = dynamic_cast<AliEMCALDigit *>(digits->At(idig)) ;
611 amp = dig->GetAmp() ; // Energy of the digit (arbitrary units)
612 id = dig->GetId() ; // Id label of the cell
613 timeR = dig->GetTimeR() ; // Earliest time of the digit
615 //Get eta and phi cell position in supermodule
616 Bool_t bCell = GetCellIndex(id, iSupMod, nModule, nIphi, nIeta) ;
618 Error("FillTRU","Wrong cell id number") ;
620 GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
622 //Check to which TRU in the supermodule belongs the cell.
623 //Supermodules are divided in a TRU matrix of dimension
624 //(fNTRUPhi,fNTRUEta).
625 //Each TRU is a cell matrix of dimension (nCellsPhi,nCellsEta)
627 //First calculate the row and column in the supermodule
628 //of the TRU to which the cell belongs.
629 Int_t col = ieta/nCellsEta;
630 Int_t row = iphi/nCellsPhi;
632 row = iphi/nCellsPhi2;
633 //Calculate label number of the TRU
634 Int_t itru = row + col*fNTRUPhi + iSupMod*fNTRU ;
636 //Fill TRU matrix with cell values
637 TMatrixD * amptrus = dynamic_cast<TMatrixD *>(ampmatrix->At(itru)) ;
638 TMatrixD * timeRtrus = dynamic_cast<TMatrixD *>(timeRmatrix->At(itru)) ;
640 //Calculate row and column of the cell inside the TRU with number itru
641 Int_t irow = iphi - row * nCellsPhi;
643 irow = iphi - row * nCellsPhi2;
644 Int_t icol = ieta - col * nCellsEta;
646 (*amptrus)(irow,icol) = amp ;
647 (*timeRtrus)(irow,icol) = timeR ;
652 //______________________________________________________________________
653 void AliEMCALGeometry::GetCellPhiEtaIndexInSModuleFromTRUIndex(const Int_t itru, const Int_t iphitru, const Int_t ietatru, Int_t &iphiSM, Int_t &ietaSM) const
656 // This method transforms the (eta,phi) index of cells in a
657 // TRU matrix into Super Module (eta,phi) index.
659 // Calculate in which row and column where the TRU are
662 Int_t col = itru/ fNTRUPhi ;
663 Int_t row = itru - col*fNTRUPhi ;
665 //Calculate the (eta,phi) index in SM
666 Int_t nCellsPhi = fNPhi*2/fNTRUPhi;
667 Int_t nCellsEta = fNZ*2/fNTRUEta;
669 iphiSM = nCellsPhi*row + iphitru ;
670 ietaSM = nCellsEta*col + ietatru ;
673 //______________________________________________________________________
674 AliEMCALGeometry * AliEMCALGeometry::GetInstance(){
675 // Returns the pointer of the unique instance
677 AliEMCALGeometry * rv = static_cast<AliEMCALGeometry *>( fgGeom );
681 //______________________________________________________________________
682 AliEMCALGeometry* AliEMCALGeometry::GetInstance(const Text_t* name,
683 const Text_t* title){
684 // Returns the pointer of the unique instance
686 AliEMCALGeometry * rv = 0;
688 if ( strcmp(name,"") == 0 ) rv = 0;
690 fgGeom = new AliEMCALGeometry(name, title);
691 if ( fgInit ) rv = (AliEMCALGeometry * ) fgGeom;
697 } // end if strcmp(name,"")
699 if ( strcmp(fgGeom->GetName(), name) != 0) {
700 printf("\ncurrent geometry is %s : ", fgGeom->GetName());
701 printf(" you cannot call %s ", name);
703 rv = (AliEMCALGeometry *) fgGeom;
709 Bool_t AliEMCALGeometry::IsInEMCAL(Double_t x, Double_t y, Double_t z) const {
710 // Checks whether point is inside the EMCal volume, used in AliEMCALv*.cxx
712 // Code uses cylindrical approximation made of inner radius (for speed)
714 // Points behind EMCAl, i.e. R > outer radius, but eta, phi in acceptance
715 // are considered to inside
717 Double_t r=sqrt(x*x+y*y);
719 if ( r > fEnvelop[0] ) {
721 theta = TMath::ATan2(r,z);
726 eta = -TMath::Log(TMath::Tan(theta/2.));
727 if (eta < fArm1EtaMin || eta > fArm1EtaMax)
730 Double_t phi = TMath::ATan2(y,x) * 180./TMath::Pi();
731 if (phi > fArm1PhiMin && phi < fArm1PhiMax)
739 // == Shish-kebab cases ==
741 Int_t AliEMCALGeometry::GetAbsCellId(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta) const
745 // 13-oct-05; 110 degree case
746 // May 31, 2006; ALICE numbering scheme:
747 // 0 <= nSupMod < fNumberOfSuperModules
748 // 0 <= nModule < fNPHI * fNZ ( fNPHI * fNZ/2 for fKey110DEG=1)
749 // 0 <= nIphi < fNPHIdiv
750 // 0 <= nIeta < fNETAdiv
751 // 0 <= absid < fNCells
752 static Int_t id=0; // have to change from 0 to fNCells-1
753 if(fKey110DEG == 1 && nSupMod >= 10) { // 110 degree case; last two supermodules
754 id = fNCellsInSupMod*10 + (fNCellsInSupMod/2)*(nSupMod-10);
756 id = fNCellsInSupMod*nSupMod;
758 id += fNCellsInModule *nModule;
759 id += fNPHIdiv *nIphi;
761 if(id<0 || id >= fNCells) {
762 // printf(" wrong numerations !!\n");
763 // printf(" id %6i(will be force to -1)\n", id);
764 // printf(" fNCells %6i\n", fNCells);
765 // printf(" nSupMod %6i\n", nSupMod);
766 // printf(" nModule %6i\n", nModule);
767 // printf(" nIphi %6i\n", nIphi);
768 // printf(" nIeta %6i\n", nIeta);
769 id = -TMath::Abs(id); // if negative something wrong
774 Bool_t AliEMCALGeometry::CheckAbsCellId(Int_t absId) const
776 // May 31, 2006; only trd1 now
777 if(absId<0 || absId >= fNCells) return kFALSE;
781 Bool_t AliEMCALGeometry::GetCellIndex(Int_t absId,Int_t &nSupMod,Int_t &nModule,Int_t &nIphi,Int_t &nIeta) const
783 // 21-sep-04; 19-oct-05;
784 // May 31, 2006; ALICE numbering scheme:
787 // absId - cell is as in Geant, 0<= absId < fNCells;
789 // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
790 // nModule - module number in SM, 0<= nModule < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
791 // nIphi - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv;
792 // nIeta - cell number in eta driection inside module; 0<= nIeta < fNETAdiv;
794 static Int_t tmp=0, sm10=0;
795 if(!CheckAbsCellId(absId)) return kFALSE;
797 sm10 = fNCellsInSupMod*10;
798 if(fKey110DEG == 1 && absId >= sm10) { // 110 degree case; last two supermodules
799 nSupMod = (absId-sm10) / (fNCellsInSupMod/2) + 10;
800 tmp = (absId-sm10) % (fNCellsInSupMod/2);
802 nSupMod = absId / fNCellsInSupMod;
803 tmp = absId % fNCellsInSupMod;
806 nModule = tmp / fNCellsInModule;
807 tmp = tmp % fNCellsInModule;
808 nIphi = tmp / fNPHIdiv;
809 nIeta = tmp % fNPHIdiv;
814 void AliEMCALGeometry::GetModulePhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, int &iphim, int &ietam) const
816 // added nSupMod; - 19-oct-05 !
817 // Alice numbering scheme - Jun 01,2006
818 // ietam, iphi - indexes of module in two dimensional grid of SM
819 // ietam - have to change from 0 to fNZ-1
820 // iphim - have to change from 0 to nphi-1 (fNPhi-1 or fNPhi/2-1)
823 if(fKey110DEG == 1 && nSupMod>=10) nphi = fNPhi/2;
826 ietam = nModule/nphi;
827 iphim = nModule%nphi;
830 void AliEMCALGeometry::GetCellPhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta,
831 int &iphi, int &ieta) const
834 // Added nSupMod; Nov 25, 05
835 // Alice numbering scheme - Jun 01,2006
837 // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
838 // nModule - module number in SM, 0<= nModule < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
839 // nIphi - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv;
840 // nIeta - cell number in eta driection inside module; 0<= nIeta < fNETAdiv;
843 // ieta, iphi - indexes of cell(tower) in two dimensional grid of SM
844 // ieta - have to change from 0 to (fNZ*fNETAdiv-1)
845 // iphi - have to change from 0 to (fNPhi*fNPHIdiv-1 or fNPhi*fNPHIdiv/2-1)
847 static Int_t iphim, ietam;
849 GetModulePhiEtaIndexInSModule(nSupMod,nModule, iphim, ietam);
850 // ieta = ietam*fNETAdiv + (1-nIeta); // x(module) = -z(SM)
851 ieta = ietam*fNETAdiv + (fNETAdiv - 1 - nIeta); // x(module) = -z(SM)
852 iphi = iphim*fNPHIdiv + nIphi; // y(module) = y(SM)
855 AliDebug(1,Form(" nSupMod %i nModule %i nIphi %i nIeta %i => ieta %i iphi %i\n",
856 nSupMod, nModule, nIphi, nIeta, ieta, iphi));
859 Int_t AliEMCALGeometry::GetSuperModuleNumber(Int_t absId) const
861 // Return the number of the supermodule given the absolute
862 // ALICE numbering id
864 static Int_t nSupMod, nModule, nIphi, nIeta;
865 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
869 void AliEMCALGeometry::GetModuleIndexesFromCellIndexesInSModule(Int_t nSupMod, Int_t iphi, Int_t ieta,
870 Int_t &iphim, Int_t &ietam, Int_t &nModule) const
872 // Transition from cell indexes (ieta,iphi) to module indexes (ietam,iphim, nModule)
874 nphi = GetNumberOfModuleInPhiDirection(nSupMod);
876 ietam = ieta/fNETAdiv;
877 iphim = iphi/fNPHIdiv;
878 nModule = ietam * nphi + iphim;
881 Int_t AliEMCALGeometry::GetAbsCellIdFromCellIndexes(Int_t nSupMod, Int_t iphi, Int_t ieta) const
883 // Transition from super module number(nSupMod) and cell indexes (ieta,iphi) to absId
884 static Int_t ietam, iphim, nModule;
885 static Int_t nIeta, nIphi; // cell indexes in module
887 GetModuleIndexesFromCellIndexesInSModule(nSupMod, iphi, ieta, ietam, iphim, nModule);
889 nIeta = ieta%fNETAdiv;
890 nIeta = fNETAdiv - 1 - nIeta;
891 nIphi = iphi%fNPHIdiv;
893 return GetAbsCellId(nSupMod, nModule, nIphi, nIeta);
897 // Methods for AliEMCALRecPoint - Feb 19, 2006
898 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t &xr, Double_t &yr, Double_t &zr) const
900 // Look to see what the relative
901 // position inside a given cell is
903 // Alice numbering scheme - Jun 08, 2006
905 // absId - cell is as in Geant, 0<= absId < fNCells;
907 // xr,yr,zr - x,y,z coordinates of cell with absId inside SM
909 // Shift index taking into account the difference between standard SM
910 // and SM of half size in phi direction
911 const Int_t phiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
912 static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
913 if(!CheckAbsCellId(absId)) return kFALSE;
915 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
916 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta);
918 xr = fCentersOfCellsXDir.At(ieta);
919 zr = fCentersOfCellsEtaDir.At(ieta);
922 yr = fCentersOfCellsPhiDir.At(iphi);
924 yr = fCentersOfCellsPhiDir.At(iphi + phiIndexShift);
926 AliDebug(1,Form("absId %i nSupMod %i iphi %i ieta %i xr %f yr %f zr %f ",absId,nSupMod,iphi,ieta,xr,yr,zr));
931 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t loc[3]) const
933 // Alice numbering scheme - Jun 03, 2006
934 loc[0] = loc[1] = loc[2]=0.0;
935 if(RelPosCellInSModule(absId, loc[0],loc[1],loc[2])) {
941 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, TVector3 &vloc) const
943 static Double_t loc[3];
944 if(RelPosCellInSModule(absId,loc)) {
945 vloc.SetXYZ(loc[0], loc[1], loc[2]);
951 // Alice numbering scheme - Jun 03, 2006
954 void AliEMCALGeometry::CreateListOfTrd1Modules()
956 // Generate the list of Trd1 modules
957 // which will make up the EMCAL
960 AliDebug(2,Form(" AliEMCALGeometry::CreateListOfTrd1Modules() started "));
962 AliEMCALShishKebabTrd1Module *mod=0, *mTmp=0; // current module
963 if(fShishKebabTrd1Modules == 0) {
964 fShishKebabTrd1Modules = new TList;
965 fShishKebabTrd1Modules->SetName("ListOfTRD1");
966 for(int iz=0; iz< GetNZ(); iz++) {
968 mod = new AliEMCALShishKebabTrd1Module(TMath::Pi()/2.,this);
970 mTmp = new AliEMCALShishKebabTrd1Module(*mod);
973 fShishKebabTrd1Modules->Add(mod);
976 AliDebug(2,Form(" Already exits : "));
978 mod = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(fShishKebabTrd1Modules->GetSize()-1);
979 fEtaMaxOfTRD1 = mod->GetMaxEtaOfModule(0);
981 AliDebug(2,Form(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n",
982 fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1));
984 // Jun 01, 2006 - ALICE numbering scheme
985 // define grid for cells in eta(z) and x directions in local coordinates system of SM
986 // Works just for 2x2 case only -- ?? start here
989 // Define grid for cells in phi(y) direction in local coordinates system of SM
990 // as for 2X2 as for 3X3 - Nov 8,2006
992 AliDebug(2,Form(" Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize()));
993 Int_t ind=0; // this is phi index
994 Int_t iphi=0, ieta=0, nModule=0, iphiTemp;
995 Double_t xr, zr, theta, phi, eta, r, x,y;
997 Double_t ytCenterModule, ytCenterCell;
999 fCentersOfCellsPhiDir.Set(fNPhi*fNPHIdiv);
1000 fPhiCentersOfCells.Set(fNPhi*fNPHIdiv);
1002 Double_t R0 = GetIPDistance() + GetLongModuleSize()/2.;
1003 for(Int_t it=0; it<fNPhi; it++) { // cycle on modules
1004 ytCenterModule = -fParSM[1] + fPhiModuleSize*(2*it+1)/2; // center of module
1005 for(Int_t ic=0; ic<fNPHIdiv; ic++) { // cycle on cells in module
1007 ytCenterCell = ytCenterModule + fPhiTileSize *(2*ic-1)/2.;
1008 } else if(fNPHIdiv==3){
1009 ytCenterCell = ytCenterModule + fPhiTileSize *(ic-1);
1010 } else if(fNPHIdiv==1){
1011 ytCenterCell = ytCenterModule;
1013 fCentersOfCellsPhiDir.AddAt(ytCenterCell,ind);
1014 // Define grid on phi direction
1015 // Grid is not the same for different eta bin;
1016 // Effect is small but is still here
1017 phi = TMath::ATan2(ytCenterCell, R0);
1018 fPhiCentersOfCells.AddAt(phi, ind);
1020 AliDebug(2,Form(" ind %2.2i : y %8.3f ", ind, fCentersOfCellsPhiDir.At(ind)));
1025 fCentersOfCellsEtaDir.Set(fNZ *fNETAdiv);
1026 fCentersOfCellsXDir.Set(fNZ *fNETAdiv);
1027 fEtaCentersOfCells.Set(fNZ *fNETAdiv * fNPhi*fNPHIdiv);
1028 AliDebug(2,Form(" Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize()));
1029 for(Int_t it=0; it<fNZ; it++) {
1030 AliEMCALShishKebabTrd1Module *trd1 = GetShishKebabModule(it);
1032 for(Int_t ic=0; ic<fNETAdiv; ic++) {
1034 trd1->GetCenterOfCellInLocalCoordinateofSM(ic, xr, zr); // case of 2X2
1035 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1037 trd1->GetCenterOfCellInLocalCoordinateofSM_3X3(ic, xr, zr); // case of 3X3
1038 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1040 trd1->GetCenterOfCellInLocalCoordinateofSM_1X1(xr, zr); // case of 1X1
1041 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1043 fCentersOfCellsXDir.AddAt(float(xr) - fParSM[0],ieta);
1044 fCentersOfCellsEtaDir.AddAt(float(zr) - fParSM[2],ieta);
1045 // Define grid on eta direction for each bin in phi
1046 for(int iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
1047 x = xr + trd1->GetRadius();
1048 y = fCentersOfCellsPhiDir[iphi];
1049 r = TMath::Sqrt(x*x + y*y + zr*zr);
1050 theta = TMath::ACos(zr/r);
1051 eta = AliEMCALShishKebabTrd1Module::ThetaToEta(theta);
1052 // ind = ieta*fCentersOfCellsPhiDir.GetSize() + iphi;
1053 ind = iphi*fCentersOfCellsEtaDir.GetSize() + ieta;
1054 fEtaCentersOfCells.AddAt(eta, ind);
1056 //printf(" ieta %i : xr + trd1->GetRadius() %f : zr %f : eta %f \n", ieta, xr + trd1->GetRadius(), zr, eta);
1059 for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1060 AliDebug(2,Form(" ind %2.2i : z %8.3f : x %8.3f", i+1,
1061 fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i)));
1066 void AliEMCALGeometry::GetTransformationForSM()
1068 //Uses the geometry manager to
1069 //load the transformation matrix
1070 //for the supermodules
1072 static Bool_t transInit=kFALSE;
1073 if(transInit) return;
1076 if(gGeoManager == 0) {
1077 Info("CreateTransformationForSM() "," Load geometry : TGeoManager::Import()");
1080 TGeoNode *tn = gGeoManager->GetTopNode();
1081 TGeoNode *node=0, *xen1 = 0;
1082 for(i=0; i<tn->GetNdaughters(); i++) {
1083 node = tn->GetDaughter(i);
1084 TString ns(node->GetName());
1085 if(ns.Contains(GetNameOfEMCALEnvelope())) {
1091 Info("CreateTransformationForSM() "," geometry has not EMCAL envelope with name %s",
1092 GetNameOfEMCALEnvelope());
1095 printf(" i %i : EMCAL Envelope is %s : #SM %i \n", i, xen1->GetName(), xen1->GetNdaughters());
1096 for(i=0; i<xen1->GetNdaughters(); i++) {
1097 TGeoNodeMatrix *sm = (TGeoNodeMatrix*)xen1->GetDaughter(i);
1098 fMatrixOfSM[i] = sm->GetMatrix();
1099 //Compiler doesn't like this syntax...
1100 // printf(" %i : matrix %x \n", i, fMatrixOfSM[i]);
1105 void AliEMCALGeometry::GetGlobal(const Double_t *loc, Double_t *glob, int ind) const
1107 // Figure out the global numbering
1108 // of a given supermodule from the
1110 // Alice numbering - Jun 03,2006
1111 // if(fMatrixOfSM[0] == 0) GetTransformationForSM();
1113 if(ind>=0 && ind < GetNumberOfSuperModules()) {
1114 fMatrixOfSM[ind]->LocalToMaster(loc, glob);
1118 void AliEMCALGeometry::GetGlobal(const TVector3 &vloc, TVector3 &vglob, int ind) const
1120 //Figure out the global numbering
1121 //of a given supermodule from the
1122 //local numbering given a 3-vector location
1124 static Double_t tglob[3], tloc[3];
1126 GetGlobal(tloc, tglob, ind);
1127 vglob.SetXYZ(tglob[0], tglob[1], tglob[2]);
1130 void AliEMCALGeometry::GetGlobal(Int_t absId , double glob[3]) const
1132 // Alice numbering scheme - Jun 03, 2006
1133 static Int_t nSupMod, nModule, nIphi, nIeta;
1134 static double loc[3];
1136 glob[0]=glob[1]=glob[2]=0.0; // bad case
1137 if(RelPosCellInSModule(absId, loc)) {
1138 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
1139 fMatrixOfSM[nSupMod]->LocalToMaster(loc, glob);
1143 void AliEMCALGeometry::GetGlobal(Int_t absId , TVector3 &vglob) const
1145 // Alice numbering scheme - Jun 03, 2006
1146 static Double_t glob[3];
1148 GetGlobal(absId, glob);
1149 vglob.SetXYZ(glob[0], glob[1], glob[2]);
1153 void AliEMCALGeometry::GetGlobal(const AliRecPoint *rp, TVector3 &vglob) const
1155 // Figure out the global numbering
1156 // of a given supermodule from the
1157 // local numbering for RecPoints
1159 static TVector3 vloc;
1160 static Int_t nSupMod, nModule, nIphi, nIeta;
1162 AliRecPoint *rpTmp = (AliRecPoint*)rp; // const_cast ??
1164 AliEMCALRecPoint *rpEmc = (AliEMCALRecPoint*)rpTmp;
1166 GetCellIndex(rpEmc->GetAbsId(0), nSupMod, nModule, nIphi, nIeta);
1167 rpTmp->GetLocalPosition(vloc);
1168 GetGlobal(vloc, vglob, nSupMod);
1171 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Double_t &eta,Double_t &phi) const
1173 // Nov 16, 2006- float to double
1174 // version for TRD1 only
1175 static TVector3 vglob;
1176 GetGlobal(absId, vglob);
1181 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Float_t &eta,Float_t &phi) const
1183 // Nov 16,2006 - should be discard in future
1184 static TVector3 vglob;
1185 GetGlobal(absId, vglob);
1186 eta = float(vglob.Eta());
1187 phi = float(vglob.Phi());
1190 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSM(Int_t nSupMod, Double_t &phiMin, Double_t &phiMax) const
1192 // 0<= nSupMod <=11; phi in rad
1194 if(nSupMod<0 || nSupMod >11) return kFALSE;
1196 phiMin = fPhiBoundariesOfSM[2*i];
1197 phiMax = fPhiBoundariesOfSM[2*i+1];
1201 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSMGap(Int_t nPhiSec, Double_t &phiMin, Double_t &phiMax) const
1203 // 0<= nPhiSec <=4; phi in rad
1204 // 0; gap boundaries between 0th&2th | 1th&3th SM
1205 // 1; gap boundaries between 2th&4th | 3th&5th SM
1206 // 2; gap boundaries between 4th&6th | 5th&7th SM
1207 // 3; gap boundaries between 6th&8th | 7th&9th SM
1208 // 4; gap boundaries between 8th&10th | 9th&11th SM
1209 if(nPhiSec<0 || nPhiSec >4) return kFALSE;
1210 phiMin = fPhiBoundariesOfSM[2*nPhiSec+1];
1211 phiMax = fPhiBoundariesOfSM[2*nPhiSec+2];
1215 Bool_t AliEMCALGeometry::SuperModuleNumberFromEtaPhi(Double_t eta, Double_t phi, Int_t &nSupMod) const
1217 // Return false if phi belongs a phi cracks between SM
1221 if(TMath::Abs(eta) > fEtaMaxOfTRD1) return kFALSE;
1223 phi = TVector2::Phi_0_2pi(phi); // move phi to (0,2pi) boundaries
1224 for(i=0; i<6; i++) {
1225 if(phi>=fPhiBoundariesOfSM[2*i] && phi<=fPhiBoundariesOfSM[2*i+1]) {
1227 if(eta < 0.0) nSupMod++;
1228 AliDebug(1,Form("eta %f phi %f(%5.2f) : nSupMod %i : #bound %i", eta,phi,phi*TMath::RadToDeg(), nSupMod,i));
1235 Bool_t AliEMCALGeometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi, Int_t &absId) const
1238 // stay here - phi problem as usual
1239 static Int_t nSupMod, i, ieta, iphi, etaShift, nphi;
1240 static Double_t absEta=0.0, d=0.0, dmin=0.0, phiLoc;
1241 absId = nSupMod = - 1;
1242 if(SuperModuleNumberFromEtaPhi(eta, phi, nSupMod)) {
1244 phi = TVector2::Phi_0_2pi(phi);
1245 phiLoc = phi - fPhiCentersOfSM[nSupMod/2];
1246 nphi = fPhiCentersOfCells.GetSize();
1248 phiLoc = phi - 190.*TMath::DegToRad();
1252 dmin = TMath::Abs(fPhiCentersOfCells[0]-phiLoc);
1254 for(i=1; i<nphi; i++) {
1255 d = TMath::Abs(fPhiCentersOfCells[i] - phiLoc);
1260 // printf(" i %i : d %f : dmin %f : fPhiCentersOfCells[i] %f \n", i, d, dmin, fPhiCentersOfCells[i]);
1262 // odd SM are turned with respect of even SM - reverse indexes
1263 AliDebug(2,Form(" iphi %i : dmin %f (phi %f, phiLoc %f ) ", iphi, dmin, phi, phiLoc));
1265 absEta = TMath::Abs(eta);
1266 etaShift = iphi*fCentersOfCellsEtaDir.GetSize();
1267 dmin = TMath::Abs(fEtaCentersOfCells[etaShift]-absEta);
1269 for(i=1; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1270 d = TMath::Abs(fEtaCentersOfCells[i+etaShift] - absEta);
1276 AliDebug(2,Form(" ieta %i : dmin %f (eta=%f) : nSupMod %i ", ieta, dmin, eta, nSupMod));
1278 if(eta<0) iphi = (nphi-1) - iphi;
1279 absId = GetAbsCellIdFromCellIndexes(nSupMod, iphi, ieta);
1286 AliEMCALShishKebabTrd1Module* AliEMCALGeometry::GetShishKebabModule(Int_t neta)
1288 //This method was too long to be
1289 //included in the header file - the
1290 //rule checker complained about it's
1291 //length, so we move it here. It returns the
1292 //shishkebabmodule at a given eta index point.
1294 static AliEMCALShishKebabTrd1Module* trd1=0;
1295 if(fShishKebabTrd1Modules && neta>=0 && neta<fShishKebabTrd1Modules->GetSize()) {
1296 trd1 = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(neta);
1301 void AliEMCALGeometry::Browse(TBrowser* b)
1303 if(fShishKebabTrd1Modules) b->Add(fShishKebabTrd1Modules);
1306 Bool_t AliEMCALGeometry::IsFolder() const
1308 if(fShishKebabTrd1Modules) return kTRUE;