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>
48 #include <TObjArray.h>
49 #include <TObjString.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;
67 Char_t* AliEMCALGeometry::fgDefaultGeometryName = "SHISH_77_TRD1_2X2_FINAL_110DEG";
70 // You can create the AliEMCALGeometry object independently from anything.
71 // You have to use just the correct name of geometry. If name is empty string the
72 // default name of geometry will be used.
74 // AliEMCALGeometry* g = AliEMCALGeometry::GetInstance(name,title); // first time
76 // g = AliEMCALGeometry::GetInstance(); // after first time
79 AliEMCALGeometry::AliEMCALGeometry()
81 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
82 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
83 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
84 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
85 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
86 fNCells(0),fNCellsInSupMod(0),fNCellsInModule(0),fNTRU(0),fNTRUEta(0),fNTRUPhi(0),fTrd1Angle(0.),f2Trd1Dx2(0.),
87 fPhiGapForSM(0.),fKey110DEG(0),fPhiBoundariesOfSM(0), fPhiCentersOfSM(0),fEtaMaxOfTRD1(0),
88 fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fCentersOfCellsEtaDir(0),
89 fCentersOfCellsXDir(0),fCentersOfCellsPhiDir(0),fEtaCentersOfCells(0),fPhiCentersOfCells(0),
90 fShishKebabTrd1Modules(0), fNAdditionalOpts(0),
91 fILOSS(-1), fIHADR(-1)
93 // default ctor only for internal usage (singleton)
94 // must be kept public for root persistency purposes, but should never be called by the outside world
95 // CreateListOfTrd1Modules();
96 AliDebug(2, "AliEMCALGeometry : default ctor ");
98 //______________________________________________________________________
99 AliEMCALGeometry::AliEMCALGeometry(const Text_t* name, const Text_t* title)
100 : AliGeometry(name, title),
101 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
102 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
103 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
104 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
105 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
106 fNCells(0),fNCellsInSupMod(0),fNCellsInModule(0),fNTRU(0),fNTRUEta(0),fNTRUPhi(0),fTrd1Angle(0.),f2Trd1Dx2(0.),
107 fPhiGapForSM(0.),fKey110DEG(0),fPhiBoundariesOfSM(0), fPhiCentersOfSM(0), fEtaMaxOfTRD1(0),
108 fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fCentersOfCellsEtaDir(0),
109 fCentersOfCellsXDir(0),fCentersOfCellsPhiDir(0),fEtaCentersOfCells(0),fPhiCentersOfCells(0),
110 fShishKebabTrd1Modules(0),fNAdditionalOpts(0),
111 fILOSS(-1), fIHADR(-1)
113 // ctor only for internal usage (singleton)
114 AliDebug(2, Form("AliEMCALGeometry(%s,%s) ", name,title));
118 CreateListOfTrd1Modules();
120 if (AliDebugLevel()>=2) {
125 //______________________________________________________________________
126 AliEMCALGeometry::AliEMCALGeometry(const AliEMCALGeometry& geom)
128 fGeoName(geom.fGeoName),
129 fArrayOpts(geom.fArrayOpts),
130 fAlFrontThick(geom.fAlFrontThick),
131 fECPbRadThickness(geom.fECPbRadThickness),
132 fECScintThick(geom.fECScintThick),
133 fNECLayers(geom.fNECLayers),
134 fArm1PhiMin(geom.fArm1PhiMin),
135 fArm1PhiMax(geom.fArm1PhiMax),
136 fArm1EtaMin(geom.fArm1EtaMin),
137 fArm1EtaMax(geom.fArm1EtaMax),
138 fIPDistance(geom.fIPDistance),
139 fShellThickness(geom.fShellThickness),
140 fZLength(geom.fZLength),
141 fGap2Active(geom.fGap2Active),
144 fSampling(geom.fSampling),
145 fNumberOfSuperModules(geom.fNumberOfSuperModules),
146 fSteelFrontThick(geom.fSteelFrontThick),
147 fFrontSteelStrip(geom.fFrontSteelStrip),
148 fLateralSteelStrip(geom.fLateralSteelStrip),
149 fPassiveScintThick(geom.fPassiveScintThick),
150 fPhiModuleSize(geom.fPhiModuleSize),
151 fEtaModuleSize(geom.fEtaModuleSize),
152 fPhiTileSize(geom.fPhiTileSize),
153 fEtaTileSize(geom.fEtaTileSize),
154 fLongModuleSize(geom.fLongModuleSize),
155 fNPhiSuperModule(geom.fNPhiSuperModule),
156 fNPHIdiv(geom.fNPHIdiv),
157 fNETAdiv(geom.fNETAdiv),
158 fNCells(geom.fNCells),
159 fNCellsInSupMod(geom.fNCellsInSupMod),
160 fNCellsInModule(geom.fNCellsInModule),
162 fNTRUEta(geom.fNTRUEta),
163 fNTRUPhi(geom.fNTRUPhi),
164 fTrd1Angle(geom.fTrd1Angle),
165 f2Trd1Dx2(geom.f2Trd1Dx2),
166 fPhiGapForSM(geom.fPhiGapForSM),
167 fKey110DEG(geom.fKey110DEG),
168 fPhiBoundariesOfSM(geom.fPhiBoundariesOfSM),
169 fPhiCentersOfSM(geom.fPhiCentersOfSM),
170 fEtaMaxOfTRD1(geom.fEtaMaxOfTRD1),
171 fTrd2AngleY(geom.fTrd2AngleY),
172 f2Trd2Dy2(geom.f2Trd2Dy2),
173 fEmptySpace(geom.fEmptySpace),
175 fTubsTurnAngle(geom.fTubsTurnAngle),
176 fCentersOfCellsEtaDir(geom.fCentersOfCellsEtaDir),
177 fCentersOfCellsXDir(geom.fCentersOfCellsXDir),
178 fCentersOfCellsPhiDir(geom.fCentersOfCellsPhiDir),
179 fEtaCentersOfCells(geom.fEtaCentersOfCells),
180 fPhiCentersOfCells(geom.fPhiCentersOfCells),
181 fShishKebabTrd1Modules(geom.fShishKebabTrd1Modules),
182 fNAdditionalOpts(geom.fNAdditionalOpts),
183 fILOSS(geom.fILOSS), fIHADR(geom.fIHADR)
188 //______________________________________________________________________
189 AliEMCALGeometry::~AliEMCALGeometry(void){
192 //______________________________________________________________________
193 void AliEMCALGeometry::Init(void){
194 // Initializes the EMCAL parameters
195 // naming convention : GUV_WX_N_ gives the composition of a tower
196 // WX inform about the composition of the EM calorimeter section:
197 // thickness in mm of Pb radiator (W) and of scintillator (X), and number of scintillator layers (N)
198 // New geometry: EMCAL_55_25
199 // 24-aug-04 for shish-kebab
200 // SHISH_25 or SHISH_62
201 // 11-oct-05 - correction for pre final design
202 // Feb 06,2006 - decrease the weight of EMCAL
204 // Oct 30,2006 - SHISH_TRD1_CURRENT_1X1, SHISH_TRD1_CURRENT_2X2 or SHISH_TRD1_CURRENT_3X3;
207 fAdditionalOpts[0] = "nl="; // number of sampling layers (fNECLayers)
208 fAdditionalOpts[1] = "pbTh="; // cm, Thickness of the Pb (fECPbRadThick)
209 fAdditionalOpts[2] = "scTh="; // cm, Thickness of the Sc (fECScintThick)
210 fAdditionalOpts[3] = "latSS="; // cm, Thickness of lateral steel strip (fLateralSteelStrip)
211 fAdditionalOpts[4] = "allILOSS="; // = 0,1,2,3,4 (4 - energy loss without fluctuation)
212 fAdditionalOpts[5] = "allIHADR="; // = 0,1,2 (0 - no hadronic interaction)
214 fNAdditionalOpts = sizeof(fAdditionalOpts) / sizeof(char*);
216 fgInit = kFALSE; // Assume failed until proven otherwise.
217 fGeoName = GetName();
220 if(fGeoName.Contains("110DEG") || fGeoName.Contains("CURRENT")) fKey110DEG = 1; // for GetAbsCellId
221 fShishKebabTrd1Modules = 0;
222 fTrd2AngleY = f2Trd2Dy2 = fEmptySpace = fTubsR = fTubsTurnAngle = 0;
224 fNZ = 114; // granularity along Z (eta)
225 fNPhi = 168; // granularity in phi (azimuth)
226 fArm1PhiMin = 80.0; // degrees, Starting EMCAL Phi position
227 fArm1PhiMax = 190.0; // degrees, Ending EMCAL Phi position
228 fArm1EtaMin = -0.7; // pseudorapidity, Starting EMCAL Eta position
229 fArm1EtaMax = +0.7; // pseudorapidity, Ending EMCAL Eta position
230 fIPDistance = 454.0; // cm, Radial distance to inner surface of EMCAL
231 fPhiGapForSM = 0.; // cm, only for final TRD1 geometry
232 for(int i=0; i<12; i++) fMatrixOfSM[i] = 0;
235 if(fGeoName.Contains("SHISH")){ // Only shahslyk now
236 // 7-sep-05; integration issue
237 fArm1PhiMin = 80.0; // 60 -> 80
238 fArm1PhiMax = 180.0; // 180 -> 190
240 fNumberOfSuperModules = 10; // 12 = 6 * 2 (6 in phi, 2 in Z);
241 fSteelFrontThick = 2.54; // 9-sep-04
243 fFrontSteelStrip = fPassiveScintThick = 0.0; // 13-may-05
244 fLateralSteelStrip = 0.025; // before MAY 2005
245 fPhiModuleSize = fEtaModuleSize = 11.4;
246 fPhiTileSize = fEtaTileSize = 5.52; // (11.4-5.52*2)/2. = 0.18 cm (wall thickness)
249 fAlFrontThick = fGap2Active = 0;
250 fNPHIdiv = fNETAdiv = 2;
253 fECScintThick = fECPbRadThickness = 0.2;
254 fSampling = 1.; // 30-aug-04 - should be calculated
255 if(fGeoName.Contains("TWIST")) { // all about EMCAL module
256 fNZ = 27; // 16-sep-04
257 } else if(fGeoName.Contains("TRD")) {
258 fIPDistance = 428.0; // 11-may-05
259 fSteelFrontThick = 0.0; // 3.17 -> 0.0; 28-mar-05 : no stell plate
262 fPhiModuleSize = fEtaModuleSize = 12.26;
263 fNZ = 26; // 11-oct-04
264 fTrd1Angle = 1.3; // in degree
265 // 18-nov-04; 1./0.08112=12.327
266 // http://pdsfweb01.nersc.gov/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
267 if(fGeoName.Contains("TRD1")) { // 30-jan-05
269 fPhiGapForSM = 2.; // cm, only for final TRD1 geometry
270 if(fGeoName.Contains("MAY05") || fGeoName.Contains("WSUC") || fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")){
271 fNumberOfSuperModules = 12; // 20-may-05
272 if(fGeoName.Contains("WSUC")) fNumberOfSuperModules = 1; // 27-may-05
273 fNECLayers = 77; // (13-may-05 from V.Petrov)
274 fPhiModuleSize = 12.5; // 20-may-05 - rectangular shape
275 fEtaModuleSize = 11.9;
276 fECScintThick = fECPbRadThickness = 0.16;// (13-may-05 from V.Petrov)
277 fFrontSteelStrip = 0.025;// 0.025cm = 0.25mm (13-may-05 from V.Petrov)
278 fLateralSteelStrip = 0.01; // 0.01cm = 0.1mm (13-may-05 from V.Petrov) - was 0.025
279 fPassiveScintThick = 0.8; // 0.8cm = 8mm (13-may-05 from V.Petrov)
281 fTrd1Angle = 1.5; // 1.3 or 1.5
283 if(fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")) { // 9-sep-05
284 fNumberOfSuperModules = 10;
286 fNumberOfSuperModules = 12;// last two modules have size 10 degree in phi (180<phi<190)
287 fArm1PhiMax = 200.0; // for XEN1 and turn angle of super modules
289 if(fGeoName.Contains("FINAL")) {
290 fPhiModuleSize = 12.26 - fPhiGapForSM / Float_t(fNPhi); // first assumption
291 } else if(fGeoName.Contains("CURRENT")) {
292 fECScintThick = 0.176; // 10% of weight reduction
293 fECPbRadThickness = 0.144; //
294 fLateralSteelStrip = 0.015; // 0.015cm = 0.15mm (Oct 30, from Fred)
295 fPhiModuleSize = 12.00;
296 fPhiGapForSM = (12.26 - fPhiModuleSize)*fNPhi; // have to check
298 fEtaModuleSize = fPhiModuleSize;
299 if(fGeoName.Contains("HUGE")) fNECLayers *= 3; // 28-oct-05 for analysing leakage
302 } else if(fGeoName.Contains("TRD2")) { // 30-jan-05
303 fSteelFrontThick = 0.0; // 11-mar-05
304 fIPDistance+= fSteelFrontThick; // 1-feb-05 - compensate absence of steel plate
305 fTrd1Angle = 1.64; // 1.3->1.64
306 fTrd2AngleY = fTrd1Angle; // symmetric case now
307 fEmptySpace = 0.2; // 2 mm
308 fTubsR = fIPDistance; // 31-jan-05 - as for Fred case
310 fPhiModuleSize = fTubsR*2.*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
311 fPhiModuleSize -= fEmptySpace/2.; // 11-mar-05
312 fEtaModuleSize = fPhiModuleSize; // 20-may-05
315 fNPHIdiv = fNETAdiv = 2; // 13-oct-04 - division again
316 if(fGeoName.Contains("3X3")) { // 23-nov-04
317 fNPHIdiv = fNETAdiv = 3;
318 } else if(fGeoName.Contains("4X4")) {
319 fNPHIdiv = fNETAdiv = 4;
320 } else if(fGeoName.Contains("1X1")) {
321 fNPHIdiv = fNETAdiv = 1;
324 if(fGeoName.Contains("25")){
326 fECScintThick = fECPbRadThickness = 0.5;
328 if(fGeoName.Contains("WSUC")){ // 18-may-05 - about common structure
329 fShellThickness = 30.; // should be change
333 CheckAdditionalOptions();
334 DefineSamplingFraction();
336 fPhiTileSize = fPhiModuleSize/double(fNPHIdiv) - fLateralSteelStrip; // 13-may-05
337 fEtaTileSize = fEtaModuleSize/double(fNETAdiv) - fLateralSteelStrip; // 13-may-05
339 // constant for transition absid <--> indexes
340 fNCellsInModule = fNPHIdiv*fNETAdiv;
341 fNCellsInSupMod = fNCellsInModule*fNPhi*fNZ;
342 fNCells = fNCellsInSupMod*fNumberOfSuperModules;
343 if(GetKey110DEG()) fNCells -= fNCellsInSupMod;
345 fLongModuleSize = fNECLayers*(fECScintThick + fECPbRadThickness);
346 if(fGeoName.Contains("MAY05")) fLongModuleSize += (fFrontSteelStrip + fPassiveScintThick);
349 if(fGeoName.Contains("TRD")) {
350 f2Trd1Dx2 = fEtaModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd1Angle*TMath::DegToRad()/2.);
351 if(fGeoName.Contains("TRD2")) { // 27-jan-05
352 f2Trd2Dy2 = fPhiModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
355 } else Fatal("Init", "%s is an undefined geometry!", fGeoName.Data()) ;
357 fNPhiSuperModule = fNumberOfSuperModules/2;
358 if(fNPhiSuperModule<1) fNPhiSuperModule = 1;
360 fShellThickness = fAlFrontThick + fGap2Active + fNECLayers*GetECScintThick()+(fNECLayers-1)*GetECPbRadThick();
361 if(fGeoName.Contains("SHISH")) {
362 fShellThickness = fSteelFrontThick + fLongModuleSize;
363 if(fGeoName.Contains("TWIST")) { // 13-sep-04
364 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + fPhiModuleSize*fEtaModuleSize);
365 fShellThickness += fSteelFrontThick;
366 } else if(fGeoName.Contains("TRD")) { // 1-oct-04
367 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + f2Trd1Dx2*f2Trd1Dx2);
368 fShellThickness += fSteelFrontThick;
370 fParSM[0] = GetShellThickness()/2.;
371 fParSM[1] = GetPhiModuleSize() * GetNPhi()/2.;
376 fZLength = 2.*ZFromEtaR(fIPDistance+fShellThickness,fArm1EtaMax); // Z coverage
377 fEnvelop[0] = fIPDistance; // mother volume inner radius
378 fEnvelop[1] = fIPDistance + fShellThickness; // mother volume outer r.
379 fEnvelop[2] = 1.00001*fZLength; // add some padding for mother volume.
381 fNumberOfSuperModules = 12;
383 // SM phi boundaries - (0,1),(2,3) .. (10,11) - has the same boundaries; Nov 7, 2006
384 fPhiBoundariesOfSM.Set(fNumberOfSuperModules);
385 fPhiCentersOfSM.Set(fNumberOfSuperModules/2);
386 fPhiBoundariesOfSM[0] = TMath::PiOver2() - TMath::ATan2(fParSM[1] , fIPDistance); // 1th and 2th modules)
387 fPhiBoundariesOfSM[1] = TMath::PiOver2() + TMath::ATan2(fParSM[1] , fIPDistance);
388 fPhiCentersOfSM[0] = TMath::PiOver2();
389 for(int i=1; i<=4; i++) { // from 2th ro 9th
390 fPhiBoundariesOfSM[2*i] = fPhiBoundariesOfSM[0] + 20.*TMath::DegToRad()*i;
391 fPhiBoundariesOfSM[2*i+1] = fPhiBoundariesOfSM[1] + 20.*TMath::DegToRad()*i;
392 fPhiCentersOfSM[i] = fPhiCentersOfSM[0] + 20.*TMath::DegToRad()*i;
394 fPhiBoundariesOfSM[11] = 190.*TMath::DegToRad();
395 fPhiBoundariesOfSM[10] = fPhiBoundariesOfSM[11] - TMath::ATan2((fParSM[1]) , fIPDistance);
396 fPhiCentersOfSM[5] = (fPhiBoundariesOfSM[10]+fPhiBoundariesOfSM[11])/2.;
398 //TRU parameters. These parameters values are not the final ones.
403 // Define TGeoMatrix of SM - Jan 19, 2007 (just fro TRD1)
404 if(fGeoName.Contains("TRD1")) { // copy code from AliEMCALv0::CreateSmod()
405 int nphism = GetNumberOfSuperModules()/2;
406 double dphi = (GetArm1PhiMax() - GetArm1PhiMin())/nphism;
407 double rpos = (GetEnvelop(0) + GetEnvelop(1))/2.;
408 double phi, phiRad, xpos, ypos, zpos;
409 for(int i=0; i<nphism; i++){
410 phi = GetArm1PhiMin() + dphi*(2*i+1)/2.; // phi= 90, 110, 130, 150, 170, 190
411 phiRad = phi*TMath::Pi()/180.;
412 xpos = rpos * TMath::Cos(phiRad);
413 ypos = rpos * TMath::Sin(phiRad);
416 xpos += (fParSM[1]/2. * TMath::Sin(phiRad));
417 ypos -= (fParSM[1]/2. * TMath::Cos(phiRad));
421 TGeoRotation *geoRot0 = new TGeoRotation("geoRot0", 90.0, phi, 90.0, 90.0+phi, 0.0, 0.0);
422 fMatrixOfSM[ind] = new TGeoCombiTrans(Form("EmcalSM%2.2i",ind),
423 xpos,ypos, zpos, geoRot0);
426 double phiy = 90. + phi + 180.;
427 if(phiy>=360.) phiy -= 360.;
428 TGeoRotation *geoRot1 = new TGeoRotation("geoRot1", 90.0, phi, 90.0, phiy, 180.0, 0.0);
429 fMatrixOfSM[ind] = new TGeoCombiTrans(Form("EmcalSM%2.2i",ind),
430 xpos,ypos,-zpos, geoRot1);
434 AliInfo(" is ended");
437 void AliEMCALGeometry::PrintGeometry()
439 // Separate routine is callable from broswer; Nov 7,2006
440 printf("\nInit: geometry of EMCAL named %s :\n", fGeoName.Data());
442 for(Int_t i=0; i<fArrayOpts->GetEntries(); i++){
443 TObjString *o = (TObjString*)fArrayOpts->At(i);
444 printf(" %i : %s \n", i, o->String().Data());
447 printf("Granularity: %d in eta and %d in phi\n", GetNZ(), GetNPhi()) ;
448 printf("Layout: phi = (%7.1f, %7.1f), eta = (%5.2f, %5.2f), IP = %7.2f -> for EMCAL envelope only\n",
449 GetArm1PhiMin(), GetArm1PhiMax(),GetArm1EtaMin(), GetArm1EtaMax(), GetIPDistance() );
451 printf( " ECAL : %d x (%f cm Pb, %f cm Sc) \n",
452 GetNECLayers(), GetECPbRadThick(), GetECScintThick() ) ;
453 printf(" fSampling %5.2f \n", fSampling );
454 if(fGeoName.Contains("SHISH")){
455 printf(" fIPDistance %6.3f cm \n", fIPDistance);
456 if(fSteelFrontThick>0.)
457 printf(" fSteelFrontThick %6.3f cm \n", fSteelFrontThick);
458 printf(" fNPhi %i | fNZ %i \n", fNPhi, fNZ);
459 printf(" fNCellsInModule %i : fNCellsInSupMod %i : fNCells %i\n",fNCellsInModule, fNCellsInSupMod, fNCells);
460 if(fGeoName.Contains("MAY05")){
461 printf(" fFrontSteelStrip %6.4f cm (thickness of front steel strip)\n",
463 printf(" fLateralSteelStrip %6.4f cm (thickness of lateral steel strip)\n",
465 printf(" fPassiveScintThick %6.4f cm (thickness of front passive Sc tile)\n",
468 printf(" X:Y module size %6.3f , %6.3f cm \n", fPhiModuleSize, fEtaModuleSize);
469 printf(" X:Y tile size %6.3f , %6.3f cm \n", fPhiTileSize, fEtaTileSize);
470 printf(" #of sampling layers %i(fNECLayers) \n", fNECLayers);
471 printf(" fLongModuleSize %6.3f cm \n", fLongModuleSize);
472 printf(" #supermodule in phi direction %i \n", fNPhiSuperModule );
474 printf(" fILOSS %i : fIHADR %i \n", fILOSS, fIHADR);
475 if(fGeoName.Contains("TRD")) {
476 printf(" fTrd1Angle %7.4f\n", fTrd1Angle);
477 printf(" f2Trd1Dx2 %7.4f\n", f2Trd1Dx2);
478 if(fGeoName.Contains("TRD2")) {
479 printf(" fTrd2AngleY %7.4f\n", fTrd2AngleY);
480 printf(" f2Trd2Dy2 %7.4f\n", f2Trd2Dy2);
481 printf(" fTubsR %7.2f cm\n", fTubsR);
482 printf(" fTubsTurnAngle %7.4f\n", fTubsTurnAngle);
483 printf(" fEmptySpace %7.4f cm\n", fEmptySpace);
484 } else if(fGeoName.Contains("TRD1")){
485 printf("SM dimensions(TRD1) : dx %7.2f dy %7.2f dz %7.2f (SMOD, BOX)\n",
486 fParSM[0],fParSM[1],fParSM[2]);
487 printf(" fPhiGapForSM %7.4f cm (%7.4f <- phi size in degree)\n",
488 fPhiGapForSM, TMath::ATan2(fPhiGapForSM,fIPDistance)*TMath::RadToDeg());
489 if(GetKey110DEG()) printf(" Last two modules have size 10 degree in phi (180<phi<190)\n");
490 printf(" phi SM boundaries \n");
491 for(int i=0; i<fPhiBoundariesOfSM.GetSize()/2.; i++) {
492 printf(" %i : %7.5f(%7.2f) -> %7.5f(%7.2f) : center %7.5f(%7.2f) \n", i,
493 fPhiBoundariesOfSM[2*i], fPhiBoundariesOfSM[2*i]*TMath::RadToDeg(),
494 fPhiBoundariesOfSM[2*i+1], fPhiBoundariesOfSM[2*i+1]*TMath::RadToDeg(),
495 fPhiCentersOfSM[i], fPhiCentersOfSM[i]*TMath::RadToDeg());
497 printf(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n",
498 fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1);
500 printf("\n Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize());
501 for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
502 printf(" ind %2.2i : z %8.3f : x %8.3f \n", i,
503 fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i));
504 int ind=0; // Nov 21,2006
505 for(Int_t iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
506 ind = iphi*fCentersOfCellsEtaDir.GetSize() + i;
507 printf("%6.4f ", fEtaCentersOfCells[ind]);
508 if((iphi+1)%12 == 0) printf("\n");
513 printf(" Matrix transformation\n");
514 for(Int_t i=0; i<12; i++) {
515 TGeoMatrix *m = fMatrixOfSM[i];
517 const double *xyz = m->GetTranslation();
518 printf(" %2.2i %s %s x %7.2f y %7.2f z %7.2f\n",
519 i, m->GetName(), m->ClassName(), xyz[0],xyz[1],xyz[2]);
522 printf("\n Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize());
523 for(Int_t i=0; i<fCentersOfCellsPhiDir.GetSize(); i++) {
524 double phi=fPhiCentersOfCells.At(i);
525 printf(" ind %2.2i : y %8.3f : phi %7.5f(%6.2f) \n", i, fCentersOfCellsPhiDir.At(i),
526 phi, phi*TMath::RadToDeg());
533 void AliEMCALGeometry::PrintCellIndexes(Int_t absId, int pri, char *tit)
536 Int_t nSupMod, nModule, nIphi, nIeta;
540 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
541 printf(" %s | absId : %i -> nSupMod %i nModule %i nIphi %i nIeta %i \n", tit, absId, nSupMod, nModule, nIphi, nIeta);
543 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
544 printf(" local SM index : iphi %i : ieta %i \n", iphi,ieta);
545 GetGlobal(absId, vg);
546 printf(" vglob : mag %7.2f : perp %7.2f : z %7.2f : eta %6.4f : phi %6.4f(%6.2f) \n",
547 vg.Mag(), vg.Perp(), vg.Z(), vg.Eta(), vg.Phi(), vg.Phi()*TMath::RadToDeg());
551 //______________________________________________________________________
552 void AliEMCALGeometry::CheckAdditionalOptions()
555 // Additional options that
556 // can be used to select
557 // the specific geometry of
560 // adeed allILOSS= and allIHADR= for MIP investigation
561 fArrayOpts = new TObjArray;
562 Int_t nopt = AliEMCALHistoUtilities::ParseString(fGeoName, *fArrayOpts);
563 if(nopt==1) { // no aditional option(s)
564 fArrayOpts->Delete();
569 for(Int_t i=1; i<nopt; i++){
570 TObjString *o = (TObjString*)fArrayOpts->At(i);
572 TString addOpt = o->String();
574 for(Int_t j=0; j<fNAdditionalOpts; j++) {
575 TString opt = fAdditionalOpts[j];
576 if(addOpt.Contains(opt,TString::kIgnoreCase)) {
582 AliDebug(2,Form("<E> option |%s| unavailable : ** look to the file AliEMCALGeometry.h **\n",
586 AliDebug(2,Form("<I> option |%s| is valid : number %i : |%s|\n",
587 addOpt.Data(), indj, fAdditionalOpts[indj]));
588 if (addOpt.Contains("NL=",TString::kIgnoreCase)) {// number of sampling layers
589 sscanf(addOpt.Data(),"NL=%i", &fNECLayers);
590 AliDebug(2,Form(" fNECLayers %i (new) \n", fNECLayers));
591 } else if(addOpt.Contains("PBTH=",TString::kIgnoreCase)) {//Thickness of the Pb(fECPbRadThicknes)
592 sscanf(addOpt.Data(),"PBTH=%f", &fECPbRadThickness);
593 } else if(addOpt.Contains("SCTH=",TString::kIgnoreCase)) {//Thickness of the Sc(fECScintThick)
594 sscanf(addOpt.Data(),"SCTH=%f", &fECScintThick);
595 } else if(addOpt.Contains("LATSS=",TString::kIgnoreCase)) {// Thickness of lateral steel strip (fLateralSteelStrip)
596 sscanf(addOpt.Data(),"LATSS=%f", &fLateralSteelStrip);
597 AliDebug(2,Form(" fLateralSteelStrip %f (new) \n", fLateralSteelStrip));
598 } else if(addOpt.Contains("ILOSS=",TString::kIgnoreCase)) {// As in Geant
599 sscanf(addOpt.Data(),"ALLILOSS=%i", &fILOSS);
600 AliDebug(2,Form(" fILOSS %i \n", fILOSS));
601 } else if(addOpt.Contains("IHADR=",TString::kIgnoreCase)) {// As in Geant
602 sscanf(addOpt.Data(),"ALLIHADR=%i", &fIHADR);
603 AliDebug(2,Form(" fIHADR %i \n", fIHADR));
609 void AliEMCALGeometry::DefineSamplingFraction()
612 // Look http://rhic.physics.wayne.edu/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
613 // Keep for compatibilty
615 if(fNECLayers == 69) { // 10% layer reduction
617 } else if(fNECLayers == 61) { // 20% layer reduction
619 } else if(fNECLayers == 77) {
620 if (fECScintThick>0.175 && fECScintThick<0.177) { // 10% Pb thicknes reduction
621 fSampling = 10.5; // fECScintThick = 0.176, fECPbRadThickness=0.144;
622 } else if(fECScintThick>0.191 && fECScintThick<0.193) { // 20% Pb thicknes reduction
623 fSampling = 8.93; // fECScintThick = 0.192, fECPbRadThickness=0.128;
628 //____________________________________________________________________________
629 void AliEMCALGeometry::FillTRU(const TClonesArray * digits, TClonesArray * ampmatrix, TClonesArray * timeRmatrix) {
632 // Orders digits ampitudes list in fNTRU TRUs (384 cells) per supermodule.
633 // Each TRU is a TMatrixD, and they are kept in TClonesArrays. The number of
634 // TRU in phi is fNTRUPhi, and the number of TRU in eta is fNTRUEta.
635 // Last 2 modules are half size in Phi, I considered that the number of TRU
636 // is maintained for the last modules but decision not taken. If different,
637 // then this must be changed.
642 if(fNTRUEta*fNTRUPhi != fNTRU)
643 Error("FillTRU"," Wrong number of TRUS per Eta or Phi");
645 //Initilize and declare variables
646 //List of TRU matrices initialized to 0.
647 Int_t nCellsPhi = fNPhi*2/fNTRUPhi;
648 Int_t nCellsPhi2 = fNPhi/fNTRUPhi; //HalfSize modules
649 Int_t nCellsEta = fNZ*2/fNTRUEta;
660 //List of TRU matrices initialized to 0.
661 for(Int_t k = 0; k < fNTRU*fNumberOfSuperModules; k++){
662 TMatrixD * amptrus = new TMatrixD(nCellsPhi,nCellsEta) ;
663 TMatrixD * timeRtrus = new TMatrixD(nCellsPhi,nCellsEta) ;
664 for(Int_t i = 0; i < nCellsPhi; i++){
665 for(Int_t j = 0; j < nCellsEta; j++){
666 (*amptrus)(i,j) = 0.0;
667 (*timeRtrus)(i,j) = 0.0;
670 new((*ampmatrix)[k]) TMatrixD(*amptrus) ;
671 new((*timeRmatrix)[k]) TMatrixD(*timeRtrus) ;
674 AliEMCALDigit * dig ;
676 //Digits loop to fill TRU matrices with amplitudes.
677 for(Int_t idig = 0 ; idig < digits->GetEntriesFast() ; idig++){
679 dig = dynamic_cast<AliEMCALDigit *>(digits->At(idig)) ;
680 amp = dig->GetAmp() ; // Energy of the digit (arbitrary units)
681 id = dig->GetId() ; // Id label of the cell
682 timeR = dig->GetTimeR() ; // Earliest time of the digit
684 //Get eta and phi cell position in supermodule
685 Bool_t bCell = GetCellIndex(id, iSupMod, nModule, nIphi, nIeta) ;
687 Error("FillTRU","Wrong cell id number") ;
689 GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
691 //Check to which TRU in the supermodule belongs the cell.
692 //Supermodules are divided in a TRU matrix of dimension
693 //(fNTRUPhi,fNTRUEta).
694 //Each TRU is a cell matrix of dimension (nCellsPhi,nCellsEta)
696 //First calculate the row and column in the supermodule
697 //of the TRU to which the cell belongs.
698 Int_t col = ieta/nCellsEta;
699 Int_t row = iphi/nCellsPhi;
701 row = iphi/nCellsPhi2;
702 //Calculate label number of the TRU
703 Int_t itru = row + col*fNTRUPhi + iSupMod*fNTRU ;
705 //Fill TRU matrix with cell values
706 TMatrixD * amptrus = dynamic_cast<TMatrixD *>(ampmatrix->At(itru)) ;
707 TMatrixD * timeRtrus = dynamic_cast<TMatrixD *>(timeRmatrix->At(itru)) ;
709 //Calculate row and column of the cell inside the TRU with number itru
710 Int_t irow = iphi - row * nCellsPhi;
712 irow = iphi - row * nCellsPhi2;
713 Int_t icol = ieta - col * nCellsEta;
715 (*amptrus)(irow,icol) = amp ;
716 (*timeRtrus)(irow,icol) = timeR ;
721 //______________________________________________________________________
722 void AliEMCALGeometry::GetCellPhiEtaIndexInSModuleFromTRUIndex(const Int_t itru, const Int_t iphitru, const Int_t ietatru, Int_t &iphiSM, Int_t &ietaSM) const
725 // This method transforms the (eta,phi) index of cells in a
726 // TRU matrix into Super Module (eta,phi) index.
728 // Calculate in which row and column where the TRU are
731 Int_t col = itru/ fNTRUPhi ;
732 Int_t row = itru - col*fNTRUPhi ;
734 //Calculate the (eta,phi) index in SM
735 Int_t nCellsPhi = fNPhi*2/fNTRUPhi;
736 Int_t nCellsEta = fNZ*2/fNTRUEta;
738 iphiSM = nCellsPhi*row + iphitru ;
739 ietaSM = nCellsEta*col + ietatru ;
742 //______________________________________________________________________
743 AliEMCALGeometry * AliEMCALGeometry::GetInstance(){
744 // Returns the pointer of the unique instance
746 AliEMCALGeometry * rv = static_cast<AliEMCALGeometry *>( fgGeom );
750 //______________________________________________________________________
751 AliEMCALGeometry* AliEMCALGeometry::GetInstance(const Text_t* name,
752 const Text_t* title){
753 // Returns the pointer of the unique instance
755 AliEMCALGeometry * rv = 0;
757 if ( strcmp(name,"") == 0 ) { // get default geometry
758 fgGeom = new AliEMCALGeometry(fgDefaultGeometryName, title);
760 fgGeom = new AliEMCALGeometry(name, title);
761 } // end if strcmp(name,"")
762 if ( fgInit ) rv = (AliEMCALGeometry * ) fgGeom;
769 if ( strcmp(fgGeom->GetName(), name) != 0) {
770 printf("\ncurrent geometry is %s : ", fgGeom->GetName());
771 printf(" you cannot call %s ", name);
773 rv = (AliEMCALGeometry *) fgGeom;
779 Bool_t AliEMCALGeometry::IsInEMCAL(Double_t x, Double_t y, Double_t z) const {
780 // Checks whether point is inside the EMCal volume, used in AliEMCALv*.cxx
782 // Code uses cylindrical approximation made of inner radius (for speed)
784 // Points behind EMCAl, i.e. R > outer radius, but eta, phi in acceptance
785 // are considered to inside
787 Double_t r=sqrt(x*x+y*y);
789 if ( r > fEnvelop[0] ) {
791 theta = TMath::ATan2(r,z);
796 eta = -TMath::Log(TMath::Tan(theta/2.));
797 if (eta < fArm1EtaMin || eta > fArm1EtaMax)
800 Double_t phi = TMath::ATan2(y,x) * 180./TMath::Pi();
801 if (phi > fArm1PhiMin && phi < fArm1PhiMax)
809 // == Shish-kebab cases ==
811 Int_t AliEMCALGeometry::GetAbsCellId(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta) const
815 // 13-oct-05; 110 degree case
816 // May 31, 2006; ALICE numbering scheme:
817 // 0 <= nSupMod < fNumberOfSuperModules
818 // 0 <= nModule < fNPHI * fNZ ( fNPHI * fNZ/2 for fKey110DEG=1)
819 // 0 <= nIphi < fNPHIdiv
820 // 0 <= nIeta < fNETAdiv
821 // 0 <= absid < fNCells
822 static Int_t id=0; // have to change from 0 to fNCells-1
823 if(fKey110DEG == 1 && nSupMod >= 10) { // 110 degree case; last two supermodules
824 id = fNCellsInSupMod*10 + (fNCellsInSupMod/2)*(nSupMod-10);
826 id = fNCellsInSupMod*nSupMod;
828 id += fNCellsInModule *nModule;
829 id += fNPHIdiv *nIphi;
831 if(id<0 || id >= fNCells) {
832 // printf(" wrong numerations !!\n");
833 // printf(" id %6i(will be force to -1)\n", id);
834 // printf(" fNCells %6i\n", fNCells);
835 // printf(" nSupMod %6i\n", nSupMod);
836 // printf(" nModule %6i\n", nModule);
837 // printf(" nIphi %6i\n", nIphi);
838 // printf(" nIeta %6i\n", nIeta);
839 id = -TMath::Abs(id); // if negative something wrong
844 Bool_t AliEMCALGeometry::CheckAbsCellId(Int_t absId) const
846 // May 31, 2006; only trd1 now
847 if(absId<0 || absId >= fNCells) return kFALSE;
851 Bool_t AliEMCALGeometry::GetCellIndex(Int_t absId,Int_t &nSupMod,Int_t &nModule,Int_t &nIphi,Int_t &nIeta) const
853 // 21-sep-04; 19-oct-05;
854 // May 31, 2006; ALICE numbering scheme:
857 // absId - cell is as in Geant, 0<= absId < fNCells;
859 // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
860 // nModule - module number in SM, 0<= nModule < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
861 // nIphi - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv;
862 // nIeta - cell number in eta driection inside module; 0<= nIeta < fNETAdiv;
864 static Int_t tmp=0, sm10=0;
865 if(!CheckAbsCellId(absId)) return kFALSE;
867 sm10 = fNCellsInSupMod*10;
868 if(fKey110DEG == 1 && absId >= sm10) { // 110 degree case; last two supermodules
869 nSupMod = (absId-sm10) / (fNCellsInSupMod/2) + 10;
870 tmp = (absId-sm10) % (fNCellsInSupMod/2);
872 nSupMod = absId / fNCellsInSupMod;
873 tmp = absId % fNCellsInSupMod;
876 nModule = tmp / fNCellsInModule;
877 tmp = tmp % fNCellsInModule;
878 nIphi = tmp / fNPHIdiv;
879 nIeta = tmp % fNPHIdiv;
884 void AliEMCALGeometry::GetModulePhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, int &iphim, int &ietam) const
886 // added nSupMod; - 19-oct-05 !
887 // Alice numbering scheme - Jun 01,2006
888 // ietam, iphi - indexes of module in two dimensional grid of SM
889 // ietam - have to change from 0 to fNZ-1
890 // iphim - have to change from 0 to nphi-1 (fNPhi-1 or fNPhi/2-1)
893 if(fKey110DEG == 1 && nSupMod>=10) nphi = fNPhi/2;
896 ietam = nModule/nphi;
897 iphim = nModule%nphi;
900 void AliEMCALGeometry::GetCellPhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta,
901 int &iphi, int &ieta) const
904 // Added nSupMod; Nov 25, 05
905 // Alice numbering scheme - Jun 01,2006
907 // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
908 // nModule - module number in SM, 0<= nModule < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
909 // nIphi - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv;
910 // nIeta - cell number in eta driection inside module; 0<= nIeta < fNETAdiv;
913 // ieta, iphi - indexes of cell(tower) in two dimensional grid of SM
914 // ieta - have to change from 0 to (fNZ*fNETAdiv-1)
915 // iphi - have to change from 0 to (fNPhi*fNPHIdiv-1 or fNPhi*fNPHIdiv/2-1)
917 static Int_t iphim, ietam;
919 GetModulePhiEtaIndexInSModule(nSupMod,nModule, iphim, ietam);
920 // ieta = ietam*fNETAdiv + (1-nIeta); // x(module) = -z(SM)
921 ieta = ietam*fNETAdiv + (fNETAdiv - 1 - nIeta); // x(module) = -z(SM)
922 iphi = iphim*fNPHIdiv + nIphi; // y(module) = y(SM)
925 AliDebug(1,Form(" nSupMod %i nModule %i nIphi %i nIeta %i => ieta %i iphi %i\n",
926 nSupMod, nModule, nIphi, nIeta, ieta, iphi));
929 Int_t AliEMCALGeometry::GetSuperModuleNumber(Int_t absId) const
931 // Return the number of the supermodule given the absolute
932 // ALICE numbering id
934 static Int_t nSupMod, nModule, nIphi, nIeta;
935 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
939 void AliEMCALGeometry::GetModuleIndexesFromCellIndexesInSModule(Int_t nSupMod, Int_t iphi, Int_t ieta,
940 Int_t &iphim, Int_t &ietam, Int_t &nModule) const
942 // Transition from cell indexes (ieta,iphi) to module indexes (ietam,iphim, nModule)
944 nphi = GetNumberOfModuleInPhiDirection(nSupMod);
946 ietam = ieta/fNETAdiv;
947 iphim = iphi/fNPHIdiv;
948 nModule = ietam * nphi + iphim;
951 Int_t AliEMCALGeometry::GetAbsCellIdFromCellIndexes(Int_t nSupMod, Int_t iphi, Int_t ieta) const
953 // Transition from super module number(nSupMod) and cell indexes (ieta,iphi) to absId
954 static Int_t ietam, iphim, nModule;
955 static Int_t nIeta, nIphi; // cell indexes in module
957 GetModuleIndexesFromCellIndexesInSModule(nSupMod, iphi, ieta, ietam, iphim, nModule);
959 nIeta = ieta%fNETAdiv;
960 nIeta = fNETAdiv - 1 - nIeta;
961 nIphi = iphi%fNPHIdiv;
963 return GetAbsCellId(nSupMod, nModule, nIphi, nIeta);
967 // Methods for AliEMCALRecPoint - Feb 19, 2006
968 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t &xr, Double_t &yr, Double_t &zr) const
970 // Look to see what the relative
971 // position inside a given cell is
973 // Alice numbering scheme - Jun 08, 2006
975 // absId - cell is as in Geant, 0<= absId < fNCells;
977 // xr,yr,zr - x,y,z coordinates of cell with absId inside SM
979 // Shift index taking into account the difference between standard SM
980 // and SM of half size in phi direction
981 const Int_t phiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
982 static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
983 if(!CheckAbsCellId(absId)) return kFALSE;
985 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
986 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta);
988 xr = fCentersOfCellsXDir.At(ieta);
989 zr = fCentersOfCellsEtaDir.At(ieta);
992 yr = fCentersOfCellsPhiDir.At(iphi);
994 yr = fCentersOfCellsPhiDir.At(iphi + phiIndexShift);
996 AliDebug(1,Form("absId %i nSupMod %i iphi %i ieta %i xr %f yr %f zr %f ",absId,nSupMod,iphi,ieta,xr,yr,zr));
1001 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t loc[3]) const
1003 // Alice numbering scheme - Jun 03, 2006
1004 loc[0] = loc[1] = loc[2]=0.0;
1005 if(RelPosCellInSModule(absId, loc[0],loc[1],loc[2])) {
1011 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, TVector3 &vloc) const
1013 static Double_t loc[3];
1014 if(RelPosCellInSModule(absId,loc)) {
1015 vloc.SetXYZ(loc[0], loc[1], loc[2]);
1021 // Alice numbering scheme - Jun 03, 2006
1024 void AliEMCALGeometry::CreateListOfTrd1Modules()
1026 // Generate the list of Trd1 modules
1027 // which will make up the EMCAL
1030 AliDebug(2,Form(" AliEMCALGeometry::CreateListOfTrd1Modules() started "));
1032 AliEMCALShishKebabTrd1Module *mod=0, *mTmp=0; // current module
1033 if(fShishKebabTrd1Modules == 0) {
1034 fShishKebabTrd1Modules = new TList;
1035 fShishKebabTrd1Modules->SetName("ListOfTRD1");
1036 for(int iz=0; iz< GetNZ(); iz++) {
1038 mod = new AliEMCALShishKebabTrd1Module(TMath::Pi()/2.,this);
1040 mTmp = new AliEMCALShishKebabTrd1Module(*mod);
1043 fShishKebabTrd1Modules->Add(mod);
1046 AliDebug(2,Form(" Already exits : "));
1048 mod = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(fShishKebabTrd1Modules->GetSize()-1);
1049 fEtaMaxOfTRD1 = mod->GetMaxEtaOfModule(0);
1051 AliDebug(2,Form(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n",
1052 fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1));
1054 // Jun 01, 2006 - ALICE numbering scheme
1055 // define grid for cells in eta(z) and x directions in local coordinates system of SM
1056 // Works just for 2x2 case only -- ?? start here
1059 // Define grid for cells in phi(y) direction in local coordinates system of SM
1060 // as for 2X2 as for 3X3 - Nov 8,2006
1062 AliDebug(2,Form(" Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize()));
1063 Int_t ind=0; // this is phi index
1064 Int_t ieta=0, nModule=0, iphiTemp;
1065 Double_t xr, zr, theta, phi, eta, r, x,y;
1067 Double_t ytCenterModule=0.0, ytCenterCell=0.0;
1069 fCentersOfCellsPhiDir.Set(fNPhi*fNPHIdiv);
1070 fPhiCentersOfCells.Set(fNPhi*fNPHIdiv);
1072 Double_t R0 = GetIPDistance() + GetLongModuleSize()/2.;
1073 for(Int_t it=0; it<fNPhi; it++) { // cycle on modules
1074 ytCenterModule = -fParSM[1] + fPhiModuleSize*(2*it+1)/2; // center of module
1075 for(Int_t ic=0; ic<fNPHIdiv; ic++) { // cycle on cells in module
1077 ytCenterCell = ytCenterModule + fPhiTileSize *(2*ic-1)/2.;
1078 } else if(fNPHIdiv==3){
1079 ytCenterCell = ytCenterModule + fPhiTileSize *(ic-1);
1080 } else if(fNPHIdiv==1){
1081 ytCenterCell = ytCenterModule;
1083 fCentersOfCellsPhiDir.AddAt(ytCenterCell,ind);
1084 // Define grid on phi direction
1085 // Grid is not the same for different eta bin;
1086 // Effect is small but is still here
1087 phi = TMath::ATan2(ytCenterCell, R0);
1088 fPhiCentersOfCells.AddAt(phi, ind);
1090 AliDebug(2,Form(" ind %2.2i : y %8.3f ", ind, fCentersOfCellsPhiDir.At(ind)));
1095 fCentersOfCellsEtaDir.Set(fNZ *fNETAdiv);
1096 fCentersOfCellsXDir.Set(fNZ *fNETAdiv);
1097 fEtaCentersOfCells.Set(fNZ *fNETAdiv * fNPhi*fNPHIdiv);
1098 AliDebug(2,Form(" Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize()));
1099 for(Int_t it=0; it<fNZ; it++) {
1100 AliEMCALShishKebabTrd1Module *trd1 = GetShishKebabModule(it);
1102 for(Int_t ic=0; ic<fNETAdiv; ic++) {
1104 trd1->GetCenterOfCellInLocalCoordinateofSM(ic, xr, zr); // case of 2X2
1105 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1107 trd1->GetCenterOfCellInLocalCoordinateofSM_3X3(ic, xr, zr); // case of 3X3
1108 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1110 trd1->GetCenterOfCellInLocalCoordinateofSM_1X1(xr, zr); // case of 1X1
1111 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1113 fCentersOfCellsXDir.AddAt(float(xr) - fParSM[0],ieta);
1114 fCentersOfCellsEtaDir.AddAt(float(zr) - fParSM[2],ieta);
1115 // Define grid on eta direction for each bin in phi
1116 for(int iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
1117 x = xr + trd1->GetRadius();
1118 y = fCentersOfCellsPhiDir[iphi];
1119 r = TMath::Sqrt(x*x + y*y + zr*zr);
1120 theta = TMath::ACos(zr/r);
1121 eta = AliEMCALShishKebabTrd1Module::ThetaToEta(theta);
1122 // ind = ieta*fCentersOfCellsPhiDir.GetSize() + iphi;
1123 ind = iphi*fCentersOfCellsEtaDir.GetSize() + ieta;
1124 fEtaCentersOfCells.AddAt(eta, ind);
1126 //printf(" ieta %i : xr + trd1->GetRadius() %f : zr %f : eta %f \n", ieta, xr + trd1->GetRadius(), zr, eta);
1129 for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1130 AliDebug(2,Form(" ind %2.2i : z %8.3f : x %8.3f", i+1,
1131 fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i)));
1136 void AliEMCALGeometry::GetTransformationForSM()
1138 //Uses the geometry manager to
1139 //load the transformation matrix
1140 //for the supermodules
1141 // Unused after 19 Jan, 2007 - keep for compatibility;
1144 static Bool_t transInit=kFALSE;
1145 if(transInit) return;
1148 if(gGeoManager == 0) {
1149 Info("CreateTransformationForSM() "," Load geometry : TGeoManager::Import()");
1152 TGeoNode *tn = gGeoManager->GetTopNode();
1153 TGeoNode *node=0, *xen1 = 0;
1154 for(i=0; i<tn->GetNdaughters(); i++) {
1155 node = tn->GetDaughter(i);
1156 TString ns(node->GetName());
1157 if(ns.Contains(GetNameOfEMCALEnvelope())) {
1163 Info("CreateTransformationForSM() "," geometry has not EMCAL envelope with name %s",
1164 GetNameOfEMCALEnvelope());
1167 printf(" i %i : EMCAL Envelope is %s : #SM %i \n", i, xen1->GetName(), xen1->GetNdaughters());
1168 for(i=0; i<xen1->GetNdaughters(); i++) {
1169 TGeoNodeMatrix *sm = (TGeoNodeMatrix*)xen1->GetDaughter(i);
1170 fMatrixOfSM[i] = sm->GetMatrix();
1171 //Compiler doesn't like this syntax...
1172 // printf(" %i : matrix %x \n", i, fMatrixOfSM[i]);
1177 void AliEMCALGeometry::GetGlobal(const Double_t *loc, Double_t *glob, int ind) const
1179 // Figure out the global numbering
1180 // of a given supermodule from the
1182 // Alice numbering - Jun 03,2006
1183 // if(fMatrixOfSM[0] == 0) GetTransformationForSM();
1185 if(ind>=0 && ind < GetNumberOfSuperModules()) {
1186 fMatrixOfSM[ind]->LocalToMaster(loc, glob);
1190 void AliEMCALGeometry::GetGlobal(const TVector3 &vloc, TVector3 &vglob, int ind) const
1192 //Figure out the global numbering
1193 //of a given supermodule from the
1194 //local numbering given a 3-vector location
1196 static Double_t tglob[3], tloc[3];
1198 GetGlobal(tloc, tglob, ind);
1199 vglob.SetXYZ(tglob[0], tglob[1], tglob[2]);
1202 void AliEMCALGeometry::GetGlobal(Int_t absId , double glob[3]) const
1204 // Alice numbering scheme - Jun 03, 2006
1205 static Int_t nSupMod, nModule, nIphi, nIeta;
1206 static double loc[3];
1208 glob[0]=glob[1]=glob[2]=0.0; // bad case
1209 if(RelPosCellInSModule(absId, loc)) {
1210 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
1211 fMatrixOfSM[nSupMod]->LocalToMaster(loc, glob);
1215 void AliEMCALGeometry::GetGlobal(Int_t absId , TVector3 &vglob) const
1217 // Alice numbering scheme - Jun 03, 2006
1218 static Double_t glob[3];
1220 GetGlobal(absId, glob);
1221 vglob.SetXYZ(glob[0], glob[1], glob[2]);
1225 void AliEMCALGeometry::GetGlobal(const AliRecPoint *rp, TVector3 &vglob) const
1227 // Figure out the global numbering
1228 // of a given supermodule from the
1229 // local numbering for RecPoints
1231 static TVector3 vloc;
1232 static Int_t nSupMod, nModule, nIphi, nIeta;
1234 AliRecPoint *rpTmp = (AliRecPoint*)rp; // const_cast ??
1236 AliEMCALRecPoint *rpEmc = (AliEMCALRecPoint*)rpTmp;
1238 GetCellIndex(rpEmc->GetAbsId(0), nSupMod, nModule, nIphi, nIeta);
1239 rpTmp->GetLocalPosition(vloc);
1240 GetGlobal(vloc, vglob, nSupMod);
1243 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Double_t &eta,Double_t &phi) const
1245 // Nov 16, 2006- float to double
1246 // version for TRD1 only
1247 static TVector3 vglob;
1248 GetGlobal(absId, vglob);
1253 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Float_t &eta,Float_t &phi) const
1255 // Nov 16,2006 - should be discard in future
1256 static TVector3 vglob;
1257 GetGlobal(absId, vglob);
1258 eta = float(vglob.Eta());
1259 phi = float(vglob.Phi());
1262 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSM(Int_t nSupMod, Double_t &phiMin, Double_t &phiMax) const
1264 // 0<= nSupMod <=11; phi in rad
1266 if(nSupMod<0 || nSupMod >11) return kFALSE;
1268 phiMin = fPhiBoundariesOfSM[2*i];
1269 phiMax = fPhiBoundariesOfSM[2*i+1];
1273 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSMGap(Int_t nPhiSec, Double_t &phiMin, Double_t &phiMax) const
1275 // 0<= nPhiSec <=4; phi in rad
1276 // 0; gap boundaries between 0th&2th | 1th&3th SM
1277 // 1; gap boundaries between 2th&4th | 3th&5th SM
1278 // 2; gap boundaries between 4th&6th | 5th&7th SM
1279 // 3; gap boundaries between 6th&8th | 7th&9th SM
1280 // 4; gap boundaries between 8th&10th | 9th&11th SM
1281 if(nPhiSec<0 || nPhiSec >4) return kFALSE;
1282 phiMin = fPhiBoundariesOfSM[2*nPhiSec+1];
1283 phiMax = fPhiBoundariesOfSM[2*nPhiSec+2];
1287 Bool_t AliEMCALGeometry::SuperModuleNumberFromEtaPhi(Double_t eta, Double_t phi, Int_t &nSupMod) const
1289 // Return false if phi belongs a phi cracks between SM
1293 if(TMath::Abs(eta) > fEtaMaxOfTRD1) return kFALSE;
1295 phi = TVector2::Phi_0_2pi(phi); // move phi to (0,2pi) boundaries
1296 for(i=0; i<6; i++) {
1297 if(phi>=fPhiBoundariesOfSM[2*i] && phi<=fPhiBoundariesOfSM[2*i+1]) {
1299 if(eta < 0.0) nSupMod++;
1300 AliDebug(1,Form("eta %f phi %f(%5.2f) : nSupMod %i : #bound %i", eta,phi,phi*TMath::RadToDeg(), nSupMod,i));
1307 Bool_t AliEMCALGeometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi, Int_t &absId) const
1310 // stay here - phi problem as usual
1311 static Int_t nSupMod, i, ieta, iphi, etaShift, nphi;
1312 static Double_t absEta=0.0, d=0.0, dmin=0.0, phiLoc;
1313 absId = nSupMod = - 1;
1314 if(SuperModuleNumberFromEtaPhi(eta, phi, nSupMod)) {
1316 phi = TVector2::Phi_0_2pi(phi);
1317 phiLoc = phi - fPhiCentersOfSM[nSupMod/2];
1318 nphi = fPhiCentersOfCells.GetSize();
1320 phiLoc = phi - 190.*TMath::DegToRad();
1324 dmin = TMath::Abs(fPhiCentersOfCells[0]-phiLoc);
1326 for(i=1; i<nphi; i++) {
1327 d = TMath::Abs(fPhiCentersOfCells[i] - phiLoc);
1332 // printf(" i %i : d %f : dmin %f : fPhiCentersOfCells[i] %f \n", i, d, dmin, fPhiCentersOfCells[i]);
1334 // odd SM are turned with respect of even SM - reverse indexes
1335 AliDebug(2,Form(" iphi %i : dmin %f (phi %f, phiLoc %f ) ", iphi, dmin, phi, phiLoc));
1337 absEta = TMath::Abs(eta);
1338 etaShift = iphi*fCentersOfCellsEtaDir.GetSize();
1339 dmin = TMath::Abs(fEtaCentersOfCells[etaShift]-absEta);
1341 for(i=1; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1342 d = TMath::Abs(fEtaCentersOfCells[i+etaShift] - absEta);
1348 AliDebug(2,Form(" ieta %i : dmin %f (eta=%f) : nSupMod %i ", ieta, dmin, eta, nSupMod));
1350 if(eta<0) iphi = (nphi-1) - iphi;
1351 absId = GetAbsCellIdFromCellIndexes(nSupMod, iphi, ieta);
1358 AliEMCALShishKebabTrd1Module* AliEMCALGeometry::GetShishKebabModule(Int_t neta)
1360 //This method was too long to be
1361 //included in the header file - the
1362 //rule checker complained about it's
1363 //length, so we move it here. It returns the
1364 //shishkebabmodule at a given eta index point.
1366 static AliEMCALShishKebabTrd1Module* trd1=0;
1367 if(fShishKebabTrd1Modules && neta>=0 && neta<fShishKebabTrd1Modules->GetSize()) {
1368 trd1 = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(neta);
1373 void AliEMCALGeometry::Browse(TBrowser* b)
1375 if(fShishKebabTrd1Modules) b->Add(fShishKebabTrd1Modules);
1376 for(int i=0; i<fNumberOfSuperModules; i++) {
1377 if(fMatrixOfSM[i]) b->Add(fMatrixOfSM[i]);
1381 Bool_t AliEMCALGeometry::IsFolder() const
1383 if(fShishKebabTrd1Modules) return kTRUE;