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>
57 #include "AliEMCALGeometry.h"
58 #include "AliEMCALShishKebabTrd1Module.h"
59 #include "AliEMCALRecPoint.h"
60 #include "AliEMCALDigit.h"
61 #include "AliEMCALHistoUtilities.h"
63 ClassImp(AliEMCALGeometry)
65 // these initialisations are needed for a singleton
66 AliEMCALGeometry *AliEMCALGeometry::fgGeom = 0;
67 Bool_t AliEMCALGeometry::fgInit = kFALSE;
68 Char_t* AliEMCALGeometry::fgDefaultGeometryName = "SHISH_77_TRD1_2X2_FINAL_110DEG";
71 // You can create the AliEMCALGeometry object independently from anything.
72 // You have to use just the correct name of geometry. If name is empty string the
73 // default name of geometry will be used.
75 // AliEMCALGeometry* g = AliEMCALGeometry::GetInstance(name,title); // first time
77 // g = AliEMCALGeometry::GetInstance(); // after first time
79 // MC: If you work with MC data you have to get geometry the next way:
80 // == =============================
81 // AliRunLoader *rl = AliRunLoader::GetRunLoader();
82 // AliEMCALGeometry *geom = dynamic_cast<AliEMCAL*>(rl->GetAliRun()->GetDetector("EMCAL"))->GetGeometry();
85 AliEMCALGeometry::AliEMCALGeometry()
87 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
88 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
89 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
90 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
91 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
92 fNCells(0),fNCellsInSupMod(0),fNCellsInModule(0),fNTRUEta(0),fNTRUPhi(0),
93 fNCellsInTRUEta(0), fNCellsInTRUPhi(0), fTrd1Angle(0.),f2Trd1Dx2(0.),
94 fPhiGapForSM(0.),fKey110DEG(0),fPhiBoundariesOfSM(0), fPhiCentersOfSM(0),fEtaMaxOfTRD1(0),
95 fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fCentersOfCellsEtaDir(0),
96 fCentersOfCellsXDir(0),fCentersOfCellsPhiDir(0),fEtaCentersOfCells(0),fPhiCentersOfCells(0),
97 fShishKebabTrd1Modules(0), fNAdditionalOpts(0),
98 fILOSS(-1), fIHADR(-1)
100 // default ctor only for internal usage (singleton)
101 // must be kept public for root persistency purposes, but should never be called by the outside world
102 // CreateListOfTrd1Modules();
103 AliDebug(2, "AliEMCALGeometry : default ctor ");
105 //______________________________________________________________________
106 AliEMCALGeometry::AliEMCALGeometry(const Text_t* name, const Text_t* title)
107 : AliGeometry(name, title),
108 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
109 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
110 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
111 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
112 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
113 fNCells(0),fNCellsInSupMod(0),fNCellsInModule(0),fNTRUEta(0),fNTRUPhi(0),
114 fNCellsInTRUEta(0), fNCellsInTRUPhi(0), fTrd1Angle(0.),f2Trd1Dx2(0.),
115 fPhiGapForSM(0.),fKey110DEG(0),fPhiBoundariesOfSM(0), fPhiCentersOfSM(0), fEtaMaxOfTRD1(0),
116 fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fCentersOfCellsEtaDir(0),
117 fCentersOfCellsXDir(0),fCentersOfCellsPhiDir(0),fEtaCentersOfCells(0),fPhiCentersOfCells(0),
118 fShishKebabTrd1Modules(0),fNAdditionalOpts(0),
119 fILOSS(-1), fIHADR(-1)
121 // ctor only for internal usage (singleton)
122 AliDebug(2, Form("AliEMCALGeometry(%s,%s) ", name,title));
126 CreateListOfTrd1Modules();
128 if (AliDebugLevel()>=2) {
133 //______________________________________________________________________
134 AliEMCALGeometry::AliEMCALGeometry(const AliEMCALGeometry& geom)
136 fGeoName(geom.fGeoName),
137 fArrayOpts(geom.fArrayOpts),
138 fAlFrontThick(geom.fAlFrontThick),
139 fECPbRadThickness(geom.fECPbRadThickness),
140 fECScintThick(geom.fECScintThick),
141 fNECLayers(geom.fNECLayers),
142 fArm1PhiMin(geom.fArm1PhiMin),
143 fArm1PhiMax(geom.fArm1PhiMax),
144 fArm1EtaMin(geom.fArm1EtaMin),
145 fArm1EtaMax(geom.fArm1EtaMax),
146 fIPDistance(geom.fIPDistance),
147 fShellThickness(geom.fShellThickness),
148 fZLength(geom.fZLength),
149 fGap2Active(geom.fGap2Active),
152 fSampling(geom.fSampling),
153 fNumberOfSuperModules(geom.fNumberOfSuperModules),
154 fSteelFrontThick(geom.fSteelFrontThick),
155 fFrontSteelStrip(geom.fFrontSteelStrip),
156 fLateralSteelStrip(geom.fLateralSteelStrip),
157 fPassiveScintThick(geom.fPassiveScintThick),
158 fPhiModuleSize(geom.fPhiModuleSize),
159 fEtaModuleSize(geom.fEtaModuleSize),
160 fPhiTileSize(geom.fPhiTileSize),
161 fEtaTileSize(geom.fEtaTileSize),
162 fLongModuleSize(geom.fLongModuleSize),
163 fNPhiSuperModule(geom.fNPhiSuperModule),
164 fNPHIdiv(geom.fNPHIdiv),
165 fNETAdiv(geom.fNETAdiv),
166 fNCells(geom.fNCells),
167 fNCellsInSupMod(geom.fNCellsInSupMod),
168 fNCellsInModule(geom.fNCellsInModule),
169 fNTRUEta(geom.fNTRUEta),
170 fNTRUPhi(geom.fNTRUPhi),
171 fNCellsInTRUEta(geom.fNCellsInTRUEta),
172 fNCellsInTRUPhi(geom.fNCellsInTRUPhi),
173 fTrd1Angle(geom.fTrd1Angle),
174 f2Trd1Dx2(geom.f2Trd1Dx2),
175 fPhiGapForSM(geom.fPhiGapForSM),
176 fKey110DEG(geom.fKey110DEG),
177 fPhiBoundariesOfSM(geom.fPhiBoundariesOfSM),
178 fPhiCentersOfSM(geom.fPhiCentersOfSM),
179 fEtaMaxOfTRD1(geom.fEtaMaxOfTRD1),
180 fTrd2AngleY(geom.fTrd2AngleY),
181 f2Trd2Dy2(geom.f2Trd2Dy2),
182 fEmptySpace(geom.fEmptySpace),
184 fTubsTurnAngle(geom.fTubsTurnAngle),
185 fCentersOfCellsEtaDir(geom.fCentersOfCellsEtaDir),
186 fCentersOfCellsXDir(geom.fCentersOfCellsXDir),
187 fCentersOfCellsPhiDir(geom.fCentersOfCellsPhiDir),
188 fEtaCentersOfCells(geom.fEtaCentersOfCells),
189 fPhiCentersOfCells(geom.fPhiCentersOfCells),
190 fShishKebabTrd1Modules(geom.fShishKebabTrd1Modules),
191 fNAdditionalOpts(geom.fNAdditionalOpts),
192 fILOSS(geom.fILOSS), fIHADR(geom.fIHADR)
197 //______________________________________________________________________
198 AliEMCALGeometry::~AliEMCALGeometry(void){
201 //______________________________________________________________________
202 void AliEMCALGeometry::Init(void){
203 // Initializes the EMCAL parameters
204 // naming convention : GUV_WX_N_ gives the composition of a tower
205 // WX inform about the composition of the EM calorimeter section:
206 // thickness in mm of Pb radiator (W) and of scintillator (X), and number of scintillator layers (N)
207 // New geometry: EMCAL_55_25
208 // 24-aug-04 for shish-kebab
209 // SHISH_25 or SHISH_62
210 // 11-oct-05 - correction for pre final design
211 // Feb 06,2006 - decrease the weight of EMCAL
213 // Oct 30,2006 - SHISH_TRD1_CURRENT_1X1, SHISH_TRD1_CURRENT_2X2 or SHISH_TRD1_CURRENT_3X3;
216 fAdditionalOpts[0] = "nl="; // number of sampling layers (fNECLayers)
217 fAdditionalOpts[1] = "pbTh="; // cm, Thickness of the Pb (fECPbRadThick)
218 fAdditionalOpts[2] = "scTh="; // cm, Thickness of the Sc (fECScintThick)
219 fAdditionalOpts[3] = "latSS="; // cm, Thickness of lateral steel strip (fLateralSteelStrip)
220 fAdditionalOpts[4] = "allILOSS="; // = 0,1,2,3,4 (4 - energy loss without fluctuation)
221 fAdditionalOpts[5] = "allIHADR="; // = 0,1,2 (0 - no hadronic interaction)
223 fNAdditionalOpts = sizeof(fAdditionalOpts) / sizeof(char*);
225 fgInit = kFALSE; // Assume failed until proven otherwise.
226 fGeoName = GetName();
229 if(fGeoName.Contains("110DEG") || fGeoName.Contains("CURRENT")) fKey110DEG = 1; // for GetAbsCellId
230 fShishKebabTrd1Modules = 0;
231 fTrd2AngleY = f2Trd2Dy2 = fEmptySpace = fTubsR = fTubsTurnAngle = 0;
233 fNZ = 114; // granularity along Z (eta)
234 fNPhi = 168; // granularity in phi (azimuth)
235 fArm1PhiMin = 80.0; // degrees, Starting EMCAL Phi position
236 fArm1PhiMax = 190.0; // degrees, Ending EMCAL Phi position
237 fArm1EtaMin = -0.7; // pseudorapidity, Starting EMCAL Eta position
238 fArm1EtaMax = +0.7; // pseudorapidity, Ending EMCAL Eta position
239 fIPDistance = 454.0; // cm, Radial distance to inner surface of EMCAL
240 fPhiGapForSM = 0.; // cm, only for final TRD1 geometry
241 for(int i=0; i<12; i++) fMatrixOfSM[i] = 0;
244 if(fGeoName.Contains("SHISH")){ // Only shahslyk now
245 // 7-sep-05; integration issue
246 fArm1PhiMin = 80.0; // 60 -> 80
247 fArm1PhiMax = 180.0; // 180 -> 190
249 fNumberOfSuperModules = 10; // 12 = 6 * 2 (6 in phi, 2 in Z);
250 fSteelFrontThick = 2.54; // 9-sep-04
252 fFrontSteelStrip = fPassiveScintThick = 0.0; // 13-may-05
253 fLateralSteelStrip = 0.025; // before MAY 2005
254 fPhiModuleSize = fEtaModuleSize = 11.4;
255 fPhiTileSize = fEtaTileSize = 5.52; // (11.4-5.52*2)/2. = 0.18 cm (wall thickness)
258 fAlFrontThick = fGap2Active = 0;
259 fNPHIdiv = fNETAdiv = 2;
262 fECScintThick = fECPbRadThickness = 0.2;
263 fSampling = 1.; // 30-aug-04 - should be calculated
264 if(fGeoName.Contains("TWIST")) { // all about EMCAL module
265 fNZ = 27; // 16-sep-04
266 } else if(fGeoName.Contains("TRD")) {
267 fIPDistance = 428.0; // 11-may-05
268 fSteelFrontThick = 0.0; // 3.17 -> 0.0; 28-mar-05 : no stell plate
271 fPhiModuleSize = fEtaModuleSize = 12.26;
272 fNZ = 26; // 11-oct-04
273 fTrd1Angle = 1.3; // in degree
274 // 18-nov-04; 1./0.08112=12.327
275 // http://pdsfweb01.nersc.gov/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
276 if(fGeoName.Contains("TRD1")) { // 30-jan-05
278 fPhiGapForSM = 2.; // cm, only for final TRD1 geometry
279 if(fGeoName.Contains("MAY05") || fGeoName.Contains("WSUC") || fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")){
280 fNumberOfSuperModules = 12; // 20-may-05
281 if(fGeoName.Contains("WSUC")) fNumberOfSuperModules = 1; // 27-may-05
282 fNECLayers = 77; // (13-may-05 from V.Petrov)
283 fPhiModuleSize = 12.5; // 20-may-05 - rectangular shape
284 fEtaModuleSize = 11.9;
285 fECScintThick = fECPbRadThickness = 0.16;// (13-may-05 from V.Petrov)
286 fFrontSteelStrip = 0.025;// 0.025cm = 0.25mm (13-may-05 from V.Petrov)
287 fLateralSteelStrip = 0.01; // 0.01cm = 0.1mm (13-may-05 from V.Petrov) - was 0.025
288 fPassiveScintThick = 0.8; // 0.8cm = 8mm (13-may-05 from V.Petrov)
290 fTrd1Angle = 1.5; // 1.3 or 1.5
292 if(fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")) { // 9-sep-05
293 fNumberOfSuperModules = 10;
295 fNumberOfSuperModules = 12;// last two modules have size 10 degree in phi (180<phi<190)
296 fArm1PhiMax = 200.0; // for XEN1 and turn angle of super modules
298 if(fGeoName.Contains("FINAL")) {
299 fPhiModuleSize = 12.26 - fPhiGapForSM / Float_t(fNPhi); // first assumption
300 } else if(fGeoName.Contains("CURRENT")) {
301 fECScintThick = 0.176; // 10% of weight reduction
302 fECPbRadThickness = 0.144; //
303 fLateralSteelStrip = 0.015; // 0.015cm = 0.15mm (Oct 30, from Fred)
304 fPhiModuleSize = 12.00;
305 fPhiGapForSM = (12.26 - fPhiModuleSize)*fNPhi; // have to check
307 fEtaModuleSize = fPhiModuleSize;
308 if(fGeoName.Contains("HUGE")) fNECLayers *= 3; // 28-oct-05 for analysing leakage
311 } else if(fGeoName.Contains("TRD2")) { // 30-jan-05
312 fSteelFrontThick = 0.0; // 11-mar-05
313 fIPDistance+= fSteelFrontThick; // 1-feb-05 - compensate absence of steel plate
314 fTrd1Angle = 1.64; // 1.3->1.64
315 fTrd2AngleY = fTrd1Angle; // symmetric case now
316 fEmptySpace = 0.2; // 2 mm
317 fTubsR = fIPDistance; // 31-jan-05 - as for Fred case
319 fPhiModuleSize = fTubsR*2.*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
320 fPhiModuleSize -= fEmptySpace/2.; // 11-mar-05
321 fEtaModuleSize = fPhiModuleSize; // 20-may-05
324 fNPHIdiv = fNETAdiv = 2; // 13-oct-04 - division again
325 if(fGeoName.Contains("3X3")) { // 23-nov-04
326 fNPHIdiv = fNETAdiv = 3;
327 } else if(fGeoName.Contains("4X4")) {
328 fNPHIdiv = fNETAdiv = 4;
329 } else if(fGeoName.Contains("1X1")) {
330 fNPHIdiv = fNETAdiv = 1;
333 if(fGeoName.Contains("25")){
335 fECScintThick = fECPbRadThickness = 0.5;
337 if(fGeoName.Contains("WSUC")){ // 18-may-05 - about common structure
338 fShellThickness = 30.; // should be change
342 CheckAdditionalOptions();
343 DefineSamplingFraction();
345 fPhiTileSize = fPhiModuleSize/double(fNPHIdiv) - fLateralSteelStrip; // 13-may-05
346 fEtaTileSize = fEtaModuleSize/double(fNETAdiv) - fLateralSteelStrip; // 13-may-05
348 // constant for transition absid <--> indexes
349 fNCellsInModule = fNPHIdiv*fNETAdiv;
350 fNCellsInSupMod = fNCellsInModule*fNPhi*fNZ;
351 fNCells = fNCellsInSupMod*fNumberOfSuperModules;
352 if(GetKey110DEG()) fNCells -= fNCellsInSupMod;
354 fLongModuleSize = fNECLayers*(fECScintThick + fECPbRadThickness);
355 if(fGeoName.Contains("MAY05")) fLongModuleSize += (fFrontSteelStrip + fPassiveScintThick);
358 if(fGeoName.Contains("TRD")) {
359 f2Trd1Dx2 = fEtaModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd1Angle*TMath::DegToRad()/2.);
360 if(fGeoName.Contains("TRD2")) { // 27-jan-05
361 f2Trd2Dy2 = fPhiModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
364 } else Fatal("Init", "%s is an undefined geometry!", fGeoName.Data()) ;
366 fNPhiSuperModule = fNumberOfSuperModules/2;
367 if(fNPhiSuperModule<1) fNPhiSuperModule = 1;
369 fShellThickness = fAlFrontThick + fGap2Active + fNECLayers*GetECScintThick()+(fNECLayers-1)*GetECPbRadThick();
370 if(fGeoName.Contains("SHISH")) {
371 fShellThickness = fSteelFrontThick + fLongModuleSize;
372 if(fGeoName.Contains("TWIST")) { // 13-sep-04
373 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + fPhiModuleSize*fEtaModuleSize);
374 fShellThickness += fSteelFrontThick;
375 } else if(fGeoName.Contains("TRD")) { // 1-oct-04
376 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + f2Trd1Dx2*f2Trd1Dx2);
377 fShellThickness += fSteelFrontThick;
379 fParSM[0] = GetShellThickness()/2.;
380 fParSM[1] = GetPhiModuleSize() * GetNPhi()/2.;
385 fZLength = 2.*ZFromEtaR(fIPDistance+fShellThickness,fArm1EtaMax); // Z coverage
386 fEnvelop[0] = fIPDistance; // mother volume inner radius
387 fEnvelop[1] = fIPDistance + fShellThickness; // mother volume outer r.
388 fEnvelop[2] = 1.00001*fZLength; // add some padding for mother volume.
390 fNumberOfSuperModules = 12;
392 // SM phi boundaries - (0,1),(2,3) .. (10,11) - has the same boundaries; Nov 7, 2006
393 fPhiBoundariesOfSM.Set(fNumberOfSuperModules);
394 fPhiCentersOfSM.Set(fNumberOfSuperModules/2);
395 fPhiBoundariesOfSM[0] = TMath::PiOver2() - TMath::ATan2(fParSM[1] , fIPDistance); // 1th and 2th modules)
396 fPhiBoundariesOfSM[1] = TMath::PiOver2() + TMath::ATan2(fParSM[1] , fIPDistance);
397 fPhiCentersOfSM[0] = TMath::PiOver2();
398 for(int i=1; i<=4; i++) { // from 2th ro 9th
399 fPhiBoundariesOfSM[2*i] = fPhiBoundariesOfSM[0] + 20.*TMath::DegToRad()*i;
400 fPhiBoundariesOfSM[2*i+1] = fPhiBoundariesOfSM[1] + 20.*TMath::DegToRad()*i;
401 fPhiCentersOfSM[i] = fPhiCentersOfSM[0] + 20.*TMath::DegToRad()*i;
403 fPhiBoundariesOfSM[11] = 190.*TMath::DegToRad();
404 fPhiBoundariesOfSM[10] = fPhiBoundariesOfSM[11] - TMath::ATan2((fParSM[1]) , fIPDistance);
405 fPhiCentersOfSM[5] = (fPhiBoundariesOfSM[10]+fPhiBoundariesOfSM[11])/2.;
407 //TRU parameters. These parameters values are not the final ones.
410 fNCellsInTRUEta = 16 ;
411 fNCellsInTRUPhi = 24 ;
413 // Define TGeoMatrix of SM - Jan 19, 2007 (just fro TRD1)
414 if(fGeoName.Contains("TRD1")) { // copy code from AliEMCALv0::CreateSmod()
415 int nphism = GetNumberOfSuperModules()/2;
416 double dphi = (GetArm1PhiMax() - GetArm1PhiMin())/nphism;
417 double rpos = (GetEnvelop(0) + GetEnvelop(1))/2.;
418 double phi, phiRad, xpos, ypos, zpos;
419 for(int i=0; i<nphism; i++){
420 phi = GetArm1PhiMin() + dphi*(2*i+1)/2.; // phi= 90, 110, 130, 150, 170, 190
421 phiRad = phi*TMath::Pi()/180.;
422 xpos = rpos * TMath::Cos(phiRad);
423 ypos = rpos * TMath::Sin(phiRad);
426 xpos += (fParSM[1]/2. * TMath::Sin(phiRad));
427 ypos -= (fParSM[1]/2. * TMath::Cos(phiRad));
431 TGeoRotation *geoRot0 = new TGeoRotation("geoRot0", 90.0, phi, 90.0, 90.0+phi, 0.0, 0.0);
432 fMatrixOfSM[ind] = new TGeoCombiTrans(Form("EmcalSM%2.2i",ind),
433 xpos,ypos, zpos, geoRot0);
436 double phiy = 90. + phi + 180.;
437 if(phiy>=360.) phiy -= 360.;
438 TGeoRotation *geoRot1 = new TGeoRotation("geoRot1", 90.0, phi, 90.0, phiy, 180.0, 0.0);
439 fMatrixOfSM[ind] = new TGeoCombiTrans(Form("EmcalSM%2.2i",ind),
440 xpos,ypos,-zpos, geoRot1);
444 if(fGeoName.Contains("WSUC")) fNumberOfSuperModules = 1; // Jul 12, 2007
447 AliInfo(" is ended");
450 void AliEMCALGeometry::PrintGeometry()
452 // Separate routine is callable from broswer; Nov 7,2006
453 printf("\nInit: geometry of EMCAL named %s :\n", fGeoName.Data());
455 for(Int_t i=0; i<fArrayOpts->GetEntries(); i++){
456 TObjString *o = (TObjString*)fArrayOpts->At(i);
457 printf(" %i : %s \n", i, o->String().Data());
460 printf("Granularity: %d in eta and %d in phi\n", GetNZ(), GetNPhi()) ;
461 printf("Layout: phi = (%7.1f, %7.1f), eta = (%5.2f, %5.2f), IP = %7.2f -> for EMCAL envelope only\n",
462 GetArm1PhiMin(), GetArm1PhiMax(),GetArm1EtaMin(), GetArm1EtaMax(), GetIPDistance() );
464 printf( " ECAL : %d x (%f cm Pb, %f cm Sc) \n",
465 GetNECLayers(), GetECPbRadThick(), GetECScintThick() ) ;
466 printf(" fSampling %5.2f \n", fSampling );
467 if(fGeoName.Contains("SHISH")){
468 printf(" fIPDistance %6.3f cm \n", fIPDistance);
469 if(fSteelFrontThick>0.)
470 printf(" fSteelFrontThick %6.3f cm \n", fSteelFrontThick);
471 printf(" fNPhi %i | fNZ %i \n", fNPhi, fNZ);
472 printf(" fNCellsInModule %i : fNCellsInSupMod %i : fNCells %i\n",fNCellsInModule, fNCellsInSupMod, fNCells);
473 if(fGeoName.Contains("MAY05")){
474 printf(" fFrontSteelStrip %6.4f cm (thickness of front steel strip)\n",
476 printf(" fLateralSteelStrip %6.4f cm (thickness of lateral steel strip)\n",
478 printf(" fPassiveScintThick %6.4f cm (thickness of front passive Sc tile)\n",
481 printf(" X:Y module size %6.3f , %6.3f cm \n", fPhiModuleSize, fEtaModuleSize);
482 printf(" X:Y tile size %6.3f , %6.3f cm \n", fPhiTileSize, fEtaTileSize);
483 printf(" #of sampling layers %i(fNECLayers) \n", fNECLayers);
484 printf(" fLongModuleSize %6.3f cm \n", fLongModuleSize);
485 printf(" #supermodule in phi direction %i \n", fNPhiSuperModule );
487 printf(" fILOSS %i : fIHADR %i \n", fILOSS, fIHADR);
488 if(fGeoName.Contains("TRD")) {
489 printf(" fTrd1Angle %7.4f\n", fTrd1Angle);
490 printf(" f2Trd1Dx2 %7.4f\n", f2Trd1Dx2);
491 if(fGeoName.Contains("TRD2")) {
492 printf(" fTrd2AngleY %7.4f\n", fTrd2AngleY);
493 printf(" f2Trd2Dy2 %7.4f\n", f2Trd2Dy2);
494 printf(" fTubsR %7.2f cm\n", fTubsR);
495 printf(" fTubsTurnAngle %7.4f\n", fTubsTurnAngle);
496 printf(" fEmptySpace %7.4f cm\n", fEmptySpace);
497 } else if(fGeoName.Contains("TRD1")){
498 printf("SM dimensions(TRD1) : dx %7.2f dy %7.2f dz %7.2f (SMOD, BOX)\n",
499 fParSM[0],fParSM[1],fParSM[2]);
500 printf(" fPhiGapForSM %7.4f cm (%7.4f <- phi size in degree)\n",
501 fPhiGapForSM, TMath::ATan2(fPhiGapForSM,fIPDistance)*TMath::RadToDeg());
502 if(GetKey110DEG()) printf(" Last two modules have size 10 degree in phi (180<phi<190)\n");
503 printf(" phi SM boundaries \n");
504 for(int i=0; i<fPhiBoundariesOfSM.GetSize()/2.; i++) {
505 printf(" %i : %7.5f(%7.2f) -> %7.5f(%7.2f) : center %7.5f(%7.2f) \n", i,
506 fPhiBoundariesOfSM[2*i], fPhiBoundariesOfSM[2*i]*TMath::RadToDeg(),
507 fPhiBoundariesOfSM[2*i+1], fPhiBoundariesOfSM[2*i+1]*TMath::RadToDeg(),
508 fPhiCentersOfSM[i], fPhiCentersOfSM[i]*TMath::RadToDeg());
510 printf(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n",
511 fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1);
513 printf("\n Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize());
514 for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
515 printf(" ind %2.2i : z %8.3f : x %8.3f \n", i,
516 fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i));
517 int ind=0; // Nov 21,2006
518 for(Int_t iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
519 ind = iphi*fCentersOfCellsEtaDir.GetSize() + i;
520 printf("%6.4f ", fEtaCentersOfCells[ind]);
521 if((iphi+1)%12 == 0) printf("\n");
526 printf(" Matrix transformation\n");
527 for(Int_t i=0; i<12; i++) {
528 TGeoMatrix *m = fMatrixOfSM[i];
530 const double *xyz = m->GetTranslation();
531 printf(" %2.2i %s %s x %7.2f y %7.2f z %7.2f\n",
532 i, m->GetName(), m->ClassName(), xyz[0],xyz[1],xyz[2]);
535 printf("\n Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize());
536 for(Int_t i=0; i<fCentersOfCellsPhiDir.GetSize(); i++) {
537 double phi=fPhiCentersOfCells.At(i);
538 printf(" ind %2.2i : y %8.3f : phi %7.5f(%6.2f) \n", i, fCentersOfCellsPhiDir.At(i),
539 phi, phi*TMath::RadToDeg());
546 void AliEMCALGeometry::PrintCellIndexes(Int_t absId, int pri, char *tit)
549 Int_t nSupMod, nModule, nIphi, nIeta;
553 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
554 printf(" %s | absId : %i -> nSupMod %i nModule %i nIphi %i nIeta %i \n", tit, absId, nSupMod, nModule, nIphi, nIeta);
556 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
557 printf(" local SM index : iphi %i : ieta %i \n", iphi,ieta);
558 GetGlobal(absId, vg);
559 printf(" vglob : mag %7.2f : perp %7.2f : z %7.2f : eta %6.4f : phi %6.4f(%6.2f) \n",
560 vg.Mag(), vg.Perp(), vg.Z(), vg.Eta(), vg.Phi(), vg.Phi()*TMath::RadToDeg());
564 //______________________________________________________________________
565 void AliEMCALGeometry::CheckAdditionalOptions()
568 // Additional options that
569 // can be used to select
570 // the specific geometry of
573 // adeed allILOSS= and allIHADR= for MIP investigation
574 fArrayOpts = new TObjArray;
575 Int_t nopt = AliEMCALHistoUtilities::ParseString(fGeoName, *fArrayOpts);
576 if(nopt==1) { // no aditional option(s)
577 fArrayOpts->Delete();
582 for(Int_t i=1; i<nopt; i++){
583 TObjString *o = (TObjString*)fArrayOpts->At(i);
585 TString addOpt = o->String();
587 for(Int_t j=0; j<fNAdditionalOpts; j++) {
588 TString opt = fAdditionalOpts[j];
589 if(addOpt.Contains(opt,TString::kIgnoreCase)) {
595 AliDebug(2,Form("<E> option |%s| unavailable : ** look to the file AliEMCALGeometry.h **\n",
599 AliDebug(2,Form("<I> option |%s| is valid : number %i : |%s|\n",
600 addOpt.Data(), indj, fAdditionalOpts[indj]));
601 if (addOpt.Contains("NL=",TString::kIgnoreCase)) {// number of sampling layers
602 sscanf(addOpt.Data(),"NL=%i", &fNECLayers);
603 AliDebug(2,Form(" fNECLayers %i (new) \n", fNECLayers));
604 } else if(addOpt.Contains("PBTH=",TString::kIgnoreCase)) {//Thickness of the Pb(fECPbRadThicknes)
605 sscanf(addOpt.Data(),"PBTH=%f", &fECPbRadThickness);
606 } else if(addOpt.Contains("SCTH=",TString::kIgnoreCase)) {//Thickness of the Sc(fECScintThick)
607 sscanf(addOpt.Data(),"SCTH=%f", &fECScintThick);
608 } else if(addOpt.Contains("LATSS=",TString::kIgnoreCase)) {// Thickness of lateral steel strip (fLateralSteelStrip)
609 sscanf(addOpt.Data(),"LATSS=%f", &fLateralSteelStrip);
610 AliDebug(2,Form(" fLateralSteelStrip %f (new) \n", fLateralSteelStrip));
611 } else if(addOpt.Contains("ILOSS=",TString::kIgnoreCase)) {// As in Geant
612 sscanf(addOpt.Data(),"ALLILOSS=%i", &fILOSS);
613 AliDebug(2,Form(" fILOSS %i \n", fILOSS));
614 } else if(addOpt.Contains("IHADR=",TString::kIgnoreCase)) {// As in Geant
615 sscanf(addOpt.Data(),"ALLIHADR=%i", &fIHADR);
616 AliDebug(2,Form(" fIHADR %i \n", fIHADR));
622 void AliEMCALGeometry::DefineSamplingFraction()
625 // Look http://rhic.physics.wayne.edu/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
626 // Keep for compatibilty
628 if(fNECLayers == 69) { // 10% layer reduction
630 } else if(fNECLayers == 61) { // 20% layer reduction
632 } else if(fNECLayers == 77) {
633 if (fECScintThick>0.175 && fECScintThick<0.177) { // 10% Pb thicknes reduction
634 fSampling = 10.5; // fECScintThick = 0.176, fECPbRadThickness=0.144;
635 } else if(fECScintThick>0.191 && fECScintThick<0.193) { // 20% Pb thicknes reduction
636 fSampling = 8.93; // fECScintThick = 0.192, fECPbRadThickness=0.128;
641 //______________________________________________________________________
642 void AliEMCALGeometry::GetCellPhiEtaIndexInSModuleFromTRUIndex(const Int_t itru, const Int_t iphitru, const Int_t ietatru, Int_t &iphiSM, Int_t &ietaSM) const
645 // This method transforms the (eta,phi) index of cells in a
646 // TRU matrix into Super Module (eta,phi) index.
648 // Calculate in which row and column where the TRU are
651 Int_t col = itru/ fNTRUPhi ;
652 Int_t row = itru - col*fNTRUPhi ;
654 iphiSM = fNCellsInTRUPhi*row + iphitru ;
655 ietaSM = fNCellsInTRUEta*col + ietatru ;
658 //______________________________________________________________________
659 AliEMCALGeometry * AliEMCALGeometry::GetInstance(){
660 // Returns the pointer of the unique instance
662 AliEMCALGeometry * rv = static_cast<AliEMCALGeometry *>( fgGeom );
666 //______________________________________________________________________
667 AliEMCALGeometry* AliEMCALGeometry::GetInstance(const Text_t* name,
668 const Text_t* title){
669 // Returns the pointer of the unique instance
671 AliEMCALGeometry * rv = 0;
673 if ( strcmp(name,"") == 0 ) { // get default geometry
674 fgGeom = new AliEMCALGeometry(fgDefaultGeometryName, title);
676 fgGeom = new AliEMCALGeometry(name, title);
677 } // end if strcmp(name,"")
678 if ( fgInit ) rv = (AliEMCALGeometry * ) fgGeom;
685 if ( strcmp(fgGeom->GetName(), name) != 0) {
686 printf("\ncurrent geometry is %s : ", fgGeom->GetName());
687 printf(" you cannot call %s ", name);
689 rv = (AliEMCALGeometry *) fgGeom;
695 Bool_t AliEMCALGeometry::IsInEMCAL(Double_t x, Double_t y, Double_t z) const {
696 // Checks whether point is inside the EMCal volume, used in AliEMCALv*.cxx
698 // Code uses cylindrical approximation made of inner radius (for speed)
700 // Points behind EMCAl, i.e. R > outer radius, but eta, phi in acceptance
701 // are considered to inside
703 Double_t r=sqrt(x*x+y*y);
705 if ( r > fEnvelop[0] ) {
707 theta = TMath::ATan2(r,z);
712 eta = -TMath::Log(TMath::Tan(theta/2.));
713 if (eta < fArm1EtaMin || eta > fArm1EtaMax)
716 Double_t phi = TMath::ATan2(y,x) * 180./TMath::Pi();
717 if (phi < 0) phi += 360; // phi should go from 0 to 360 in this case
718 if (phi > fArm1PhiMin && phi < fArm1PhiMax)
726 // == Shish-kebab cases ==
728 Int_t AliEMCALGeometry::GetAbsCellId(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta) const
732 // 13-oct-05; 110 degree case
733 // May 31, 2006; ALICE numbering scheme:
734 // 0 <= nSupMod < fNumberOfSuperModules
735 // 0 <= nModule < fNPHI * fNZ ( fNPHI * fNZ/2 for fKey110DEG=1)
736 // 0 <= nIphi < fNPHIdiv
737 // 0 <= nIeta < fNETAdiv
738 // 0 <= absid < fNCells
739 static Int_t id=0; // have to change from 0 to fNCells-1
740 if(fKey110DEG == 1 && nSupMod >= 10) { // 110 degree case; last two supermodules
741 id = fNCellsInSupMod*10 + (fNCellsInSupMod/2)*(nSupMod-10);
743 id = fNCellsInSupMod*nSupMod;
745 id += fNCellsInModule *nModule;
746 id += fNPHIdiv *nIphi;
748 if(id<0 || id >= fNCells) {
749 // printf(" wrong numerations !!\n");
750 // printf(" id %6i(will be force to -1)\n", id);
751 // printf(" fNCells %6i\n", fNCells);
752 // printf(" nSupMod %6i\n", nSupMod);
753 // printf(" nModule %6i\n", nModule);
754 // printf(" nIphi %6i\n", nIphi);
755 // printf(" nIeta %6i\n", nIeta);
756 id = -TMath::Abs(id); // if negative something wrong
761 Bool_t AliEMCALGeometry::CheckAbsCellId(Int_t absId) const
763 // May 31, 2006; only trd1 now
764 if(absId<0 || absId >= fNCells) return kFALSE;
768 Bool_t AliEMCALGeometry::GetCellIndex(Int_t absId,Int_t &nSupMod,Int_t &nModule,Int_t &nIphi,Int_t &nIeta) const
770 // 21-sep-04; 19-oct-05;
771 // May 31, 2006; ALICE numbering scheme:
774 // absId - cell is as in Geant, 0<= absId < fNCells;
776 // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
777 // nModule - module number in SM, 0<= nModule < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
778 // nIphi - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv;
779 // nIeta - cell number in eta driection inside module; 0<= nIeta < fNETAdiv;
781 static Int_t tmp=0, sm10=0;
782 if(!CheckAbsCellId(absId)) return kFALSE;
784 sm10 = fNCellsInSupMod*10;
785 if(fKey110DEG == 1 && absId >= sm10) { // 110 degree case; last two supermodules
786 nSupMod = (absId-sm10) / (fNCellsInSupMod/2) + 10;
787 tmp = (absId-sm10) % (fNCellsInSupMod/2);
789 nSupMod = absId / fNCellsInSupMod;
790 tmp = absId % fNCellsInSupMod;
793 nModule = tmp / fNCellsInModule;
794 tmp = tmp % fNCellsInModule;
795 nIphi = tmp / fNPHIdiv;
796 nIeta = tmp % fNPHIdiv;
801 void AliEMCALGeometry::GetModulePhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, int &iphim, int &ietam) const
803 // added nSupMod; - 19-oct-05 !
804 // Alice numbering scheme - Jun 01,2006
805 // ietam, iphi - indexes of module in two dimensional grid of SM
806 // ietam - have to change from 0 to fNZ-1
807 // iphim - have to change from 0 to nphi-1 (fNPhi-1 or fNPhi/2-1)
810 if(fKey110DEG == 1 && nSupMod>=10) nphi = fNPhi/2;
813 ietam = nModule/nphi;
814 iphim = nModule%nphi;
817 void AliEMCALGeometry::GetCellPhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta,
818 int &iphi, int &ieta) const
821 // Added nSupMod; Nov 25, 05
822 // Alice numbering scheme - Jun 01,2006
824 // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
825 // nModule - module number in SM, 0<= nModule < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
826 // nIphi - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv;
827 // nIeta - cell number in eta driection inside module; 0<= nIeta < fNETAdiv;
830 // ieta, iphi - indexes of cell(tower) in two dimensional grid of SM
831 // ieta - have to change from 0 to (fNZ*fNETAdiv-1)
832 // iphi - have to change from 0 to (fNPhi*fNPHIdiv-1 or fNPhi*fNPHIdiv/2-1)
834 static Int_t iphim, ietam;
836 GetModulePhiEtaIndexInSModule(nSupMod,nModule, iphim, ietam);
837 // ieta = ietam*fNETAdiv + (1-nIeta); // x(module) = -z(SM)
838 ieta = ietam*fNETAdiv + (fNETAdiv - 1 - nIeta); // x(module) = -z(SM)
839 iphi = iphim*fNPHIdiv + nIphi; // y(module) = y(SM)
842 AliDebug(1,Form(" nSupMod %i nModule %i nIphi %i nIeta %i => ieta %i iphi %i\n",
843 nSupMod, nModule, nIphi, nIeta, ieta, iphi));
846 Int_t AliEMCALGeometry::GetSuperModuleNumber(Int_t absId) const
848 // Return the number of the supermodule given the absolute
849 // ALICE numbering id
851 static Int_t nSupMod, nModule, nIphi, nIeta;
852 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
856 void AliEMCALGeometry::GetModuleIndexesFromCellIndexesInSModule(Int_t nSupMod, Int_t iphi, Int_t ieta,
857 Int_t &iphim, Int_t &ietam, Int_t &nModule) const
859 // Transition from cell indexes (ieta,iphi) to module indexes (ietam,iphim, nModule)
861 nphi = GetNumberOfModuleInPhiDirection(nSupMod);
863 ietam = ieta/fNETAdiv;
864 iphim = iphi/fNPHIdiv;
865 nModule = ietam * nphi + iphim;
868 Int_t AliEMCALGeometry::GetAbsCellIdFromCellIndexes(Int_t nSupMod, Int_t iphi, Int_t ieta) const
870 // Transition from super module number(nSupMod) and cell indexes (ieta,iphi) to absId
871 static Int_t ietam, iphim, nModule;
872 static Int_t nIeta, nIphi; // cell indexes in module
874 GetModuleIndexesFromCellIndexesInSModule(nSupMod, iphi, ieta, ietam, iphim, nModule);
876 nIeta = ieta%fNETAdiv;
877 nIeta = fNETAdiv - 1 - nIeta;
878 nIphi = iphi%fNPHIdiv;
880 return GetAbsCellId(nSupMod, nModule, nIphi, nIeta);
884 // Methods for AliEMCALRecPoint - Feb 19, 2006
885 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t &xr, Double_t &yr, Double_t &zr) const
887 // Look to see what the relative
888 // position inside a given cell is
890 // Alice numbering scheme - Jun 08, 2006
892 // absId - cell is as in Geant, 0<= absId < fNCells;
894 // xr,yr,zr - x,y,z coordinates of cell with absId inside SM
896 // Shift index taking into account the difference between standard SM
897 // and SM of half size in phi direction
898 const Int_t phiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
899 static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
900 if(!CheckAbsCellId(absId)) return kFALSE;
902 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
903 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta);
905 xr = fCentersOfCellsXDir.At(ieta);
906 zr = fCentersOfCellsEtaDir.At(ieta);
909 yr = fCentersOfCellsPhiDir.At(iphi);
911 yr = fCentersOfCellsPhiDir.At(iphi + phiIndexShift);
913 AliDebug(1,Form("absId %i nSupMod %i iphi %i ieta %i xr %f yr %f zr %f ",absId,nSupMod,iphi,ieta,xr,yr,zr));
918 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t loc[3]) const
920 // Alice numbering scheme - Jun 03, 2006
921 loc[0] = loc[1] = loc[2]=0.0;
922 if(RelPosCellInSModule(absId, loc[0],loc[1],loc[2])) {
928 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, TVector3 &vloc) const
930 static Double_t loc[3];
931 if(RelPosCellInSModule(absId,loc)) {
932 vloc.SetXYZ(loc[0], loc[1], loc[2]);
938 // Alice numbering scheme - Jun 03, 2006
941 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t distEff, Double_t &xr, Double_t &yr, Double_t &zr) const
943 // Jul 30, 2007 - taking into account position of shower max
944 // Look to see what the relative
945 // position inside a given cell is
948 // absId - cell is as in Geant, 0<= absId < fNCells;
949 // e - cluster energy
951 // xr,yr,zr - x,y,z coordinates of cell with absId inside SM
953 // Shift index taking into account the difference between standard SM
954 // and SM of half size in phi direction
955 const Int_t phiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
956 static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
957 static Int_t iphim, ietam;
958 static AliEMCALShishKebabTrd1Module *mod = 0;
960 if(!CheckAbsCellId(absId)) return kFALSE;
962 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
963 GetModulePhiEtaIndexInSModule(nSupMod, nModule, iphim, ietam);
964 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta);
966 mod = GetShishKebabModule(ietam);
967 mod->GetPositionAtCenterCellLine(nIeta, distEff, v);
968 xr = v.Y() - fParSM[0];
969 zr = v.X() - fParSM[2];
972 yr = fCentersOfCellsPhiDir.At(iphi);
974 yr = fCentersOfCellsPhiDir.At(iphi + phiIndexShift);
976 AliDebug(1,Form("absId %i nSupMod %i iphi %i ieta %i xr %f yr %f zr %f ",absId,nSupMod,iphi,ieta,xr,yr,zr));
981 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Int_t maxAbsId, Double_t distEff, Double_t &xr, Double_t &yr, Double_t &zr) const
983 // Jul 31, 2007 - taking into account position of shower max and apply coor2.
984 // Look to see what the relative
985 // position inside a given cell is
988 // absId - cell is as in Geant, 0<= absId < fNCells;
989 // maxAbsId - abs id of cell with highest energy
990 // e - cluster energy
992 // xr,yr,zr - x,y,z coordinates of cell with absId inside SM
994 // Shift index taking into account the difference between standard SM
995 // and SM of half size in phi direction
996 const Int_t phiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
997 static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
998 static Int_t iphim, ietam;
999 static AliEMCALShishKebabTrd1Module *mod = 0;
1002 static Int_t nSupModM, nModuleM, nIphiM, nIetaM, iphiM, ietaM;
1003 static Int_t iphimM, ietamM, maxAbsIdCopy=-1;
1004 static AliEMCALShishKebabTrd1Module *modM = 0;
1005 static Double_t distCorr;
1007 if(!CheckAbsCellId(absId)) return kFALSE;
1009 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
1010 GetModulePhiEtaIndexInSModule(nSupMod, nModule, iphim, ietam);
1011 GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta);
1012 mod = GetShishKebabModule(ietam);
1014 if(absId != maxAbsId) {
1016 if(maxAbsIdCopy != maxAbsId) {
1017 GetCellIndex(maxAbsId, nSupModM, nModuleM, nIphiM, nIetaM);
1018 GetModulePhiEtaIndexInSModule(nSupModM, nModuleM, iphimM, ietamM);
1019 GetCellPhiEtaIndexInSModule(nSupModM,nModuleM,nIphiM,nIetaM, iphiM, ietaM);
1020 modM = GetShishKebabModule(ietamM); // do I need this ?
1021 maxAbsIdCopy = maxAbsId;
1024 distCorr = GetEtaModuleSize()*(ietam-ietamM)/TMath::Tan(modM->GetTheta()); // Stay here
1025 //printf(" distCorr %f | dist %f | ietam %i -> etamM %i\n", distCorr, dist, ietam, ietamM);
1027 // distEff += distCorr;
1029 // Bad resolution in this case, strong bias vs phi
1031 mod->GetPositionAtCenterCellLine(nIeta, distEff, v); // Stay here
1032 xr = v.Y() - fParSM[0];
1033 zr = v.X() - fParSM[2];
1036 yr = fCentersOfCellsPhiDir.At(iphi);
1038 yr = fCentersOfCellsPhiDir.At(iphi + phiIndexShift);
1040 AliDebug(1,Form("absId %i nSupMod %i iphi %i ieta %i xr %f yr %f zr %f ",absId,nSupMod,iphi,ieta,xr,yr,zr));
1045 void AliEMCALGeometry::CreateListOfTrd1Modules()
1047 // Generate the list of Trd1 modules
1048 // which will make up the EMCAL
1051 AliDebug(2,Form(" AliEMCALGeometry::CreateListOfTrd1Modules() started "));
1053 AliEMCALShishKebabTrd1Module *mod=0, *mTmp=0; // current module
1054 if(fShishKebabTrd1Modules == 0) {
1055 fShishKebabTrd1Modules = new TList;
1056 fShishKebabTrd1Modules->SetName("ListOfTRD1");
1057 for(int iz=0; iz< GetNZ(); iz++) {
1059 mod = new AliEMCALShishKebabTrd1Module(TMath::Pi()/2.,this);
1061 mTmp = new AliEMCALShishKebabTrd1Module(*mod);
1064 fShishKebabTrd1Modules->Add(mod);
1067 AliDebug(2,Form(" Already exits : "));
1069 mod = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(fShishKebabTrd1Modules->GetSize()-1);
1070 fEtaMaxOfTRD1 = mod->GetMaxEtaOfModule(0);
1072 AliDebug(2,Form(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n",
1073 fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1));
1075 // Jun 01, 2006 - ALICE numbering scheme
1076 // define grid for cells in eta(z) and x directions in local coordinates system of SM
1077 // Works just for 2x2 case only -- ?? start here
1080 // Define grid for cells in phi(y) direction in local coordinates system of SM
1081 // as for 2X2 as for 3X3 - Nov 8,2006
1083 AliDebug(2,Form(" Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize()));
1084 Int_t ind=0; // this is phi index
1085 Int_t ieta=0, nModule=0, iphiTemp;
1086 Double_t xr, zr, theta, phi, eta, r, x,y;
1088 Double_t ytCenterModule=0.0, ytCenterCell=0.0;
1090 fCentersOfCellsPhiDir.Set(fNPhi*fNPHIdiv);
1091 fPhiCentersOfCells.Set(fNPhi*fNPHIdiv);
1093 Double_t R0 = GetIPDistance() + GetLongModuleSize()/2.;
1094 for(Int_t it=0; it<fNPhi; it++) { // cycle on modules
1095 ytCenterModule = -fParSM[1] + fPhiModuleSize*(2*it+1)/2; // center of module
1096 for(Int_t ic=0; ic<fNPHIdiv; ic++) { // cycle on cells in module
1098 ytCenterCell = ytCenterModule + fPhiTileSize *(2*ic-1)/2.;
1099 } else if(fNPHIdiv==3){
1100 ytCenterCell = ytCenterModule + fPhiTileSize *(ic-1);
1101 } else if(fNPHIdiv==1){
1102 ytCenterCell = ytCenterModule;
1104 fCentersOfCellsPhiDir.AddAt(ytCenterCell,ind);
1105 // Define grid on phi direction
1106 // Grid is not the same for different eta bin;
1107 // Effect is small but is still here
1108 phi = TMath::ATan2(ytCenterCell, R0);
1109 fPhiCentersOfCells.AddAt(phi, ind);
1111 AliDebug(2,Form(" ind %2.2i : y %8.3f ", ind, fCentersOfCellsPhiDir.At(ind)));
1116 fCentersOfCellsEtaDir.Set(fNZ *fNETAdiv);
1117 fCentersOfCellsXDir.Set(fNZ *fNETAdiv);
1118 fEtaCentersOfCells.Set(fNZ *fNETAdiv * fNPhi*fNPHIdiv);
1119 AliDebug(2,Form(" Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize()));
1120 for(Int_t it=0; it<fNZ; it++) {
1121 AliEMCALShishKebabTrd1Module *trd1 = GetShishKebabModule(it);
1123 for(Int_t ic=0; ic<fNETAdiv; ic++) {
1125 trd1->GetCenterOfCellInLocalCoordinateofSM(ic, xr, zr); // case of 2X2
1126 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1128 trd1->GetCenterOfCellInLocalCoordinateofSM_3X3(ic, xr, zr); // case of 3X3
1129 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1131 trd1->GetCenterOfCellInLocalCoordinateofSM_1X1(xr, zr); // case of 1X1
1132 GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta);
1134 fCentersOfCellsXDir.AddAt(float(xr) - fParSM[0],ieta);
1135 fCentersOfCellsEtaDir.AddAt(float(zr) - fParSM[2],ieta);
1136 // Define grid on eta direction for each bin in phi
1137 for(int iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
1138 x = xr + trd1->GetRadius();
1139 y = fCentersOfCellsPhiDir[iphi];
1140 r = TMath::Sqrt(x*x + y*y + zr*zr);
1141 theta = TMath::ACos(zr/r);
1142 eta = AliEMCALShishKebabTrd1Module::ThetaToEta(theta);
1143 // ind = ieta*fCentersOfCellsPhiDir.GetSize() + iphi;
1144 ind = iphi*fCentersOfCellsEtaDir.GetSize() + ieta;
1145 fEtaCentersOfCells.AddAt(eta, ind);
1147 //printf(" ieta %i : xr + trd1->GetRadius() %f : zr %f : eta %f \n", ieta, xr + trd1->GetRadius(), zr, eta);
1150 for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1151 AliDebug(2,Form(" ind %2.2i : z %8.3f : x %8.3f", i+1,
1152 fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i)));
1157 void AliEMCALGeometry::GetTransformationForSM()
1159 //Uses the geometry manager to
1160 //load the transformation matrix
1161 //for the supermodules
1162 // Unused after 19 Jan, 2007 - keep for compatibility;
1165 static Bool_t transInit=kFALSE;
1166 if(transInit) return;
1169 if(gGeoManager == 0) {
1170 Info("CreateTransformationForSM() "," Load geometry : TGeoManager::Import()");
1173 TGeoNode *tn = gGeoManager->GetTopNode();
1174 TGeoNode *node=0, *xen1 = 0;
1175 for(i=0; i<tn->GetNdaughters(); i++) {
1176 node = tn->GetDaughter(i);
1177 TString ns(node->GetName());
1178 if(ns.Contains(GetNameOfEMCALEnvelope())) {
1184 Info("CreateTransformationForSM() "," geometry has not EMCAL envelope with name %s",
1185 GetNameOfEMCALEnvelope());
1188 printf(" i %i : EMCAL Envelope is %s : #SM %i \n", i, xen1->GetName(), xen1->GetNdaughters());
1189 for(i=0; i<xen1->GetNdaughters(); i++) {
1190 TGeoNodeMatrix *sm = (TGeoNodeMatrix*)xen1->GetDaughter(i);
1191 fMatrixOfSM[i] = sm->GetMatrix();
1192 //Compiler doesn't like this syntax...
1193 // printf(" %i : matrix %x \n", i, fMatrixOfSM[i]);
1198 void AliEMCALGeometry::GetGlobal(const Double_t *loc, Double_t *glob, int ind) const
1200 // Figure out the global numbering
1201 // of a given supermodule from the
1203 // Alice numbering - Jun 03,2006
1204 // if(fMatrixOfSM[0] == 0) GetTransformationForSM();
1206 if(ind>=0 && ind < GetNumberOfSuperModules()) {
1207 fMatrixOfSM[ind]->LocalToMaster(loc, glob);
1211 void AliEMCALGeometry::GetGlobal(const TVector3 &vloc, TVector3 &vglob, int ind) const
1213 //Figure out the global numbering
1214 //of a given supermodule from the
1215 //local numbering given a 3-vector location
1217 static Double_t tglob[3], tloc[3];
1219 GetGlobal(tloc, tglob, ind);
1220 vglob.SetXYZ(tglob[0], tglob[1], tglob[2]);
1223 void AliEMCALGeometry::GetGlobal(Int_t absId , double glob[3]) const
1225 // Alice numbering scheme - Jun 03, 2006
1226 static Int_t nSupMod, nModule, nIphi, nIeta;
1227 static double loc[3];
1229 glob[0]=glob[1]=glob[2]=0.0; // bad case
1230 if(RelPosCellInSModule(absId, loc)) {
1231 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
1232 fMatrixOfSM[nSupMod]->LocalToMaster(loc, glob);
1236 void AliEMCALGeometry::GetGlobal(Int_t absId , TVector3 &vglob) const
1238 // Alice numbering scheme - Jun 03, 2006
1239 static Double_t glob[3];
1241 GetGlobal(absId, glob);
1242 vglob.SetXYZ(glob[0], glob[1], glob[2]);
1246 void AliEMCALGeometry::GetGlobal(const AliRecPoint *rp, TVector3 &vglob) const
1248 // Figure out the global numbering
1249 // of a given supermodule from the
1250 // local numbering for RecPoints
1252 static TVector3 vloc;
1253 static Int_t nSupMod, nModule, nIphi, nIeta;
1255 AliRecPoint *rpTmp = (AliRecPoint*)rp; // const_cast ??
1257 AliEMCALRecPoint *rpEmc = (AliEMCALRecPoint*)rpTmp;
1259 GetCellIndex(rpEmc->GetAbsId(0), nSupMod, nModule, nIphi, nIeta);
1260 rpTmp->GetLocalPosition(vloc);
1261 GetGlobal(vloc, vglob, nSupMod);
1264 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Double_t &eta,Double_t &phi) const
1266 // Nov 16, 2006- float to double
1267 // version for TRD1 only
1268 static TVector3 vglob;
1269 GetGlobal(absId, vglob);
1274 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Float_t &eta,Float_t &phi) const
1276 // Nov 16,2006 - should be discard in future
1277 static TVector3 vglob;
1278 GetGlobal(absId, vglob);
1279 eta = float(vglob.Eta());
1280 phi = float(vglob.Phi());
1283 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSM(Int_t nSupMod, Double_t &phiMin, Double_t &phiMax) const
1285 // 0<= nSupMod <=11; phi in rad
1287 if(nSupMod<0 || nSupMod >11) return kFALSE;
1289 phiMin = fPhiBoundariesOfSM[2*i];
1290 phiMax = fPhiBoundariesOfSM[2*i+1];
1294 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSMGap(Int_t nPhiSec, Double_t &phiMin, Double_t &phiMax) const
1296 // 0<= nPhiSec <=4; phi in rad
1297 // 0; gap boundaries between 0th&2th | 1th&3th SM
1298 // 1; gap boundaries between 2th&4th | 3th&5th SM
1299 // 2; gap boundaries between 4th&6th | 5th&7th SM
1300 // 3; gap boundaries between 6th&8th | 7th&9th SM
1301 // 4; gap boundaries between 8th&10th | 9th&11th SM
1302 if(nPhiSec<0 || nPhiSec >4) return kFALSE;
1303 phiMin = fPhiBoundariesOfSM[2*nPhiSec+1];
1304 phiMax = fPhiBoundariesOfSM[2*nPhiSec+2];
1308 Bool_t AliEMCALGeometry::SuperModuleNumberFromEtaPhi(Double_t eta, Double_t phi, Int_t &nSupMod) const
1310 // Return false if phi belongs a phi cracks between SM
1314 if(TMath::Abs(eta) > fEtaMaxOfTRD1) return kFALSE;
1316 phi = TVector2::Phi_0_2pi(phi); // move phi to (0,2pi) boundaries
1317 for(i=0; i<6; i++) {
1318 if(phi>=fPhiBoundariesOfSM[2*i] && phi<=fPhiBoundariesOfSM[2*i+1]) {
1320 if(eta < 0.0) nSupMod++;
1321 AliDebug(1,Form("eta %f phi %f(%5.2f) : nSupMod %i : #bound %i", eta,phi,phi*TMath::RadToDeg(), nSupMod,i));
1328 Bool_t AliEMCALGeometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi, Int_t &absId) const
1331 // stay here - phi problem as usual
1332 static Int_t nSupMod, i, ieta, iphi, etaShift, nphi;
1333 static Double_t absEta=0.0, d=0.0, dmin=0.0, phiLoc;
1334 absId = nSupMod = - 1;
1335 if(SuperModuleNumberFromEtaPhi(eta, phi, nSupMod)) {
1337 phi = TVector2::Phi_0_2pi(phi);
1338 phiLoc = phi - fPhiCentersOfSM[nSupMod/2];
1339 nphi = fPhiCentersOfCells.GetSize();
1341 phiLoc = phi - 190.*TMath::DegToRad();
1345 dmin = TMath::Abs(fPhiCentersOfCells[0]-phiLoc);
1347 for(i=1; i<nphi; i++) {
1348 d = TMath::Abs(fPhiCentersOfCells[i] - phiLoc);
1353 // printf(" i %i : d %f : dmin %f : fPhiCentersOfCells[i] %f \n", i, d, dmin, fPhiCentersOfCells[i]);
1355 // odd SM are turned with respect of even SM - reverse indexes
1356 AliDebug(2,Form(" iphi %i : dmin %f (phi %f, phiLoc %f ) ", iphi, dmin, phi, phiLoc));
1358 absEta = TMath::Abs(eta);
1359 etaShift = iphi*fCentersOfCellsEtaDir.GetSize();
1360 dmin = TMath::Abs(fEtaCentersOfCells[etaShift]-absEta);
1362 for(i=1; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1363 d = TMath::Abs(fEtaCentersOfCells[i+etaShift] - absEta);
1369 AliDebug(2,Form(" ieta %i : dmin %f (eta=%f) : nSupMod %i ", ieta, dmin, eta, nSupMod));
1371 if(eta<0) iphi = (nphi-1) - iphi;
1372 absId = GetAbsCellIdFromCellIndexes(nSupMod, iphi, ieta);
1379 AliEMCALShishKebabTrd1Module* AliEMCALGeometry::GetShishKebabModule(Int_t neta) const
1381 //This method was too long to be
1382 //included in the header file - the
1383 //rule checker complained about it's
1384 //length, so we move it here. It returns the
1385 //shishkebabmodule at a given eta index point.
1387 static AliEMCALShishKebabTrd1Module* trd1=0;
1388 if(fShishKebabTrd1Modules && neta>=0 && neta<fShishKebabTrd1Modules->GetSize()) {
1389 trd1 = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(neta);
1394 void AliEMCALGeometry::Browse(TBrowser* b)
1396 if(fShishKebabTrd1Modules) b->Add(fShishKebabTrd1Modules);
1397 for(int i=0; i<fNumberOfSuperModules; i++) {
1398 if(fMatrixOfSM[i]) b->Add(fMatrixOfSM[i]);
1402 Bool_t AliEMCALGeometry::IsFolder() const
1404 if(fShishKebabTrd1Modules) return kTRUE;