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 //*-- Author: Sahal Yacoob (LBL / UCT)
27 // and : Yves Schutz (SUBATECH)
28 // and : Jennifer Klay (LBL)
29 // SHASHLYK : Aleksei Pavlinov (WSU)
30 // SuperModules -> module(or tower) -> cell
32 // --- AliRoot header files ---
34 #include "Riostream.h"
38 //#include <TArrayD.h>
39 #include <TObjArray.h>
40 #include <TGeoManager.h>
42 #include <TGeoMatrix.h>
44 #include <TObjString.h>
45 #include <TClonesArray.h>
48 //#include "AliConst.h"
52 #include "AliEMCALGeometry.h"
53 #include "AliEMCALShishKebabTrd1Module.h"
54 #include "AliEMCALRecPoint.h"
55 #include "AliEMCALDigit.h"
56 #include "AliEMCALHistoUtilities.h"
58 ClassImp(AliEMCALGeometry)
60 // these initialisations are needed for a singleton
61 AliEMCALGeometry *AliEMCALGeometry::fgGeom = 0;
62 Bool_t AliEMCALGeometry::fgInit = kFALSE;
65 AliEMCALGeometry::AliEMCALGeometry()
67 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
68 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
69 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
70 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
71 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
72 fNCells(0),fNCellsInSupMod(0),fNCellsInTower(0),fNTRU(0),fNTRUEta(0),fNTRUPhi(0),fTrd1Angle(0.),f2Trd1Dx2(0.),
73 fPhiGapForSM(0.),fKey110DEG(0),fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fEtaCentersOfCells(0),
74 fXCentersOfCells(0),fPhiCentersOfCells(0),fShishKebabTrd1Modules(),fNAdditionalOpts(0)
76 // default ctor only for internal usage (singleton)
77 // must be kept public for root persistency purposes, but should never be called by the outside world
78 // CreateListOfTrd1Modules();
79 AliDebug(2, "AliEMCALGeometry : default ctor ");
81 //______________________________________________________________________
82 AliEMCALGeometry::AliEMCALGeometry(const Text_t* name, const Text_t* title)
83 : AliGeometry(name, title),
84 fGeoName(0),fArrayOpts(0),fAlFrontThick(0.),fECPbRadThickness(0.),fECScintThick(0.),
85 fNECLayers(0),fArm1PhiMin(0.),fArm1PhiMax(0.),fArm1EtaMin(0.),fArm1EtaMax(0.),fIPDistance(0.),
86 fShellThickness(0.),fZLength(0.),fGap2Active(0.),fNZ(0),fNPhi(0),fSampling(0.),fNumberOfSuperModules(0),
87 fSteelFrontThick(0.),fFrontSteelStrip(0.),fLateralSteelStrip(0.),fPassiveScintThick(0.),fPhiModuleSize(0.),
88 fEtaModuleSize(0.),fPhiTileSize(0.),fEtaTileSize(0.),fLongModuleSize(0.),fNPhiSuperModule(0),fNPHIdiv(0),fNETAdiv(0),
89 fNCells(0),fNCellsInSupMod(0),fNCellsInTower(0),fNTRU(0),fNTRUEta(0),fNTRUPhi(0),fTrd1Angle(0.),f2Trd1Dx2(0.),
90 fPhiGapForSM(0.),fKey110DEG(0),fTrd2AngleY(0.),f2Trd2Dy2(0.),fEmptySpace(0.),fTubsR(0.),fTubsTurnAngle(0.),fEtaCentersOfCells(0),
91 fXCentersOfCells(0),fPhiCentersOfCells(0),fShishKebabTrd1Modules(),fNAdditionalOpts(0)
93 // ctor only for internal usage (singleton)
94 AliDebug(2, Form("AliEMCALGeometry(%s,%s) ", name,title));
96 CreateListOfTrd1Modules();
98 //______________________________________________________________________
99 AliEMCALGeometry::AliEMCALGeometry(const AliEMCALGeometry& geom)
101 fGeoName(geom.fGeoName),
102 fArrayOpts(geom.fArrayOpts),
103 fAlFrontThick(geom.fAlFrontThick),
104 fECPbRadThickness(geom.fECPbRadThickness),
105 fECScintThick(geom.fECScintThick),
106 fNECLayers(geom.fNECLayers),
107 fArm1PhiMin(geom.fArm1PhiMin),
108 fArm1PhiMax(geom.fArm1PhiMax),
109 fArm1EtaMin(geom.fArm1EtaMin),
110 fArm1EtaMax(geom.fArm1EtaMax),
111 fIPDistance(geom.fIPDistance),
112 fShellThickness(geom.fShellThickness),
113 fZLength(geom.fZLength),
114 fGap2Active(geom.fGap2Active),
117 fSampling(geom.fSampling),
118 fNumberOfSuperModules(geom.fNumberOfSuperModules),
119 fSteelFrontThick(geom.fSteelFrontThick),
120 fFrontSteelStrip(geom.fFrontSteelStrip),
121 fLateralSteelStrip(geom.fLateralSteelStrip),
122 fPassiveScintThick(geom.fPassiveScintThick),
123 fPhiModuleSize(geom.fPhiModuleSize),
124 fEtaModuleSize(geom.fEtaModuleSize),
125 fPhiTileSize(geom.fPhiTileSize),
126 fEtaTileSize(geom.fEtaTileSize),
127 fLongModuleSize(geom.fLongModuleSize),
128 fNPhiSuperModule(geom.fNPhiSuperModule),
129 fNPHIdiv(geom.fNPHIdiv),
130 fNETAdiv(geom.fNETAdiv),
131 fNCells(geom.fNCells),
132 fNCellsInSupMod(geom.fNCellsInSupMod),
133 fNCellsInTower(geom.fNCellsInTower),
135 fNTRUEta(geom.fNTRUEta),
136 fNTRUPhi(geom.fNTRUPhi),
137 fTrd1Angle(geom.fTrd1Angle),
138 f2Trd1Dx2(geom.f2Trd1Dx2),
139 fPhiGapForSM(geom.fPhiGapForSM),
140 fKey110DEG(geom.fKey110DEG),
141 fTrd2AngleY(geom.fTrd2AngleY),
142 f2Trd2Dy2(geom.f2Trd2Dy2),
143 fEmptySpace(geom.fEmptySpace),
145 fTubsTurnAngle(geom.fTubsTurnAngle),
146 fEtaCentersOfCells(geom.fEtaCentersOfCells),
147 fXCentersOfCells(geom.fXCentersOfCells),
148 fPhiCentersOfCells(geom.fPhiCentersOfCells),
149 fShishKebabTrd1Modules(geom.fShishKebabTrd1Modules),
150 fNAdditionalOpts(geom.fNAdditionalOpts)
155 //______________________________________________________________________
156 AliEMCALGeometry::~AliEMCALGeometry(void){
159 //______________________________________________________________________
160 void AliEMCALGeometry::Init(void){
161 // Initializes the EMCAL parameters
162 // naming convention : GUV_WX_N_ gives the composition of a tower
163 // WX inform about the composition of the EM calorimeter section:
164 // thickness in mm of Pb radiator (W) and of scintillator (X), and number of scintillator layers (N)
165 // New geometry: EMCAL_55_25
166 // 24-aug-04 for shish-kebab
167 // SHISH_25 or SHISH_62
168 // 11-oct-05 - correction for pre final design
169 // Feb 06,2006 - decrease the weight of EMCAL
171 fAdditionalOpts[0] = "nl="; // number of sampling layers (fNECLayers)
172 fAdditionalOpts[1] = "pbTh="; // cm, Thickness of the Pb (fECPbRadThick)
173 fAdditionalOpts[2] = "scTh="; // cm, Thickness of the Sc (fECScintThick)
174 fAdditionalOpts[3] = "latSS="; // cm, Thickness of lateral steel strip (fLateralSteelStrip)
176 fNAdditionalOpts = sizeof(fAdditionalOpts) / sizeof(char*);
178 fgInit = kFALSE; // Assume failed until proven otherwise.
179 fGeoName = GetName();
182 if(fGeoName.Contains("110DEG")) fKey110DEG = 1; // for GetAbsCellId
183 fShishKebabTrd1Modules = 0;
184 fTrd2AngleY = f2Trd2Dy2 = fEmptySpace = fTubsR = fTubsTurnAngle = 0;
186 fNZ = 114; // granularity along Z (eta)
187 fNPhi = 168; // granularity in phi (azimuth)
188 fArm1PhiMin = 60.0; // degrees, Starting EMCAL Phi position
189 fArm1PhiMax = 180.0; // degrees, Ending EMCAL Phi position
190 fArm1EtaMin = -0.7; // pseudorapidity, Starting EMCAL Eta position
191 fArm1EtaMax = +0.7; // pseudorapidity, Ending EMCAL Eta position
192 fIPDistance = 454.0; // cm, Radial distance to inner surface of EMCAL
193 fPhiGapForSM = 0.; // cm, only for final TRD1 geometry
194 for(int i=0; i<12; i++) fMatrixOfSM[i] = 0;
197 if(fGeoName.Contains("SHISH")){ // Only shahslyk now
198 // 7-sep-05; integration issue
199 fArm1PhiMin = 80.0; // 60 -> 80
200 fArm1PhiMax = 180.0; // 180 -> 190
202 fNumberOfSuperModules = 10; // 12 = 6 * 2 (6 in phi, 2 in Z);
203 fSteelFrontThick = 2.54; // 9-sep-04
205 fFrontSteelStrip = fPassiveScintThick = 0.0; // 13-may-05
206 fLateralSteelStrip = 0.025; // before MAY 2005
207 fPhiModuleSize = fEtaModuleSize = 11.4;
208 fPhiTileSize = fEtaTileSize = 5.52; // (11.4-5.52*2)/2. = 0.18 cm (wall thickness)
211 fAlFrontThick = fGap2Active = 0;
212 fNPHIdiv = fNETAdiv = 2;
215 fECScintThick = fECPbRadThickness = 0.2;
216 fSampling = 1.; // 30-aug-04 - should be calculated
217 if(fGeoName.Contains("TWIST")) { // all about EMCAL module
218 fNZ = 27; // 16-sep-04
219 } else if(fGeoName.Contains("TRD")) {
220 fIPDistance = 428.0; // 11-may-05
221 fSteelFrontThick = 0.0; // 3.17 -> 0.0; 28-mar-05 : no stell plate
224 fPhiModuleSize = fEtaModuleSize = 12.26;
225 fNZ = 26; // 11-oct-04
226 fTrd1Angle = 1.3; // in degree
227 // 18-nov-04; 1./0.08112=12.327
228 // http://pdsfweb01.nersc.gov/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
229 if(fGeoName.Contains("TRD1")) { // 30-jan-05
231 fPhiGapForSM = 2.; // cm, only for final TRD1 geometry
232 if(fGeoName.Contains("MAY05") || fGeoName.Contains("WSUC") || fGeoName.Contains("FINAL")){
233 fNumberOfSuperModules = 12; // 20-may-05
234 if(fGeoName.Contains("WSUC")) fNumberOfSuperModules = 1; // 27-may-05
235 fNECLayers = 77; // (13-may-05 from V.Petrov)
236 fPhiModuleSize = 12.5; // 20-may-05 - rectangular shape
237 fEtaModuleSize = 11.9;
238 fECScintThick = fECPbRadThickness = 0.16;// (13-may-05 from V.Petrov)
239 fFrontSteelStrip = 0.025;// 0.025cm = 0.25mm (13-may-05 from V.Petrov)
240 fLateralSteelStrip = 0.01; // 0.01cm = 0.1mm (13-may-05 from V.Petrov) - was 0.025
241 fPassiveScintThick = 0.8; // 0.8cm = 8mm (13-may-05 from V.Petrov)
243 fTrd1Angle = 1.5; // 1.3 or 1.5
245 if(fGeoName.Contains("FINAL")) { // 9-sep-05
246 fNumberOfSuperModules = 10;
247 if(fGeoName.Contains("110DEG")) {
248 fNumberOfSuperModules = 12;// last two modules have size 10 degree in phi (180<phi<190)
249 fArm1PhiMax = 200.0; // for XEN1 and turn angle of super modules
251 fPhiModuleSize = 12.26 - fPhiGapForSM / Float_t(fNPhi); // first assumption
252 fEtaModuleSize = fPhiModuleSize;
253 if(fGeoName.Contains("HUGE")) fNECLayers *= 3; // 28-oct-05 for analysing leakage
256 } else if(fGeoName.Contains("TRD2")) { // 30-jan-05
257 fSteelFrontThick = 0.0; // 11-mar-05
258 fIPDistance+= fSteelFrontThick; // 1-feb-05 - compensate absence of steel plate
259 fTrd1Angle = 1.64; // 1.3->1.64
260 fTrd2AngleY = fTrd1Angle; // symmetric case now
261 fEmptySpace = 0.2; // 2 mm
262 fTubsR = fIPDistance; // 31-jan-05 - as for Fred case
264 fPhiModuleSize = fTubsR*2.*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
265 fPhiModuleSize -= fEmptySpace/2.; // 11-mar-05
266 fEtaModuleSize = fPhiModuleSize; // 20-may-05
269 fNPHIdiv = fNETAdiv = 2; // 13-oct-04 - division again
270 if(fGeoName.Contains("3X3")) { // 23-nov-04
271 fNPHIdiv = fNETAdiv = 3;
272 } else if(fGeoName.Contains("4X4")) {
273 fNPHIdiv = fNETAdiv = 4;
276 if(fGeoName.Contains("25")){
278 fECScintThick = fECPbRadThickness = 0.5;
280 if(fGeoName.Contains("WSUC")){ // 18-may-05 - about common structure
281 fShellThickness = 30.; // should be change
285 CheckAdditionalOptions();
286 DefineSamplingFraction();
288 fPhiTileSize = fPhiModuleSize/2. - fLateralSteelStrip; // 13-may-05
289 fEtaTileSize = fEtaModuleSize/2. - fLateralSteelStrip; // 13-may-05
291 // constant for transition absid <--> indexes
292 fNCellsInTower = fNPHIdiv*fNETAdiv;
293 fNCellsInSupMod = fNCellsInTower*fNPhi*fNZ;
294 fNCells = fNCellsInSupMod*fNumberOfSuperModules;
295 if(fGeoName.Contains("110DEG")) fNCells -= fNCellsInSupMod;
297 fLongModuleSize = fNECLayers*(fECScintThick + fECPbRadThickness);
298 if(fGeoName.Contains("MAY05")) fLongModuleSize += (fFrontSteelStrip + fPassiveScintThick);
301 if(fGeoName.Contains("TRD")) {
302 f2Trd1Dx2 = fEtaModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd1Angle*TMath::DegToRad()/2.);
303 if(fGeoName.Contains("TRD2")) { // 27-jan-05
304 f2Trd2Dy2 = fPhiModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd2AngleY*TMath::DegToRad()/2.);
307 } else Fatal("Init", "%s is an undefined geometry!", fGeoName.Data()) ;
309 fNPhiSuperModule = fNumberOfSuperModules/2;
310 if(fNPhiSuperModule<1) fNPhiSuperModule = 1;
311 //There is always one more scintillator than radiator layer because of the first block of aluminium
312 fShellThickness = fAlFrontThick + fGap2Active + fNECLayers*GetECScintThick()+(fNECLayers-1)*GetECPbRadThick();
313 if(fGeoName.Contains("SHISH")) {
314 fShellThickness = fSteelFrontThick + fLongModuleSize;
315 if(fGeoName.Contains("TWIST")) { // 13-sep-04
316 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + fPhiModuleSize*fEtaModuleSize);
317 fShellThickness += fSteelFrontThick;
318 } else if(fGeoName.Contains("TRD")) { // 1-oct-04
319 fShellThickness = TMath::Sqrt(fLongModuleSize*fLongModuleSize + f2Trd1Dx2*f2Trd1Dx2);
320 fShellThickness += fSteelFrontThick;
322 fParSM[0] = GetShellThickness()/2.;
323 fParSM[1] = GetPhiModuleSize() * GetNPhi()/2.;
328 fZLength = 2.*ZFromEtaR(fIPDistance+fShellThickness,fArm1EtaMax); // Z coverage
329 fEnvelop[0] = fIPDistance; // mother volume inner radius
330 fEnvelop[1] = fIPDistance + fShellThickness; // mother volume outer r.
331 fEnvelop[2] = 1.00001*fZLength; // add some padding for mother volume.
333 fNumberOfSuperModules = 12;
337 if (AliDebugLevel()>=2) {
338 printf("Init: geometry of EMCAL named %s is as follows:\n", fGeoName.Data());
339 printf( " ECAL : %d x (%f cm Pb, %f cm Sc) \n",
340 GetNECLayers(), GetECPbRadThick(), GetECScintThick() ) ;
341 printf(" fSampling %5.2f \n", fSampling );
342 if(fGeoName.Contains("SHISH")){
343 printf(" fIPDistance %6.3f cm \n", fIPDistance);
344 if(fSteelFrontThick>0.)
345 printf(" fSteelFrontThick %6.3f cm \n", fSteelFrontThick);
346 printf(" fNPhi %i | fNZ %i \n", fNPhi, fNZ);
347 printf(" fNCellsInTower %i : fNCellsInSupMod %i : fNCells %i\n",fNCellsInTower, fNCellsInSupMod, fNCells);
348 if(fGeoName.Contains("MAY05")){
349 printf(" fFrontSteelStrip %6.4f cm (thickness of front steel strip)\n",
351 printf(" fLateralSteelStrip %6.4f cm (thickness of lateral steel strip)\n",
353 printf(" fPassiveScintThick %6.4f cm (thickness of front passive Sc tile)\n",
356 printf(" X:Y module size %6.3f , %6.3f cm \n", fPhiModuleSize, fEtaModuleSize);
357 printf(" X:Y tile size %6.3f , %6.3f cm \n", fPhiTileSize, fEtaTileSize);
358 printf(" #of sampling layers %i(fNECLayers) \n", fNECLayers);
359 printf(" fLongModuleSize %6.3f cm \n", fLongModuleSize);
360 printf(" #supermodule in phi direction %i \n", fNPhiSuperModule );
362 if(fGeoName.Contains("TRD")) {
363 printf(" fTrd1Angle %7.4f\n", fTrd1Angle);
364 printf(" f2Trd1Dx2 %7.4f\n", f2Trd1Dx2);
365 if(fGeoName.Contains("TRD2")) {
366 printf(" fTrd2AngleY %7.4f\n", fTrd2AngleY);
367 printf(" f2Trd2Dy2 %7.4f\n", f2Trd2Dy2);
368 printf(" fTubsR %7.2f cm\n", fTubsR);
369 printf(" fTubsTurnAngle %7.4f\n", fTubsTurnAngle);
370 printf(" fEmptySpace %7.4f cm\n", fEmptySpace);
371 } else if(fGeoName.Contains("TRD1") && fGeoName.Contains("FINAL")){
372 printf("SM dimensions(TRD1) : dx %7.2f dy %7.2f dz %7.2f (SMOD, BOX)\n",
373 fParSM[0],fParSM[1],fParSM[2]);
374 printf(" fPhiGapForSM %7.4f cm \n", fPhiGapForSM);
375 if(fGeoName.Contains("110DEG"))printf(" Last two modules have size 10 degree in phi (180<phi<190)\n");
378 printf("Granularity: %d in eta and %d in phi\n", GetNZ(), GetNPhi()) ;
379 printf("Layout: phi = (%7.1f, %7.1f), eta = (%5.2f, %5.2f), IP = %7.2f\n",
380 GetArm1PhiMin(), GetArm1PhiMax(),GetArm1EtaMin(), GetArm1EtaMax(), GetIPDistance() );
382 //TRU parameters. These parameters values are not the final ones.
388 //______________________________________________________________________
390 void AliEMCALGeometry::CheckAdditionalOptions()
393 //Additional options that
394 //can be used to select
395 //the specific geometry of
398 fArrayOpts = new TObjArray;
399 Int_t nopt = AliEMCALHistoUtilities::ParseString(fGeoName, *fArrayOpts);
400 if(nopt==1) { // no aditional option(s)
401 fArrayOpts->Delete();
406 for(Int_t i=1; i<nopt; i++){
407 TObjString *o = (TObjString*)fArrayOpts->At(i);
409 TString addOpt = o->String();
411 for(Int_t j=0; j<fNAdditionalOpts; j++) {
412 TString opt = fAdditionalOpts[j];
413 if(addOpt.Contains(opt,TString::kIgnoreCase)) {
419 AliDebug(2,Form("<E> option |%s| unavailable : ** look to the file AliEMCALGeometry.h **\n",
423 AliDebug(2,Form("<I> option |%s| is valid : number %i : |%s|\n",
424 addOpt.Data(), indj, fAdditionalOpts[indj]));
425 if (addOpt.Contains("NL=",TString::kIgnoreCase)) {// number of sampling layers
426 sscanf(addOpt.Data(),"NL=%i", &fNECLayers);
427 AliDebug(2,Form(" fNECLayers %i (new) \n", fNECLayers));
428 } else if(addOpt.Contains("PBTH=",TString::kIgnoreCase)) {//Thickness of the Pb(fECPbRadThicknes)
429 sscanf(addOpt.Data(),"PBTH=%f", &fECPbRadThickness);
430 } else if(addOpt.Contains("SCTH=",TString::kIgnoreCase)) {//Thickness of the Sc(fECScintThick)
431 sscanf(addOpt.Data(),"SCTH=%f", &fECScintThick);
432 } else if(addOpt.Contains("LATSS=",TString::kIgnoreCase)) {// Thickness of lateral steel strip (fLateralSteelStrip)
433 sscanf(addOpt.Data(),"LATSS=%f", &fLateralSteelStrip);
434 AliDebug(2,Form(" fLateralSteelStrip %f (new) \n", fLateralSteelStrip));
440 void AliEMCALGeometry::DefineSamplingFraction()
443 // Look http://rhic.physics.wayne.edu/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
444 // Keep for compatibilty
446 if(fNECLayers == 69) { // 10% layer reduction
448 } else if(fNECLayers == 61) { // 20% layer reduction
450 } else if(fNECLayers == 77) {
451 if (fECScintThick>0.175 && fECScintThick<0.177) { // 10% Pb thicknes reduction
452 fSampling = 10.5; // fECScintThick = 0.176, fECPbRadThickness=0.144;
453 } else if(fECScintThick>0.191 && fECScintThick<0.193) { // 20% Pb thicknes reduction
454 fSampling = 8.93; // fECScintThick = 0.192, fECPbRadThickness=0.128;
459 //____________________________________________________________________________
460 void AliEMCALGeometry::FillTRU(const TClonesArray * digits, TClonesArray * ampmatrix, TClonesArray * timeRmatrix) {
463 // Orders digits ampitudes list in fNTRU TRUs (384 cells) per supermodule.
464 // Each TRU is a TMatrixD, and they are kept in TClonesArrays. The number of
465 // TRU in phi is fNTRUPhi, and the number of TRU in eta is fNTRUEta.
466 // Last 2 modules are half size in Phi, I considered that the number of TRU
467 // is maintained for the last modules but decision not taken. If different,
468 // then this must be changed.
473 if(fNTRUEta*fNTRUPhi != fNTRU)
474 Error("FillTRU"," Wrong number of TRUS per Eta or Phi");
476 //Initilize and declare variables
477 //List of TRU matrices initialized to 0.
478 Int_t nCellsPhi = fNPhi*2/fNTRUPhi;
479 Int_t nCellsPhi2 = fNPhi/fNTRUPhi; //HalfSize modules
480 Int_t nCellsEta = fNZ*2/fNTRUEta;
491 //List of TRU matrices initialized to 0.
492 for(Int_t k = 0; k < fNTRU*fNumberOfSuperModules; k++){
493 TMatrixD * amptrus = new TMatrixD(nCellsPhi,nCellsEta) ;
494 TMatrixD * timeRtrus = new TMatrixD(nCellsPhi,nCellsEta) ;
495 for(Int_t i = 0; i < nCellsPhi; i++){
496 for(Int_t j = 0; j < nCellsEta; j++){
497 (*amptrus)(i,j) = 0.0;
498 (*timeRtrus)(i,j) = 0.0;
501 new((*ampmatrix)[k]) TMatrixD(*amptrus) ;
502 new((*timeRmatrix)[k]) TMatrixD(*timeRtrus) ;
505 AliEMCALDigit * dig ;
507 //Digits loop to fill TRU matrices with amplitudes.
508 for(Int_t idig = 0 ; idig < digits->GetEntriesFast() ; idig++){
510 dig = dynamic_cast<AliEMCALDigit *>(digits->At(idig)) ;
511 amp = dig->GetAmp() ; // Energy of the digit (arbitrary units)
512 id = dig->GetId() ; // Id label of the cell
513 timeR = dig->GetTimeR() ; // Earliest time of the digit
515 //Get eta and phi cell position in supermodule
516 Bool_t bCell = GetCellIndex(id, iSupMod, nTower, nIphi, nIeta) ;
518 Error("FillTRU","Wrong cell id number") ;
520 GetCellPhiEtaIndexInSModule(iSupMod,nTower,nIphi, nIeta,iphi,ieta);
522 //Check to which TRU in the supermodule belongs the cell.
523 //Supermodules are divided in a TRU matrix of dimension
524 //(fNTRUPhi,fNTRUEta).
525 //Each TRU is a cell matrix of dimension (nCellsPhi,nCellsEta)
527 //First calculate the row and column in the supermodule
528 //of the TRU to which the cell belongs.
529 Int_t col = ieta/nCellsEta;
530 Int_t row = iphi/nCellsPhi;
532 row = iphi/nCellsPhi2;
533 //Calculate label number of the TRU
534 Int_t itru = row + col*fNTRUPhi + iSupMod*fNTRU ;
536 //Fill TRU matrix with cell values
537 TMatrixD * amptrus = dynamic_cast<TMatrixD *>(ampmatrix->At(itru)) ;
538 TMatrixD * timeRtrus = dynamic_cast<TMatrixD *>(timeRmatrix->At(itru)) ;
540 //Calculate row and column of the cell inside the TRU with number itru
541 Int_t irow = iphi - row * nCellsPhi;
543 irow = iphi - row * nCellsPhi2;
544 Int_t icol = ieta - col * nCellsEta;
546 (*amptrus)(irow,icol) = amp ;
547 (*timeRtrus)(irow,icol) = timeR ;
552 //______________________________________________________________________
553 void AliEMCALGeometry::GetCellPhiEtaIndexInSModuleFromTRUIndex(const Int_t itru, const Int_t iphitru, const Int_t ietatru, Int_t &iphiSM, Int_t &ietaSM) const
556 // This method transforms the (eta,phi) index of cells in a
557 // TRU matrix into Super Module (eta,phi) index.
559 // Calculate in which row and column where the TRU are
562 Int_t col = itru/ fNTRUPhi ;
563 Int_t row = itru - col*fNTRUPhi ;
565 //Calculate the (eta,phi) index in SM
566 Int_t nCellsPhi = fNPhi*2/fNTRUPhi;
567 Int_t nCellsEta = fNZ*2/fNTRUEta;
569 iphiSM = nCellsPhi*row + iphitru ;
570 ietaSM = nCellsEta*col + ietatru ;
573 //______________________________________________________________________
574 AliEMCALGeometry * AliEMCALGeometry::GetInstance(){
575 // Returns the pointer of the unique instance
577 AliEMCALGeometry * rv = static_cast<AliEMCALGeometry *>( fgGeom );
581 //______________________________________________________________________
582 AliEMCALGeometry* AliEMCALGeometry::GetInstance(const Text_t* name,
583 const Text_t* title){
584 // Returns the pointer of the unique instance
586 AliEMCALGeometry * rv = 0;
588 if ( strcmp(name,"") == 0 ) rv = 0;
590 fgGeom = new AliEMCALGeometry(name, title);
591 if ( fgInit ) rv = (AliEMCALGeometry * ) fgGeom;
597 } // end if strcmp(name,"")
599 if ( strcmp(fgGeom->GetName(), name) != 0) {
600 printf("\ncurrent geometry is %s : ", fgGeom->GetName());
601 printf(" you cannot call %s ", name);
603 rv = (AliEMCALGeometry *) fgGeom;
609 Bool_t AliEMCALGeometry::IsInEMCAL(Double_t x, Double_t y, Double_t z) const {
610 // Checks whether point is inside the EMCal volume, used in AliEMCALv*.cxx
612 // Code uses cylindrical approximation made of inner radius (for speed)
614 // Points behind EMCAl, i.e. R > outer radius, but eta, phi in acceptance
615 // are considered to inside
617 Double_t r=sqrt(x*x+y*y);
619 if ( r > fEnvelop[0] ) {
621 theta = TMath::ATan2(r,z);
626 eta = -TMath::Log(TMath::Tan(theta/2.));
627 if (eta < fArm1EtaMin || eta > fArm1EtaMax)
630 Double_t phi = TMath::ATan2(y,x) * 180./TMath::Pi();
631 if (phi > fArm1PhiMin && phi < fArm1PhiMax)
639 // == Shish-kebab cases ==
641 Int_t AliEMCALGeometry::GetAbsCellId(Int_t nSupMod, Int_t nTower, Int_t nIphi, Int_t nIeta) const
645 // 13-oct-05; 110 degree case
646 // May 31, 2006; ALICE numbering scheme:
647 // 0 <= nSupMod < fNumberOfSuperModules
648 // 0 <= nTower < fNPHI * fNZ ( fNPHI * fNZ/2 for fKey110DEG=1)
649 // 0 <= nIphi < fNPHIdiv
650 // 0 <= nIeta < fNETAdiv
651 // 0 <= absid < fNCells
652 static Int_t id=0; // have to change from 0 to fNCells-1
653 if(fKey110DEG == 1 && nSupMod >= 10) { // 110 degree case; last two supermodules
654 id = fNCellsInSupMod*10 + (fNCellsInSupMod/2)*(nSupMod-10);
656 id = fNCellsInSupMod*nSupMod;
658 id += fNCellsInTower *nTower;
659 id += fNPHIdiv *nIphi;
661 if(id<0 || id >= fNCells) {
662 // printf(" wrong numerations !!\n");
663 // printf(" id %6i(will be force to -1)\n", id);
664 // printf(" fNCells %6i\n", fNCells);
665 // printf(" nSupMod %6i\n", nSupMod);
666 // printf(" nTower %6i\n", nTower);
667 // printf(" nIphi %6i\n", nIphi);
668 // printf(" nIeta %6i\n", nIeta);
669 id = -TMath::Abs(id); // if negative something wrong
674 Bool_t AliEMCALGeometry::CheckAbsCellId(Int_t absId) const
676 // May 31, 2006; only trd1 now
677 if(absId<0 || absId >= fNCells) return kFALSE;
681 Bool_t AliEMCALGeometry::GetCellIndex(Int_t absId,Int_t &nSupMod,Int_t &nTower,Int_t &nIphi,Int_t &nIeta) const
683 // 21-sep-04; 19-oct-05;
684 // May 31, 2006; ALICE numbering scheme:
685 static Int_t tmp=0, sm10=0;
686 if(!CheckAbsCellId(absId)) return kFALSE;
688 sm10 = fNCellsInSupMod*10;
689 if(fKey110DEG == 1 && absId >= sm10) { // 110 degree case; last two supermodules
690 nSupMod = (absId-sm10) / (fNCellsInSupMod/2) + 10;
691 tmp = (absId-sm10) % (fNCellsInSupMod/2);
693 nSupMod = absId / fNCellsInSupMod;
694 tmp = absId % fNCellsInSupMod;
697 nTower = tmp / fNCellsInTower;
698 tmp = tmp % fNCellsInTower;
699 nIphi = tmp / fNPHIdiv;
700 nIeta = tmp % fNPHIdiv;
705 void AliEMCALGeometry::GetModulePhiEtaIndexInSModule(Int_t nSupMod, Int_t nTower, int &iphim, int &ietam) const
707 // added nSupMod; have to check - 19-oct-05 !
708 // Alice numbering scheme - Jun 01,2006
711 if(fKey110DEG == 1 && nSupMod>=10) nphi = fNPhi/2;
714 ietam = nTower/nphi; // have to change from 0 to fNZ-1
715 iphim = nTower%nphi; // have to change from 0 to fNPhi-1
718 void AliEMCALGeometry::GetCellPhiEtaIndexInSModule(Int_t nSupMod, Int_t nTower, Int_t nIphi, Int_t nIeta,
719 int &iphi, int &ieta) const
721 // added nSupMod; Nov 25, 05
722 // Alice numbering scheme - Jun 01,2006
723 static Int_t iphim, ietam;
725 GetModulePhiEtaIndexInSModule(nSupMod,nTower, iphim, ietam);
726 // have to change from 0 to (fNZ*fNETAdiv-1)
727 ieta = ietam*fNETAdiv + (1-nIeta); // x(module) = -z(SM)
728 // iphi - have to change from 0 to (fNPhi*fNPHIdiv-1)
729 iphi = iphim*fNPHIdiv + nIphi; // y(module) = y(SM)
732 Int_t AliEMCALGeometry::GetSuperModuleNumber(Int_t absId) const
734 //return the number of the
735 //supermodule given the absolute
738 static Int_t nSupMod, nTower, nIphi, nIeta;
739 GetCellIndex(absId, nSupMod, nTower, nIphi, nIeta);
743 // Methods for AliEMCALRecPoint - Feb 19, 2006
744 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t &xr, Double_t &yr, Double_t &zr) const
746 // Look to see what the relative
747 // position inside a given cell is
749 // Alice numbering scheme - Jun 08, 2006
751 static Int_t nSupMod, nTower, nIphi, nIeta, iphi, ieta;
752 static Int_t phiIndexShift=6;
753 if(!CheckAbsCellId(absId)) return kFALSE;
755 GetCellIndex(absId, nSupMod, nTower, nIphi, nIeta);
756 GetCellPhiEtaIndexInSModule(nSupMod,nTower,nIphi,nIeta, iphi, ieta);
758 xr = fXCentersOfCells.At(ieta);
759 zr = fEtaCentersOfCells.At(ieta);
762 yr = fPhiCentersOfCells.At(iphi);
764 yr = fPhiCentersOfCells.At(iphi + phiIndexShift);
765 // cout<<" absId "<<absId<<" nSupMod "<<nSupMod << " iphi "<<iphi<<" ieta "<<ieta;
766 // cout<< " xr " << xr << " yr " << yr << " zr " << zr <<endl;
772 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t loc[3]) const
774 // Alice numbering scheme - Jun 03, 2006
775 loc[0] = loc[1] = loc[2]=0.0;
776 if(RelPosCellInSModule(absId, loc[0],loc[1],loc[2])) {
782 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, TVector3 &vloc) const
784 static Double_t loc[3];
785 if(RelPosCellInSModule(absId,loc)) {
786 vloc.SetXYZ(loc[0], loc[1], loc[2]);
792 // Alice numbering scheme - Jun 03, 2006
795 void AliEMCALGeometry::CreateListOfTrd1Modules()
797 //Generate the list of Trd1 modules
798 //which will make up the EMCAL
801 AliDebug(2,Form(" AliEMCALGeometry::CreateListOfTrd1Modules() started "));
803 AliEMCALShishKebabTrd1Module *mod=0, *mTmp=0; // current module
804 if(fShishKebabTrd1Modules == 0) {
805 fShishKebabTrd1Modules = new TList;
806 for(int iz=0; iz< GetNZ(); iz++) {
808 mod = new AliEMCALShishKebabTrd1Module(TMath::Pi()/2.,this);
810 mTmp = new AliEMCALShishKebabTrd1Module(*mod);
813 fShishKebabTrd1Modules->Add(mod);
816 AliDebug(2,Form(" Already exits : "));
818 AliDebug(2,Form(" fShishKebabTrd1Modules has %i modules \n",
819 fShishKebabTrd1Modules->GetSize()));
821 // Jun 01, 2006 - ALICE numbering scheme
822 // define grid for cells in eta(z) and x directions in local coordinates system of SM
823 // fEtaCentersOfCells = new TArrayD(fNZ *fNETAdiv);
824 // fXCentersOfCells = new TArrayD(fNZ *fNETAdiv);
825 fEtaCentersOfCells.Set(fNZ *fNETAdiv);
826 fXCentersOfCells.Set(fNZ *fNETAdiv);
827 AliDebug(2,Form(" Cells grid in eta directions : size %i\n", fEtaCentersOfCells.GetSize()));
828 Int_t iphi=0, ieta=0, nTower=0;
830 for(Int_t it=0; it<fNZ; it++) { // array index
831 AliEMCALShishKebabTrd1Module *trd1 = GetShishKebabModule(it);
833 for(Int_t ic=0; ic<fNETAdiv; ic++) { // array index
834 trd1->GetCenterOfCellInLocalCoordinateofSM(ic, xr, zr);
835 GetCellPhiEtaIndexInSModule(0, nTower, 0, ic, iphi, ieta); // don't depend from phi - ieta in action
836 fXCentersOfCells.AddAt(float(xr) - fParSM[0],ieta);
837 fEtaCentersOfCells.AddAt(float(zr) - fParSM[2],ieta);
840 for(Int_t i=0; i<fEtaCentersOfCells.GetSize(); i++) {
841 AliDebug(2,Form(" ind %2.2i : z %8.3f : x %8.3f", i+1,
842 fEtaCentersOfCells.At(i),fXCentersOfCells.At(i)));
845 // define grid for cells in phi(y) direction in local coordinates system of SM
846 // fPhiCentersOfCells = new TArrayD(fNPhi*fNPHIdiv);
847 fPhiCentersOfCells.Set(fNPhi*fNPHIdiv);
848 AliDebug(2,Form(" Cells grid in phi directions : size %i\n", fPhiCentersOfCells.GetSize()));
850 for(Int_t it=0; it<fNPhi; it++) { // array index
851 Float_t ytLeftCenterModule = -fParSM[1] + fPhiModuleSize*(2*it+1)/2; // module
852 for(Int_t ic=0; ic<fNPHIdiv; ic++) { // array index
853 Float_t ytLeftCenterCell = ytLeftCenterModule + fPhiTileSize *(2*ic-1)/2.; // tower(cell)
854 fPhiCentersOfCells.AddAt(ytLeftCenterCell,ind);
855 AliDebug(2,Form(" ind %2.2i : y %8.3f ", ind, fPhiCentersOfCells.At(ind)));
861 void AliEMCALGeometry::GetTransformationForSM()
863 //Uses the geometry manager to
864 //load the transformation matrix
865 //for the supermodules
867 static Bool_t transInit=kFALSE;
868 if(transInit) return;
871 if(gGeoManager == 0) {
872 Info("CreateTransformationForSM() "," Load geometry : TGeoManager::Import()");
875 TGeoNode *tn = gGeoManager->GetTopNode();
876 TGeoNode *node=0, *xen1 = 0;
877 for(i=0; i<tn->GetNdaughters(); i++) {
878 node = tn->GetDaughter(i);
879 TString ns(node->GetName());
880 if(ns.Contains(GetNameOfEMCALEnvelope())) {
886 Info("CreateTransformationForSM() "," geometry has not EMCAL envelope with name %s",
887 GetNameOfEMCALEnvelope());
890 printf(" i %i : EMCAL Envelope is %s : #SM %i \n", i, xen1->GetName(), xen1->GetNdaughters());
891 for(i=0; i<xen1->GetNdaughters(); i++) {
892 TGeoNodeMatrix *sm = (TGeoNodeMatrix*)xen1->GetDaughter(i);
893 fMatrixOfSM[i] = sm->GetMatrix();
894 //Compiler doesn't like this syntax...
895 // printf(" %i : matrix %x \n", i, fMatrixOfSM[i]);
900 void AliEMCALGeometry::GetGlobal(const Double_t *loc, Double_t *glob, int ind) const
902 // Figure out the global numbering
903 // of a given supermodule from the
905 // Alice numbering - Jun 03,2006
906 // if(fMatrixOfSM[0] == 0) GetTransformationForSM();
908 if(ind>=0 && ind < GetNumberOfSuperModules()) {
909 fMatrixOfSM[ind]->LocalToMaster(loc, glob);
913 void AliEMCALGeometry::GetGlobal(const TVector3 &vloc, TVector3 &vglob, int ind) const
915 //Figure out the global numbering
916 //of a given supermodule from the
917 //local numbering given a 3-vector location
919 static Double_t tglob[3], tloc[3];
921 GetGlobal(tloc, tglob, ind);
922 vglob.SetXYZ(tglob[0], tglob[1], tglob[2]);
925 void AliEMCALGeometry::GetGlobal(Int_t absId , double glob[3]) const
927 // Alice numbering scheme - Jun 03, 2006
928 static Int_t nSupMod, nModule, nIphi, nIeta;
929 static double loc[3];
931 glob[0]=glob[1]=glob[2]=0.0; // bad case
932 if(RelPosCellInSModule(absId, loc)) {
933 GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
934 fMatrixOfSM[nSupMod]->LocalToMaster(loc, glob);
938 void AliEMCALGeometry::GetGlobal(Int_t absId , TVector3 &vglob) const
940 // Alice numbering scheme - Jun 03, 2006
941 static Double_t glob[3];
943 GetGlobal(absId, glob);
944 vglob.SetXYZ(glob[0], glob[1], glob[2]);
948 void AliEMCALGeometry::GetGlobal(const AliRecPoint *rp, TVector3 &vglob) const
950 // Figure out the global numbering
951 // of a given supermodule from the
952 // local numbering for RecPoints
954 static TVector3 vloc;
955 static Int_t nSupMod, nModule, nIphi, nIeta;
957 AliRecPoint *rpTmp = (AliRecPoint*)rp; // const_cast ??
959 AliEMCALRecPoint *rpEmc = (AliEMCALRecPoint*)rpTmp;
961 GetCellIndex(rpEmc->GetAbsId(0), nSupMod, nModule, nIphi, nIeta);
962 rpTmp->GetLocalPosition(vloc);
963 GetGlobal(vloc, vglob, nSupMod);
966 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Float_t &eta,Float_t &phi) const
968 // Jun 03, 2006 - version for TRD1
969 static TVector3 vglob;
970 GetGlobal(absId, vglob);
975 AliEMCALShishKebabTrd1Module* AliEMCALGeometry::GetShishKebabModule(Int_t neta=0)
977 //This method was too long to be
978 //included in the header file - the
979 //rule checker complained about it's
980 //length, so we move it here. It returns the
981 //shishkebabmodule at a given eta index point.
983 static AliEMCALShishKebabTrd1Module* trd1=0;
984 if(fShishKebabTrd1Modules && neta>=0 && neta<fShishKebabTrd1Modules->GetSize()) {
985 trd1 = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(neta);