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)
39 // --- AliRoot header files ---
40 #include <Riostream.h>
42 #include <TClonesArray.h>
43 #include <TGeoManager.h>
44 #include <TGeoMatrix.h>
47 #include <TObjArray.h>
48 #include <TObjString.h>
55 #include "AliEMCALGeometry.h"
56 #include "AliEMCALShishKebabTrd1Module.h"
57 #include "AliEMCALRecPoint.h"
58 #include "AliEMCALDigit.h"
59 #include "AliEMCALHistoUtilities.h"
61 ClassImp(AliEMCALGeometry)
63 // these initialisations are needed for a singleton
64 AliEMCALGeometry *AliEMCALGeometry::fgGeom = 0;
65 Bool_t AliEMCALGeometry::fgInit = kFALSE;
66 Char_t* AliEMCALGeometry::fgDefaultGeometryName = "SHISH_77_TRD1_2X2_FINAL_110DEG";
69 // You can create the AliEMCALGeometry object independently from anything.
70 // You have to use just the correct name of geometry. If name is empty string the
71 // default name of geometry will be used.
73 // AliEMCALGeometry* g = AliEMCALGeometry::GetInstance(name,title); // first time
75 // g = AliEMCALGeometry::GetInstance(); // after first time
78 AliEMCALGeometry::AliEMCALGeometry()
80 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
81 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
82 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
83 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
84 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
85 fNCells(0),fNCellsInSupMod(0),fNCellsInModule(0),fNTRU(0),fNTRUEta(0),fNTRUPhi(0),fTrd1Angle(0.),f2Trd1Dx2(0.),
86 fPhiGapForSM(0.),fKey110DEG(0),fPhiBoundariesOfSM(0), fPhiCentersOfSM(0),fEtaMaxOfTRD1(0),
87 fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fCentersOfCellsEtaDir(0),
88 fCentersOfCellsXDir(0),fCentersOfCellsPhiDir(0),fEtaCentersOfCells(0),fPhiCentersOfCells(0),
89 fShishKebabTrd1Modules(0), fNAdditionalOpts(0),
90 fILOSS(-1), fIHADR(-1)
92 // default ctor only for internal usage (singleton)
93 // must be kept public for root persistency purposes, but should never be called by the outside world
94 // CreateListOfTrd1Modules();
95 AliDebug(2, "AliEMCALGeometry : default ctor ");
97 //______________________________________________________________________
98 AliEMCALGeometry::AliEMCALGeometry(const Text_t* name, const Text_t* title)
99 : AliGeometry(name, title),
100 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
101 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
102 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
103 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
104 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
105 fNCells(0),fNCellsInSupMod(0),fNCellsInModule(0),fNTRU(0),fNTRUEta(0),fNTRUPhi(0),fTrd1Angle(0.),f2Trd1Dx2(0.),
106 fPhiGapForSM(0.),fKey110DEG(0),fPhiBoundariesOfSM(0), fPhiCentersOfSM(0), fEtaMaxOfTRD1(0),
107 fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fCentersOfCellsEtaDir(0),
108 fCentersOfCellsXDir(0),fCentersOfCellsPhiDir(0),fEtaCentersOfCells(0),fPhiCentersOfCells(0),
109 fShishKebabTrd1Modules(0),fNAdditionalOpts(0),
110 fILOSS(-1), fIHADR(-1)
112 // ctor only for internal usage (singleton)
113 AliDebug(2, Form("AliEMCALGeometry(%s,%s) ", name,title));
117 CreateListOfTrd1Modules();
119 if (AliDebugLevel()>=2) {
124 //______________________________________________________________________
125 AliEMCALGeometry::AliEMCALGeometry(const AliEMCALGeometry& geom)
127 fGeoName(geom.fGeoName),
128 fArrayOpts(geom.fArrayOpts),
129 fAlFrontThick(geom.fAlFrontThick),
130 fECPbRadThickness(geom.fECPbRadThickness),
131 fECScintThick(geom.fECScintThick),
132 fNECLayers(geom.fNECLayers),
133 fArm1PhiMin(geom.fArm1PhiMin),
134 fArm1PhiMax(geom.fArm1PhiMax),
135 fArm1EtaMin(geom.fArm1EtaMin),
136 fArm1EtaMax(geom.fArm1EtaMax),
137 fIPDistance(geom.fIPDistance),
138 fShellThickness(geom.fShellThickness),
139 fZLength(geom.fZLength),
140 fGap2Active(geom.fGap2Active),
143 fSampling(geom.fSampling),
144 fNumberOfSuperModules(geom.fNumberOfSuperModules),
145 fSteelFrontThick(geom.fSteelFrontThick),
146 fFrontSteelStrip(geom.fFrontSteelStrip),
147 fLateralSteelStrip(geom.fLateralSteelStrip),
148 fPassiveScintThick(geom.fPassiveScintThick),
149 fPhiModuleSize(geom.fPhiModuleSize),
150 fEtaModuleSize(geom.fEtaModuleSize),
151 fPhiTileSize(geom.fPhiTileSize),
152 fEtaTileSize(geom.fEtaTileSize),
153 fLongModuleSize(geom.fLongModuleSize),
154 fNPhiSuperModule(geom.fNPhiSuperModule),
155 fNPHIdiv(geom.fNPHIdiv),
156 fNETAdiv(geom.fNETAdiv),
157 fNCells(geom.fNCells),
158 fNCellsInSupMod(geom.fNCellsInSupMod),
159 fNCellsInModule(geom.fNCellsInModule),
161 fNTRUEta(geom.fNTRUEta),
162 fNTRUPhi(geom.fNTRUPhi),
163 fTrd1Angle(geom.fTrd1Angle),
164 f2Trd1Dx2(geom.f2Trd1Dx2),
165 fPhiGapForSM(geom.fPhiGapForSM),
166 fKey110DEG(geom.fKey110DEG),
167 fPhiBoundariesOfSM(geom.fPhiBoundariesOfSM),
168 fPhiCentersOfSM(geom.fPhiCentersOfSM),
169 fEtaMaxOfTRD1(geom.fEtaMaxOfTRD1),
170 fTrd2AngleY(geom.fTrd2AngleY),
171 f2Trd2Dy2(geom.f2Trd2Dy2),
172 fEmptySpace(geom.fEmptySpace),
174 fTubsTurnAngle(geom.fTubsTurnAngle),
175 fCentersOfCellsEtaDir(geom.fCentersOfCellsEtaDir),
176 fCentersOfCellsXDir(geom.fCentersOfCellsXDir),
177 fCentersOfCellsPhiDir(geom.fCentersOfCellsPhiDir),
178 fEtaCentersOfCells(geom.fEtaCentersOfCells),
179 fPhiCentersOfCells(geom.fPhiCentersOfCells),
180 fShishKebabTrd1Modules(geom.fShishKebabTrd1Modules),
181 fNAdditionalOpts(geom.fNAdditionalOpts),
182 fILOSS(geom.fILOSS), fIHADR(geom.fIHADR)
187 //______________________________________________________________________
188 AliEMCALGeometry::~AliEMCALGeometry(void){
191 //______________________________________________________________________
192 void AliEMCALGeometry::Init(void){
193 // Initializes the EMCAL parameters
194 // naming convention : GUV_WX_N_ gives the composition of a tower
195 // WX inform about the composition of the EM calorimeter section:
196 // thickness in mm of Pb radiator (W) and of scintillator (X), and number of scintillator layers (N)
197 // New geometry: EMCAL_55_25
198 // 24-aug-04 for shish-kebab
199 // SHISH_25 or SHISH_62
200 // 11-oct-05 - correction for pre final design
201 // Feb 06,2006 - decrease the weight of EMCAL
203 // Oct 30,2006 - SHISH_TRD1_CURRENT_1X1, SHISH_TRD1_CURRENT_2X2 or SHISH_TRD1_CURRENT_3X3;
206 fAdditionalOpts[0] = "nl="; // number of sampling layers (fNECLayers)
207 fAdditionalOpts[1] = "pbTh="; // cm, Thickness of the Pb (fECPbRadThick)
208 fAdditionalOpts[2] = "scTh="; // cm, Thickness of the Sc (fECScintThick)
209 fAdditionalOpts[3] = "latSS="; // cm, Thickness of lateral steel strip (fLateralSteelStrip)
210 fAdditionalOpts[4] = "allILOSS="; // = 0,1,2,3,4 (4 - energy loss without fluctuation)
211 fAdditionalOpts[5] = "allIHADR="; // = 0,1,2 (0 - no hadronic interaction)
213 fNAdditionalOpts = sizeof(fAdditionalOpts) / sizeof(char*);
215 fgInit = kFALSE; // Assume failed until proven otherwise.
216 fGeoName = GetName();
219 if(fGeoName.Contains("110DEG") || fGeoName.Contains("CURRENT")) fKey110DEG = 1; // for GetAbsCellId
220 fShishKebabTrd1Modules = 0;
221 fTrd2AngleY = f2Trd2Dy2 = fEmptySpace = fTubsR = fTubsTurnAngle = 0;
223 fNZ = 114; // granularity along Z (eta)
224 fNPhi = 168; // granularity in phi (azimuth)
225 fArm1PhiMin = 80.0; // degrees, Starting EMCAL Phi position
226 fArm1PhiMax = 190.0; // degrees, Ending EMCAL Phi position
227 fArm1EtaMin = -0.7; // pseudorapidity, Starting EMCAL Eta position
228 fArm1EtaMax = +0.7; // pseudorapidity, Ending EMCAL Eta position
229 fIPDistance = 454.0; // cm, Radial distance to inner surface of EMCAL
230 fPhiGapForSM = 0.; // cm, only for final TRD1 geometry
231 for(int i=0; i<12; i++) fMatrixOfSM[i] = 0;
234 if(fGeoName.Contains("SHISH")){ // Only shahslyk now
235 // 7-sep-05; integration issue
236 fArm1PhiMin = 80.0; // 60 -> 80
237 fArm1PhiMax = 180.0; // 180 -> 190
239 fNumberOfSuperModules = 10; // 12 = 6 * 2 (6 in phi, 2 in Z);
240 fSteelFrontThick = 2.54; // 9-sep-04
242 fFrontSteelStrip = fPassiveScintThick = 0.0; // 13-may-05
243 fLateralSteelStrip = 0.025; // before MAY 2005
244 fPhiModuleSize = fEtaModuleSize = 11.4;
245 fPhiTileSize = fEtaTileSize = 5.52; // (11.4-5.52*2)/2. = 0.18 cm (wall thickness)
248 fAlFrontThick = fGap2Active = 0;
249 fNPHIdiv = fNETAdiv = 2;
252 fECScintThick = fECPbRadThickness = 0.2;
253 fSampling = 1.; // 30-aug-04 - should be calculated
254 if(fGeoName.Contains("TWIST")) { // all about EMCAL module
255 fNZ = 27; // 16-sep-04
256 } else if(fGeoName.Contains("TRD")) {
257 fIPDistance = 428.0; // 11-may-05
258 fSteelFrontThick = 0.0; // 3.17 -> 0.0; 28-mar-05 : no stell plate
261 fPhiModuleSize = fEtaModuleSize = 12.26;
262 fNZ = 26; // 11-oct-04
263 fTrd1Angle = 1.3; // in degree
264 // 18-nov-04; 1./0.08112=12.327
265 // http://pdsfweb01.nersc.gov/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
266 if(fGeoName.Contains("TRD1")) { // 30-jan-05
268 fPhiGapForSM = 2.; // cm, only for final TRD1 geometry
269 if(fGeoName.Contains("MAY05") || fGeoName.Contains("WSUC") || fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")){
270 fNumberOfSuperModules = 12; // 20-may-05
271 if(fGeoName.Contains("WSUC")) fNumberOfSuperModules = 1; // 27-may-05
272 fNECLayers = 77; // (13-may-05 from V.Petrov)
273 fPhiModuleSize = 12.5; // 20-may-05 - rectangular shape
274 fEtaModuleSize = 11.9;
275 fECScintThick = fECPbRadThickness = 0.16;// (13-may-05 from V.Petrov)
276 fFrontSteelStrip = 0.025;// 0.025cm = 0.25mm (13-may-05 from V.Petrov)
277 fLateralSteelStrip = 0.01; // 0.01cm = 0.1mm (13-may-05 from V.Petrov) - was 0.025
278 fPassiveScintThick = 0.8; // 0.8cm = 8mm (13-may-05 from V.Petrov)
280 fTrd1Angle = 1.5; // 1.3 or 1.5
282 if(fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")) { // 9-sep-05
283 fNumberOfSuperModules = 10;
285 fNumberOfSuperModules = 12;// last two modules have size 10 degree in phi (180<phi<190)
286 fArm1PhiMax = 200.0; // for XEN1 and turn angle of super modules
288 if(fGeoName.Contains("FINAL")) {
289 fPhiModuleSize = 12.26 - fPhiGapForSM / Float_t(fNPhi); // first assumption
290 } else if(fGeoName.Contains("CURRENT")) {
291 fECScintThick = 0.176; // 10% of weight reduction
292 fECPbRadThickness = 0.144; //
293 fLateralSteelStrip = 0.015; // 0.015cm = 0.15mm (Oct 30, from Fred)
294 fPhiModuleSize = 12.00;
295 fPhiGapForSM = (12.26 - fPhiModuleSize)*fNPhi; // have to check
297 fEtaModuleSize = fPhiModuleSize;
298 if(fGeoName.Contains("HUGE")) fNECLayers *= 3; // 28-oct-05 for analysing leakage
301 } else if(fGeoName.Contains("TRD2")) { // 30-jan-05
302 fSteelFrontThick = 0.0; // 11-mar-05
303 fIPDistance+= fSteelFrontThick; // 1-feb-05 - compensate absence of steel plate
304 fTrd1Angle = 1.64; // 1.3->1.64
305 fTrd2AngleY = fTrd1Angle; // symmetric case now
306 fEmptySpace = 0.2; // 2 mm
307 fTubsR = fIPDistance; // 31-jan-05 - as for Fred case
309 fPhiModuleSize = fTubsR*2.*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
310 fPhiModuleSize -= fEmptySpace/2.; // 11-mar-05
311 fEtaModuleSize = fPhiModuleSize; // 20-may-05
314 fNPHIdiv = fNETAdiv = 2; // 13-oct-04 - division again
315 if(fGeoName.Contains("3X3")) { // 23-nov-04
316 fNPHIdiv = fNETAdiv = 3;
317 } else if(fGeoName.Contains("4X4")) {
318 fNPHIdiv = fNETAdiv = 4;
319 } else if(fGeoName.Contains("1X1")) {
320 fNPHIdiv = fNETAdiv = 1;
323 if(fGeoName.Contains("25")){
325 fECScintThick = fECPbRadThickness = 0.5;
327 if(fGeoName.Contains("WSUC")){ // 18-may-05 - about common structure
328 fShellThickness = 30.; // should be change
332 CheckAdditionalOptions();
333 DefineSamplingFraction();
335 fPhiTileSize = fPhiModuleSize/double(fNPHIdiv) - fLateralSteelStrip; // 13-may-05
336 fEtaTileSize = fEtaModuleSize/double(fNETAdiv) - fLateralSteelStrip; // 13-may-05
338 // constant for transition absid <--> indexes
339 fNCellsInModule = fNPHIdiv*fNETAdiv;
340 fNCellsInSupMod = fNCellsInModule*fNPhi*fNZ;
341 fNCells = fNCellsInSupMod*fNumberOfSuperModules;
342 if(GetKey110DEG()) fNCells -= fNCellsInSupMod;
344 fLongModuleSize = fNECLayers*(fECScintThick + fECPbRadThickness);
345 if(fGeoName.Contains("MAY05")) fLongModuleSize += (fFrontSteelStrip + fPassiveScintThick);
348 if(fGeoName.Contains("TRD")) {
349 f2Trd1Dx2 = fEtaModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd1Angle*TMath::DegToRad()/2.);
350 if(fGeoName.Contains("TRD2")) { // 27-jan-05
351 f2Trd2Dy2 = fPhiModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
354 } else Fatal("Init", "%s is an undefined geometry!", fGeoName.Data()) ;
356 fNPhiSuperModule = fNumberOfSuperModules/2;
357 if(fNPhiSuperModule<1) fNPhiSuperModule = 1;
359 fShellThickness = fAlFrontThick + fGap2Active + fNECLayers*GetECScintThick()+(fNECLayers-1)*GetECPbRadThick();
360 if(fGeoName.Contains("SHISH")) {
361 fShellThickness = fSteelFrontThick + fLongModuleSize;
362 if(fGeoName.Contains("TWIST")) { // 13-sep-04
363 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + fPhiModuleSize*fEtaModuleSize);
364 fShellThickness += fSteelFrontThick;
365 } else if(fGeoName.Contains("TRD")) { // 1-oct-04
366 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + f2Trd1Dx2*f2Trd1Dx2);
367 fShellThickness += fSteelFrontThick;
369 fParSM[0] = GetShellThickness()/2.;
370 fParSM[1] = GetPhiModuleSize() * GetNPhi()/2.;
375 fZLength = 2.*ZFromEtaR(fIPDistance+fShellThickness,fArm1EtaMax); // Z coverage
376 fEnvelop[0] = fIPDistance; // mother volume inner radius
377 fEnvelop[1] = fIPDistance + fShellThickness; // mother volume outer r.
378 fEnvelop[2] = 1.00001*fZLength; // add some padding for mother volume.
380 fNumberOfSuperModules = 12;
382 // SM phi boundaries - (0,1),(2,3) .. (10,11) - has the same boundaries; Nov 7, 2006
383 fPhiBoundariesOfSM.Set(fNumberOfSuperModules);
384 fPhiCentersOfSM.Set(fNumberOfSuperModules/2);
385 fPhiBoundariesOfSM[0] = TMath::PiOver2() - TMath::ATan2(fParSM[1] , fIPDistance); // 1th and 2th modules)
386 fPhiBoundariesOfSM[1] = TMath::PiOver2() + TMath::ATan2(fParSM[1] , fIPDistance);
387 fPhiCentersOfSM[0] = TMath::PiOver2();
388 for(int i=1; i<=4; i++) { // from 2th ro 9th
389 fPhiBoundariesOfSM[2*i] = fPhiBoundariesOfSM[0] + 20.*TMath::DegToRad()*i;
390 fPhiBoundariesOfSM[2*i+1] = fPhiBoundariesOfSM[1] + 20.*TMath::DegToRad()*i;
391 fPhiCentersOfSM[i] = fPhiCentersOfSM[0] + 20.*TMath::DegToRad()*i;
393 fPhiBoundariesOfSM[11] = 190.*TMath::DegToRad();
394 fPhiBoundariesOfSM[10] = fPhiBoundariesOfSM[11] - TMath::ATan2((fParSM[1]) , fIPDistance);
395 fPhiCentersOfSM[5] = (fPhiBoundariesOfSM[10]+fPhiBoundariesOfSM[11])/2.;
397 //TRU parameters. These parameters values are not the final ones.
402 // Define TGeoMatrix of SM - Jan 19, 2007 (just fro TRD1)
403 if(fGeoName.Contains("TRD1")) { // copy code from AliEMCALv0::CreateSmod()
404 int nphism = GetNumberOfSuperModules()/2;
405 double dphi = (GetArm1PhiMax() - GetArm1PhiMin())/nphism;
406 double rpos = (GetEnvelop(0) + GetEnvelop(1))/2.;
407 double phi, phiRad, xpos, ypos, zpos;
408 for(int i=0; i<nphism; i++){
409 phi = GetArm1PhiMin() + dphi*(2*i+1)/2.; // phi= 90, 110, 130, 150, 170, 190
410 phiRad = phi*TMath::Pi()/180.;
411 xpos = rpos * TMath::Cos(phiRad);
412 ypos = rpos * TMath::Sin(phiRad);
415 xpos += (fParSM[1]/2. * TMath::Sin(phiRad));
416 ypos -= (fParSM[1]/2. * TMath::Cos(phiRad));
420 TGeoRotation *geoRot0 = new TGeoRotation("geoRot0", 90.0, phi, 90.0, 90.0+phi, 0.0, 0.0);
421 fMatrixOfSM[ind] = new TGeoCombiTrans(Form("EmcalSM%2.2i",ind),
422 xpos,ypos, zpos, geoRot0);
425 double phiy = 90. + phi + 180.;
426 if(phiy>=360.) phiy -= 360.;
427 TGeoRotation *geoRot1 = new TGeoRotation("geoRot1", 90.0, phi, 90.0, phiy, 180.0, 0.0);
428 fMatrixOfSM[ind] = new TGeoCombiTrans(Form("EmcalSM%2.2i",ind),
429 xpos,ypos,-zpos, geoRot1);
433 AliInfo(" is ended");
436 void AliEMCALGeometry::PrintGeometry()
438 // Separate routine is callable from broswer; Nov 7,2006
439 printf("\nInit: geometry of EMCAL named %s :\n", fGeoName.Data());
441 for(Int_t i=0; i<fArrayOpts->GetEntries(); i++){
442 TObjString *o = (TObjString*)fArrayOpts->At(i);
443 printf(" %i : %s \n", i, o->String().Data());
446 printf("Granularity: %d in eta and %d in phi\n", GetNZ(), GetNPhi()) ;
447 printf("Layout: phi = (%7.1f, %7.1f), eta = (%5.2f, %5.2f), IP = %7.2f -> for EMCAL envelope only\n",
448 GetArm1PhiMin(), GetArm1PhiMax(),GetArm1EtaMin(), GetArm1EtaMax(), GetIPDistance() );
450 printf( " ECAL : %d x (%f cm Pb, %f cm Sc) \n",
451 GetNECLayers(), GetECPbRadThick(), GetECScintThick() ) ;
452 printf(" fSampling %5.2f \n", fSampling );
453 if(fGeoName.Contains("SHISH")){
454 printf(" fIPDistance %6.3f cm \n", fIPDistance);
455 if(fSteelFrontThick>0.)
456 printf(" fSteelFrontThick %6.3f cm \n", fSteelFrontThick);
457 printf(" fNPhi %i | fNZ %i \n", fNPhi, fNZ);
458 printf(" fNCellsInModule %i : fNCellsInSupMod %i : fNCells %i\n",fNCellsInModule, fNCellsInSupMod, fNCells);
459 if(fGeoName.Contains("MAY05")){
460 printf(" fFrontSteelStrip %6.4f cm (thickness of front steel strip)\n",
462 printf(" fLateralSteelStrip %6.4f cm (thickness of lateral steel strip)\n",
464 printf(" fPassiveScintThick %6.4f cm (thickness of front passive Sc tile)\n",
467 printf(" X:Y module size %6.3f , %6.3f cm \n", fPhiModuleSize, fEtaModuleSize);
468 printf(" X:Y tile size %6.3f , %6.3f cm \n", fPhiTileSize, fEtaTileSize);
469 printf(" #of sampling layers %i(fNECLayers) \n", fNECLayers);
470 printf(" fLongModuleSize %6.3f cm \n", fLongModuleSize);
471 printf(" #supermodule in phi direction %i \n", fNPhiSuperModule );
473 printf(" fILOSS %i : fIHADR %i \n", fILOSS, fIHADR);
474 if(fGeoName.Contains("TRD")) {
475 printf(" fTrd1Angle %7.4f\n", fTrd1Angle);
476 printf(" f2Trd1Dx2 %7.4f\n", f2Trd1Dx2);
477 if(fGeoName.Contains("TRD2")) {
478 printf(" fTrd2AngleY %7.4f\n", fTrd2AngleY);
479 printf(" f2Trd2Dy2 %7.4f\n", f2Trd2Dy2);
480 printf(" fTubsR %7.2f cm\n", fTubsR);
481 printf(" fTubsTurnAngle %7.4f\n", fTubsTurnAngle);
482 printf(" fEmptySpace %7.4f cm\n", fEmptySpace);
483 } else if(fGeoName.Contains("TRD1")){
484 printf("SM dimensions(TRD1) : dx %7.2f dy %7.2f dz %7.2f (SMOD, BOX)\n",
485 fParSM[0],fParSM[1],fParSM[2]);
486 printf(" fPhiGapForSM %7.4f cm (%7.4f <- phi size in degree)\n",
487 fPhiGapForSM, TMath::ATan2(fPhiGapForSM,fIPDistance)*TMath::RadToDeg());
488 if(GetKey110DEG()) printf(" Last two modules have size 10 degree in phi (180<phi<190)\n");
489 printf(" phi SM boundaries \n");
490 for(int i=0; i<fPhiBoundariesOfSM.GetSize()/2.; i++) {
491 printf(" %i : %7.5f(%7.2f) -> %7.5f(%7.2f) : center %7.5f(%7.2f) \n", i,
492 fPhiBoundariesOfSM[2*i], fPhiBoundariesOfSM[2*i]*TMath::RadToDeg(),
493 fPhiBoundariesOfSM[2*i+1], fPhiBoundariesOfSM[2*i+1]*TMath::RadToDeg(),
494 fPhiCentersOfSM[i], fPhiCentersOfSM[i]*TMath::RadToDeg());
496 printf(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n",
497 fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1);
499 printf("\n Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize());
500 for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
501 printf(" ind %2.2i : z %8.3f : x %8.3f \n", i,
502 fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i));
503 int ind=0; // Nov 21,2006
504 for(Int_t iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
505 ind = iphi*fCentersOfCellsEtaDir.GetSize() + i;
506 printf("%6.4f ", fEtaCentersOfCells[ind]);
507 if((iphi+1)%12 == 0) printf("\n");
512 printf(" Matrix transformation\n");
513 for(Int_t i=0; i<12; i++) {
514 TGeoMatrix *m = fMatrixOfSM[i];
516 const double *xyz = m->GetTranslation();
517 printf(" %2.2i %s %s x %7.2f y %7.2f z %7.2f\n",
518 i, m->GetName(), m->ClassName(), xyz[0],xyz[1],xyz[2]);
521 printf("\n Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize());
522 for(Int_t i=0; i<fCentersOfCellsPhiDir.GetSize(); i++) {
523 double phi=fPhiCentersOfCells.At(i);
524 printf(" ind %2.2i : y %8.3f : phi %7.5f(%6.2f) \n", i, fCentersOfCellsPhiDir.At(i),
525 phi, phi*TMath::RadToDeg());
532 void AliEMCALGeometry::PrintCellIndexes(Int_t absId, int pri, char *tit)
535 Int_t nSupMod, nModule, nIphi, nIeta;
539 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
540 printf(" %s | absId : %i -> nSupMod %i nModule %i nIphi %i nIeta %i \n", tit, absId, nSupMod, nModule, nIphi, nIeta);
542 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
543 printf(" local SM index : iphi %i : ieta %i \n", iphi,ieta);
544 GetGlobal(absId, vg);
545 printf(" vglob : mag %7.2f : perp %7.2f : z %7.2f : eta %6.4f : phi %6.4f(%6.2f) \n",
546 vg.Mag(), vg.Perp(), vg.Z(), vg.Eta(), vg.Phi(), vg.Phi()*TMath::RadToDeg());
550 //______________________________________________________________________
551 void AliEMCALGeometry::CheckAdditionalOptions()
554 // Additional options that
555 // can be used to select
556 // the specific geometry of
559 // adeed allILOSS= and allIHADR= for MIP investigation
560 fArrayOpts = new TObjArray;
561 Int_t nopt = AliEMCALHistoUtilities::ParseString(fGeoName, *fArrayOpts);
562 if(nopt==1) { // no aditional option(s)
563 fArrayOpts->Delete();
568 for(Int_t i=1; i<nopt; i++){
569 TObjString *o = (TObjString*)fArrayOpts->At(i);
571 TString addOpt = o->String();
573 for(Int_t j=0; j<fNAdditionalOpts; j++) {
574 TString opt = fAdditionalOpts[j];
575 if(addOpt.Contains(opt,TString::kIgnoreCase)) {
581 AliDebug(2,Form("<E> option |%s| unavailable : ** look to the file AliEMCALGeometry.h **\n",
585 AliDebug(2,Form("<I> option |%s| is valid : number %i : |%s|\n",
586 addOpt.Data(), indj, fAdditionalOpts[indj]));
587 if (addOpt.Contains("NL=",TString::kIgnoreCase)) {// number of sampling layers
588 sscanf(addOpt.Data(),"NL=%i", &fNECLayers);
589 AliDebug(2,Form(" fNECLayers %i (new) \n", fNECLayers));
590 } else if(addOpt.Contains("PBTH=",TString::kIgnoreCase)) {//Thickness of the Pb(fECPbRadThicknes)
591 sscanf(addOpt.Data(),"PBTH=%f", &fECPbRadThickness);
592 } else if(addOpt.Contains("SCTH=",TString::kIgnoreCase)) {//Thickness of the Sc(fECScintThick)
593 sscanf(addOpt.Data(),"SCTH=%f", &fECScintThick);
594 } else if(addOpt.Contains("LATSS=",TString::kIgnoreCase)) {// Thickness of lateral steel strip (fLateralSteelStrip)
595 sscanf(addOpt.Data(),"LATSS=%f", &fLateralSteelStrip);
596 AliDebug(2,Form(" fLateralSteelStrip %f (new) \n", fLateralSteelStrip));
597 } else if(addOpt.Contains("ILOSS=",TString::kIgnoreCase)) {// As in Geant
598 sscanf(addOpt.Data(),"ALLILOSS=%i", &fILOSS);
599 AliDebug(2,Form(" fILOSS %i \n", fILOSS));
600 } else if(addOpt.Contains("IHADR=",TString::kIgnoreCase)) {// As in Geant
601 sscanf(addOpt.Data(),"ALLIHADR=%i", &fIHADR);
602 AliDebug(2,Form(" fIHADR %i \n", fIHADR));
608 void AliEMCALGeometry::DefineSamplingFraction()
611 // Look http://rhic.physics.wayne.edu/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
612 // Keep for compatibilty
614 if(fNECLayers == 69) { // 10% layer reduction
616 } else if(fNECLayers == 61) { // 20% layer reduction
618 } else if(fNECLayers == 77) {
619 if (fECScintThick>0.175 && fECScintThick<0.177) { // 10% Pb thicknes reduction
620 fSampling = 10.5; // fECScintThick = 0.176, fECPbRadThickness=0.144;
621 } else if(fECScintThick>0.191 && fECScintThick<0.193) { // 20% Pb thicknes reduction
622 fSampling = 8.93; // fECScintThick = 0.192, fECPbRadThickness=0.128;
627 //____________________________________________________________________________
628 void AliEMCALGeometry::FillTRU(const TClonesArray * digits, TClonesArray * ampmatrix, TClonesArray * timeRmatrix) {
631 // Orders digits ampitudes list in fNTRU TRUs (384 cells) per supermodule.
632 // Each TRU is a TMatrixD, and they are kept in TClonesArrays. The number of
633 // TRU in phi is fNTRUPhi, and the number of TRU in eta is fNTRUEta.
634 // Last 2 modules are half size in Phi, I considered that the number of TRU
635 // is maintained for the last modules but decision not taken. If different,
636 // then this must be changed.
641 if(fNTRUEta*fNTRUPhi != fNTRU)
642 Error("FillTRU"," Wrong number of TRUS per Eta or Phi");
644 //Initilize and declare variables
645 //List of TRU matrices initialized to 0.
646 Int_t nCellsPhi = fNPhi*2/fNTRUPhi;
647 Int_t nCellsPhi2 = fNPhi/fNTRUPhi; //HalfSize modules
648 Int_t nCellsEta = fNZ*2/fNTRUEta;
659 //List of TRU matrices initialized to 0.
660 for(Int_t k = 0; k < fNTRU*fNumberOfSuperModules; k++){
661 TMatrixD * amptrus = new TMatrixD(nCellsPhi,nCellsEta) ;
662 TMatrixD * timeRtrus = new TMatrixD(nCellsPhi,nCellsEta) ;
663 for(Int_t i = 0; i < nCellsPhi; i++){
664 for(Int_t j = 0; j < nCellsEta; j++){
665 (*amptrus)(i,j) = 0.0;
666 (*timeRtrus)(i,j) = 0.0;
669 new((*ampmatrix)[k]) TMatrixD(*amptrus) ;
670 new((*timeRmatrix)[k]) TMatrixD(*timeRtrus) ;
673 AliEMCALDigit * dig ;
675 //Digits loop to fill TRU matrices with amplitudes.
676 for(Int_t idig = 0 ; idig < digits->GetEntriesFast() ; idig++){
678 dig = dynamic_cast<AliEMCALDigit *>(digits->At(idig)) ;
679 amp = dig->GetAmp() ; // Energy of the digit (arbitrary units)
680 id = dig->GetId() ; // Id label of the cell
681 timeR = dig->GetTimeR() ; // Earliest time of the digit
683 //Get eta and phi cell position in supermodule
684 Bool_t bCell = GetCellIndex(id, iSupMod, nModule, nIphi, nIeta) ;
686 Error("FillTRU","Wrong cell id number") ;
688 GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
690 //Check to which TRU in the supermodule belongs the cell.
691 //Supermodules are divided in a TRU matrix of dimension
692 //(fNTRUPhi,fNTRUEta).
693 //Each TRU is a cell matrix of dimension (nCellsPhi,nCellsEta)
695 //First calculate the row and column in the supermodule
696 //of the TRU to which the cell belongs.
697 Int_t col = ieta/nCellsEta;
698 Int_t row = iphi/nCellsPhi;
700 row = iphi/nCellsPhi2;
701 //Calculate label number of the TRU
702 Int_t itru = row + col*fNTRUPhi + iSupMod*fNTRU ;
704 //Fill TRU matrix with cell values
705 TMatrixD * amptrus = dynamic_cast<TMatrixD *>(ampmatrix->At(itru)) ;
706 TMatrixD * timeRtrus = dynamic_cast<TMatrixD *>(timeRmatrix->At(itru)) ;
708 //Calculate row and column of the cell inside the TRU with number itru
709 Int_t irow = iphi - row * nCellsPhi;
711 irow = iphi - row * nCellsPhi2;
712 Int_t icol = ieta - col * nCellsEta;
714 (*amptrus)(irow,icol) = amp ;
715 (*timeRtrus)(irow,icol) = timeR ;
720 //______________________________________________________________________
721 void AliEMCALGeometry::GetCellPhiEtaIndexInSModuleFromTRUIndex(const Int_t itru, const Int_t iphitru, const Int_t ietatru, Int_t &iphiSM, Int_t &ietaSM) const
724 // This method transforms the (eta,phi) index of cells in a
725 // TRU matrix into Super Module (eta,phi) index.
727 // Calculate in which row and column where the TRU are
730 Int_t col = itru/ fNTRUPhi ;
731 Int_t row = itru - col*fNTRUPhi ;
733 //Calculate the (eta,phi) index in SM
734 Int_t nCellsPhi = fNPhi*2/fNTRUPhi;
735 Int_t nCellsEta = fNZ*2/fNTRUEta;
737 iphiSM = nCellsPhi*row + iphitru ;
738 ietaSM = nCellsEta*col + ietatru ;
741 //______________________________________________________________________
742 AliEMCALGeometry * AliEMCALGeometry::GetInstance(){
743 // Returns the pointer of the unique instance
745 AliEMCALGeometry * rv = static_cast<AliEMCALGeometry *>( fgGeom );
749 //______________________________________________________________________
750 AliEMCALGeometry* AliEMCALGeometry::GetInstance(const Text_t* name,
751 const Text_t* title){
752 // Returns the pointer of the unique instance
754 AliEMCALGeometry * rv = 0;
756 if ( strcmp(name,"") == 0 ) { // get default geometry
757 fgGeom = new AliEMCALGeometry(fgDefaultGeometryName, title);
759 fgGeom = new AliEMCALGeometry(name, title);
760 } // end if strcmp(name,"")
761 if ( fgInit ) rv = (AliEMCALGeometry * ) fgGeom;
768 if ( strcmp(fgGeom->GetName(), name) != 0) {
769 printf("\ncurrent geometry is %s : ", fgGeom->GetName());
770 printf(" you cannot call %s ", name);
772 rv = (AliEMCALGeometry *) fgGeom;
778 Bool_t AliEMCALGeometry::IsInEMCAL(Double_t x, Double_t y, Double_t z) const {
779 // Checks whether point is inside the EMCal volume, used in AliEMCALv*.cxx
781 // Code uses cylindrical approximation made of inner radius (for speed)
783 // Points behind EMCAl, i.e. R > outer radius, but eta, phi in acceptance
784 // are considered to inside
786 Double_t r=sqrt(x*x+y*y);
788 if ( r > fEnvelop[0] ) {
790 theta = TMath::ATan2(r,z);
795 eta = -TMath::Log(TMath::Tan(theta/2.));
796 if (eta < fArm1EtaMin || eta > fArm1EtaMax)
799 Double_t phi = TMath::ATan2(y,x) * 180./TMath::Pi();
800 if (phi > fArm1PhiMin && phi < fArm1PhiMax)
808 // == Shish-kebab cases ==
810 Int_t AliEMCALGeometry::GetAbsCellId(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta) const
814 // 13-oct-05; 110 degree case
815 // May 31, 2006; ALICE numbering scheme:
816 // 0 <= nSupMod < fNumberOfSuperModules
817 // 0 <= nModule < fNPHI * fNZ ( fNPHI * fNZ/2 for fKey110DEG=1)
818 // 0 <= nIphi < fNPHIdiv
819 // 0 <= nIeta < fNETAdiv
820 // 0 <= absid < fNCells
821 static Int_t id=0; // have to change from 0 to fNCells-1
822 if(fKey110DEG == 1 && nSupMod >= 10) { // 110 degree case; last two supermodules
823 id = fNCellsInSupMod*10 + (fNCellsInSupMod/2)*(nSupMod-10);
825 id = fNCellsInSupMod*nSupMod;
827 id += fNCellsInModule *nModule;
828 id += fNPHIdiv *nIphi;
830 if(id<0 || id >= fNCells) {
831 // printf(" wrong numerations !!\n");
832 // printf(" id %6i(will be force to -1)\n", id);
833 // printf(" fNCells %6i\n", fNCells);
834 // printf(" nSupMod %6i\n", nSupMod);
835 // printf(" nModule %6i\n", nModule);
836 // printf(" nIphi %6i\n", nIphi);
837 // printf(" nIeta %6i\n", nIeta);
838 id = -TMath::Abs(id); // if negative something wrong
843 Bool_t AliEMCALGeometry::CheckAbsCellId(Int_t absId) const
845 // May 31, 2006; only trd1 now
846 if(absId<0 || absId >= fNCells) return kFALSE;
850 Bool_t AliEMCALGeometry::GetCellIndex(Int_t absId,Int_t &nSupMod,Int_t &nModule,Int_t &nIphi,Int_t &nIeta) const
852 // 21-sep-04; 19-oct-05;
853 // May 31, 2006; ALICE numbering scheme:
856 // absId - cell is as in Geant, 0<= absId < fNCells;
858 // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
859 // nModule - module number in SM, 0<= nModule < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
860 // nIphi - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv;
861 // nIeta - cell number in eta driection inside module; 0<= nIeta < fNETAdiv;
863 static Int_t tmp=0, sm10=0;
864 if(!CheckAbsCellId(absId)) return kFALSE;
866 sm10 = fNCellsInSupMod*10;
867 if(fKey110DEG == 1 && absId >= sm10) { // 110 degree case; last two supermodules
868 nSupMod = (absId-sm10) / (fNCellsInSupMod/2) + 10;
869 tmp = (absId-sm10) % (fNCellsInSupMod/2);
871 nSupMod = absId / fNCellsInSupMod;
872 tmp = absId % fNCellsInSupMod;
875 nModule = tmp / fNCellsInModule;
876 tmp = tmp % fNCellsInModule;
877 nIphi = tmp / fNPHIdiv;
878 nIeta = tmp % fNPHIdiv;
883 void AliEMCALGeometry::GetModulePhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, int &iphim, int &ietam) const
885 // added nSupMod; - 19-oct-05 !
886 // Alice numbering scheme - Jun 01,2006
887 // ietam, iphi - indexes of module in two dimensional grid of SM
888 // ietam - have to change from 0 to fNZ-1
889 // iphim - have to change from 0 to nphi-1 (fNPhi-1 or fNPhi/2-1)
892 if(fKey110DEG == 1 && nSupMod>=10) nphi = fNPhi/2;
895 ietam = nModule/nphi;
896 iphim = nModule%nphi;
899 void AliEMCALGeometry::GetCellPhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta,
900 int &iphi, int &ieta) const
903 // Added nSupMod; Nov 25, 05
904 // Alice numbering scheme - Jun 01,2006
906 // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
907 // nModule - module number in SM, 0<= nModule < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
908 // nIphi - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv;
909 // nIeta - cell number in eta driection inside module; 0<= nIeta < fNETAdiv;
912 // ieta, iphi - indexes of cell(tower) in two dimensional grid of SM
913 // ieta - have to change from 0 to (fNZ*fNETAdiv-1)
914 // iphi - have to change from 0 to (fNPhi*fNPHIdiv-1 or fNPhi*fNPHIdiv/2-1)
916 static Int_t iphim, ietam;
918 GetModulePhiEtaIndexInSModule(nSupMod,nModule, iphim, ietam);
919 // ieta = ietam*fNETAdiv + (1-nIeta); // x(module) = -z(SM)
920 ieta = ietam*fNETAdiv + (fNETAdiv - 1 - nIeta); // x(module) = -z(SM)
921 iphi = iphim*fNPHIdiv + nIphi; // y(module) = y(SM)
924 AliDebug(1,Form(" nSupMod %i nModule %i nIphi %i nIeta %i => ieta %i iphi %i\n",
925 nSupMod, nModule, nIphi, nIeta, ieta, iphi));
928 Int_t AliEMCALGeometry::GetSuperModuleNumber(Int_t absId) const
930 // Return the number of the supermodule given the absolute
931 // ALICE numbering id
933 static Int_t nSupMod, nModule, nIphi, nIeta;
934 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
938 void AliEMCALGeometry::GetModuleIndexesFromCellIndexesInSModule(Int_t nSupMod, Int_t iphi, Int_t ieta,
939 Int_t &iphim, Int_t &ietam, Int_t &nModule) const
941 // Transition from cell indexes (ieta,iphi) to module indexes (ietam,iphim, nModule)
943 nphi = GetNumberOfModuleInPhiDirection(nSupMod);
945 ietam = ieta/fNETAdiv;
946 iphim = iphi/fNPHIdiv;
947 nModule = ietam * nphi + iphim;
950 Int_t AliEMCALGeometry::GetAbsCellIdFromCellIndexes(Int_t nSupMod, Int_t iphi, Int_t ieta) const
952 // Transition from super module number(nSupMod) and cell indexes (ieta,iphi) to absId
953 static Int_t ietam, iphim, nModule;
954 static Int_t nIeta, nIphi; // cell indexes in module
956 GetModuleIndexesFromCellIndexesInSModule(nSupMod, iphi, ieta, ietam, iphim, nModule);
958 nIeta = ieta%fNETAdiv;
959 nIeta = fNETAdiv - 1 - nIeta;
960 nIphi = iphi%fNPHIdiv;
962 return GetAbsCellId(nSupMod, nModule, nIphi, nIeta);
966 // Methods for AliEMCALRecPoint - Feb 19, 2006
967 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t &xr, Double_t &yr, Double_t &zr) const
969 // Look to see what the relative
970 // position inside a given cell is
972 // Alice numbering scheme - Jun 08, 2006
974 // absId - cell is as in Geant, 0<= absId < fNCells;
976 // xr,yr,zr - x,y,z coordinates of cell with absId inside SM
978 // Shift index taking into account the difference between standard SM
979 // and SM of half size in phi direction
980 const Int_t phiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
981 static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
982 if(!CheckAbsCellId(absId)) return kFALSE;
984 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
985 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta);
987 xr = fCentersOfCellsXDir.At(ieta);
988 zr = fCentersOfCellsEtaDir.At(ieta);
991 yr = fCentersOfCellsPhiDir.At(iphi);
993 yr = fCentersOfCellsPhiDir.At(iphi + phiIndexShift);
995 AliDebug(1,Form("absId %i nSupMod %i iphi %i ieta %i xr %f yr %f zr %f ",absId,nSupMod,iphi,ieta,xr,yr,zr));
1000 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t loc[3]) const
1002 // Alice numbering scheme - Jun 03, 2006
1003 loc[0] = loc[1] = loc[2]=0.0;
1004 if(RelPosCellInSModule(absId, loc[0],loc[1],loc[2])) {
1010 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, TVector3 &vloc) const
1012 static Double_t loc[3];
1013 if(RelPosCellInSModule(absId,loc)) {
1014 vloc.SetXYZ(loc[0], loc[1], loc[2]);
1020 // Alice numbering scheme - Jun 03, 2006
1023 void AliEMCALGeometry::CreateListOfTrd1Modules()
1025 // Generate the list of Trd1 modules
1026 // which will make up the EMCAL
1029 AliDebug(2,Form(" AliEMCALGeometry::CreateListOfTrd1Modules() started "));
1031 AliEMCALShishKebabTrd1Module *mod=0, *mTmp=0; // current module
1032 if(fShishKebabTrd1Modules == 0) {
1033 fShishKebabTrd1Modules = new TList;
1034 fShishKebabTrd1Modules->SetName("ListOfTRD1");
1035 for(int iz=0; iz< GetNZ(); iz++) {
1037 mod = new AliEMCALShishKebabTrd1Module(TMath::Pi()/2.,this);
1039 mTmp = new AliEMCALShishKebabTrd1Module(*mod);
1042 fShishKebabTrd1Modules->Add(mod);
1045 AliDebug(2,Form(" Already exits : "));
1047 mod = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(fShishKebabTrd1Modules->GetSize()-1);
1048 fEtaMaxOfTRD1 = mod->GetMaxEtaOfModule(0);
1050 AliDebug(2,Form(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n",
1051 fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1));
1053 // Jun 01, 2006 - ALICE numbering scheme
1054 // define grid for cells in eta(z) and x directions in local coordinates system of SM
1055 // Works just for 2x2 case only -- ?? start here
1058 // Define grid for cells in phi(y) direction in local coordinates system of SM
1059 // as for 2X2 as for 3X3 - Nov 8,2006
1061 AliDebug(2,Form(" Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize()));
1062 Int_t ind=0; // this is phi index
1063 Int_t iphi=0, ieta=0, nModule=0, iphiTemp;
1064 Double_t xr, zr, theta, phi, eta, r, x,y;
1066 Double_t ytCenterModule, ytCenterCell;
1068 fCentersOfCellsPhiDir.Set(fNPhi*fNPHIdiv);
1069 fPhiCentersOfCells.Set(fNPhi*fNPHIdiv);
1071 Double_t R0 = GetIPDistance() + GetLongModuleSize()/2.;
1072 for(Int_t it=0; it<fNPhi; it++) { // cycle on modules
1073 ytCenterModule = -fParSM[1] + fPhiModuleSize*(2*it+1)/2; // center of module
1074 for(Int_t ic=0; ic<fNPHIdiv; ic++) { // cycle on cells in module
1076 ytCenterCell = ytCenterModule + fPhiTileSize *(2*ic-1)/2.;
1077 } else if(fNPHIdiv==3){
1078 ytCenterCell = ytCenterModule + fPhiTileSize *(ic-1);
1079 } else if(fNPHIdiv==1){
1080 ytCenterCell = ytCenterModule;
1082 fCentersOfCellsPhiDir.AddAt(ytCenterCell,ind);
1083 // Define grid on phi direction
1084 // Grid is not the same for different eta bin;
1085 // Effect is small but is still here
1086 phi = TMath::ATan2(ytCenterCell, R0);
1087 fPhiCentersOfCells.AddAt(phi, ind);
1089 AliDebug(2,Form(" ind %2.2i : y %8.3f ", ind, fCentersOfCellsPhiDir.At(ind)));
1094 fCentersOfCellsEtaDir.Set(fNZ *fNETAdiv);
1095 fCentersOfCellsXDir.Set(fNZ *fNETAdiv);
1096 fEtaCentersOfCells.Set(fNZ *fNETAdiv * fNPhi*fNPHIdiv);
1097 AliDebug(2,Form(" Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize()));
1098 for(Int_t it=0; it<fNZ; it++) {
1099 AliEMCALShishKebabTrd1Module *trd1 = GetShishKebabModule(it);
1101 for(Int_t ic=0; ic<fNETAdiv; ic++) {
1103 trd1->GetCenterOfCellInLocalCoordinateofSM(ic, xr, zr); // case of 2X2
1104 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1106 trd1->GetCenterOfCellInLocalCoordinateofSM_3X3(ic, xr, zr); // case of 3X3
1107 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1109 trd1->GetCenterOfCellInLocalCoordinateofSM_1X1(xr, zr); // case of 1X1
1110 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1112 fCentersOfCellsXDir.AddAt(float(xr) - fParSM[0],ieta);
1113 fCentersOfCellsEtaDir.AddAt(float(zr) - fParSM[2],ieta);
1114 // Define grid on eta direction for each bin in phi
1115 for(int iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
1116 x = xr + trd1->GetRadius();
1117 y = fCentersOfCellsPhiDir[iphi];
1118 r = TMath::Sqrt(x*x + y*y + zr*zr);
1119 theta = TMath::ACos(zr/r);
1120 eta = AliEMCALShishKebabTrd1Module::ThetaToEta(theta);
1121 // ind = ieta*fCentersOfCellsPhiDir.GetSize() + iphi;
1122 ind = iphi*fCentersOfCellsEtaDir.GetSize() + ieta;
1123 fEtaCentersOfCells.AddAt(eta, ind);
1125 //printf(" ieta %i : xr + trd1->GetRadius() %f : zr %f : eta %f \n", ieta, xr + trd1->GetRadius(), zr, eta);
1128 for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1129 AliDebug(2,Form(" ind %2.2i : z %8.3f : x %8.3f", i+1,
1130 fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i)));
1135 void AliEMCALGeometry::GetTransformationForSM()
1137 //Uses the geometry manager to
1138 //load the transformation matrix
1139 //for the supermodules
1140 // Unused after 19 Jan, 2007 - keep for compatibility;
1143 static Bool_t transInit=kFALSE;
1144 if(transInit) return;
1147 if(gGeoManager == 0) {
1148 Info("CreateTransformationForSM() "," Load geometry : TGeoManager::Import()");
1151 TGeoNode *tn = gGeoManager->GetTopNode();
1152 TGeoNode *node=0, *xen1 = 0;
1153 for(i=0; i<tn->GetNdaughters(); i++) {
1154 node = tn->GetDaughter(i);
1155 TString ns(node->GetName());
1156 if(ns.Contains(GetNameOfEMCALEnvelope())) {
1162 Info("CreateTransformationForSM() "," geometry has not EMCAL envelope with name %s",
1163 GetNameOfEMCALEnvelope());
1166 printf(" i %i : EMCAL Envelope is %s : #SM %i \n", i, xen1->GetName(), xen1->GetNdaughters());
1167 for(i=0; i<xen1->GetNdaughters(); i++) {
1168 TGeoNodeMatrix *sm = (TGeoNodeMatrix*)xen1->GetDaughter(i);
1169 fMatrixOfSM[i] = sm->GetMatrix();
1170 //Compiler doesn't like this syntax...
1171 // printf(" %i : matrix %x \n", i, fMatrixOfSM[i]);
1176 void AliEMCALGeometry::GetGlobal(const Double_t *loc, Double_t *glob, int ind) const
1178 // Figure out the global numbering
1179 // of a given supermodule from the
1181 // Alice numbering - Jun 03,2006
1182 // if(fMatrixOfSM[0] == 0) GetTransformationForSM();
1184 if(ind>=0 && ind < GetNumberOfSuperModules()) {
1185 fMatrixOfSM[ind]->LocalToMaster(loc, glob);
1189 void AliEMCALGeometry::GetGlobal(const TVector3 &vloc, TVector3 &vglob, int ind) const
1191 //Figure out the global numbering
1192 //of a given supermodule from the
1193 //local numbering given a 3-vector location
1195 static Double_t tglob[3], tloc[3];
1197 GetGlobal(tloc, tglob, ind);
1198 vglob.SetXYZ(tglob[0], tglob[1], tglob[2]);
1201 void AliEMCALGeometry::GetGlobal(Int_t absId , double glob[3]) const
1203 // Alice numbering scheme - Jun 03, 2006
1204 static Int_t nSupMod, nModule, nIphi, nIeta;
1205 static double loc[3];
1207 glob[0]=glob[1]=glob[2]=0.0; // bad case
1208 if(RelPosCellInSModule(absId, loc)) {
1209 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
1210 fMatrixOfSM[nSupMod]->LocalToMaster(loc, glob);
1214 void AliEMCALGeometry::GetGlobal(Int_t absId , TVector3 &vglob) const
1216 // Alice numbering scheme - Jun 03, 2006
1217 static Double_t glob[3];
1219 GetGlobal(absId, glob);
1220 vglob.SetXYZ(glob[0], glob[1], glob[2]);
1224 void AliEMCALGeometry::GetGlobal(const AliRecPoint *rp, TVector3 &vglob) const
1226 // Figure out the global numbering
1227 // of a given supermodule from the
1228 // local numbering for RecPoints
1230 static TVector3 vloc;
1231 static Int_t nSupMod, nModule, nIphi, nIeta;
1233 AliRecPoint *rpTmp = (AliRecPoint*)rp; // const_cast ??
1235 AliEMCALRecPoint *rpEmc = (AliEMCALRecPoint*)rpTmp;
1237 GetCellIndex(rpEmc->GetAbsId(0), nSupMod, nModule, nIphi, nIeta);
1238 rpTmp->GetLocalPosition(vloc);
1239 GetGlobal(vloc, vglob, nSupMod);
1242 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Double_t &eta,Double_t &phi) const
1244 // Nov 16, 2006- float to double
1245 // version for TRD1 only
1246 static TVector3 vglob;
1247 GetGlobal(absId, vglob);
1252 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Float_t &eta,Float_t &phi) const
1254 // Nov 16,2006 - should be discard in future
1255 static TVector3 vglob;
1256 GetGlobal(absId, vglob);
1257 eta = float(vglob.Eta());
1258 phi = float(vglob.Phi());
1261 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSM(Int_t nSupMod, Double_t &phiMin, Double_t &phiMax) const
1263 // 0<= nSupMod <=11; phi in rad
1265 if(nSupMod<0 || nSupMod >11) return kFALSE;
1267 phiMin = fPhiBoundariesOfSM[2*i];
1268 phiMax = fPhiBoundariesOfSM[2*i+1];
1272 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSMGap(Int_t nPhiSec, Double_t &phiMin, Double_t &phiMax) const
1274 // 0<= nPhiSec <=4; phi in rad
1275 // 0; gap boundaries between 0th&2th | 1th&3th SM
1276 // 1; gap boundaries between 2th&4th | 3th&5th SM
1277 // 2; gap boundaries between 4th&6th | 5th&7th SM
1278 // 3; gap boundaries between 6th&8th | 7th&9th SM
1279 // 4; gap boundaries between 8th&10th | 9th&11th SM
1280 if(nPhiSec<0 || nPhiSec >4) return kFALSE;
1281 phiMin = fPhiBoundariesOfSM[2*nPhiSec+1];
1282 phiMax = fPhiBoundariesOfSM[2*nPhiSec+2];
1286 Bool_t AliEMCALGeometry::SuperModuleNumberFromEtaPhi(Double_t eta, Double_t phi, Int_t &nSupMod) const
1288 // Return false if phi belongs a phi cracks between SM
1292 if(TMath::Abs(eta) > fEtaMaxOfTRD1) return kFALSE;
1294 phi = TVector2::Phi_0_2pi(phi); // move phi to (0,2pi) boundaries
1295 for(i=0; i<6; i++) {
1296 if(phi>=fPhiBoundariesOfSM[2*i] && phi<=fPhiBoundariesOfSM[2*i+1]) {
1298 if(eta < 0.0) nSupMod++;
1299 AliDebug(1,Form("eta %f phi %f(%5.2f) : nSupMod %i : #bound %i", eta,phi,phi*TMath::RadToDeg(), nSupMod,i));
1306 Bool_t AliEMCALGeometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi, Int_t &absId) const
1309 // stay here - phi problem as usual
1310 static Int_t nSupMod, i, ieta, iphi, etaShift, nphi;
1311 static Double_t absEta=0.0, d=0.0, dmin=0.0, phiLoc;
1312 absId = nSupMod = - 1;
1313 if(SuperModuleNumberFromEtaPhi(eta, phi, nSupMod)) {
1315 phi = TVector2::Phi_0_2pi(phi);
1316 phiLoc = phi - fPhiCentersOfSM[nSupMod/2];
1317 nphi = fPhiCentersOfCells.GetSize();
1319 phiLoc = phi - 190.*TMath::DegToRad();
1323 dmin = TMath::Abs(fPhiCentersOfCells[0]-phiLoc);
1325 for(i=1; i<nphi; i++) {
1326 d = TMath::Abs(fPhiCentersOfCells[i] - phiLoc);
1331 // printf(" i %i : d %f : dmin %f : fPhiCentersOfCells[i] %f \n", i, d, dmin, fPhiCentersOfCells[i]);
1333 // odd SM are turned with respect of even SM - reverse indexes
1334 AliDebug(2,Form(" iphi %i : dmin %f (phi %f, phiLoc %f ) ", iphi, dmin, phi, phiLoc));
1336 absEta = TMath::Abs(eta);
1337 etaShift = iphi*fCentersOfCellsEtaDir.GetSize();
1338 dmin = TMath::Abs(fEtaCentersOfCells[etaShift]-absEta);
1340 for(i=1; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1341 d = TMath::Abs(fEtaCentersOfCells[i+etaShift] - absEta);
1347 AliDebug(2,Form(" ieta %i : dmin %f (eta=%f) : nSupMod %i ", ieta, dmin, eta, nSupMod));
1349 if(eta<0) iphi = (nphi-1) - iphi;
1350 absId = GetAbsCellIdFromCellIndexes(nSupMod, iphi, ieta);
1357 AliEMCALShishKebabTrd1Module* AliEMCALGeometry::GetShishKebabModule(Int_t neta)
1359 //This method was too long to be
1360 //included in the header file - the
1361 //rule checker complained about it's
1362 //length, so we move it here. It returns the
1363 //shishkebabmodule at a given eta index point.
1365 static AliEMCALShishKebabTrd1Module* trd1=0;
1366 if(fShishKebabTrd1Modules && neta>=0 && neta<fShishKebabTrd1Modules->GetSize()) {
1367 trd1 = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(neta);
1372 void AliEMCALGeometry::Browse(TBrowser* b)
1374 if(fShishKebabTrd1Modules) b->Add(fShishKebabTrd1Modules);
1375 for(int i=0; i<fNumberOfSuperModules; i++) {
1376 if(fMatrixOfSM[i]) b->Add(fMatrixOfSM[i]);
1380 Bool_t AliEMCALGeometry::IsFolder() const
1382 if(fShishKebabTrd1Modules) return kTRUE;