]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/AliEMCALGeometry.cxx
Minor fix in comment line
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALGeometry.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 /* $Id$*/
17
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
23 // -0.7 to 0.7 in eta 
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)
28 //     Indexes
29 //     absId -> nSupMod     -> nModule -> (nIphi,nIeta)
30 //
31 //*-- Author: Sahal Yacoob (LBL / UCT)
32 //     and  : Yves Schutz (SUBATECH)
33 //     and  : Jennifer Klay (LBL)
34 //     SHASHLYK : Aleksei Pavlinov (WSU) 
35 //
36
37 #include <assert.h>
38
39 // --- Root header files ---
40 #include <Riostream.h>
41 #include <TBrowser.h>
42 #include <TClonesArray.h>
43 #include <TGeoManager.h>
44 #include <TGeoMatrix.h>
45 #include <TGeoNode.h>
46 #include <TList.h>
47 #include <TMatrixD.h>
48 #include <TObjArray.h>
49 #include <TObjString.h>
50 #include <TVector2.h>
51 #include <TVector3.h>
52
53 // -- ALICE Headers.
54 #include "AliLog.h"
55
56 // --- EMCAL headers
57 #include "AliEMCALGeometry.h"
58 #include "AliEMCALShishKebabTrd1Module.h"
59 #include "AliEMCALRecPoint.h"
60 #include "AliEMCALDigit.h"
61 #include "AliEMCALHistoUtilities.h"
62
63 ClassImp(AliEMCALGeometry)
64
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 scTh=0.176 pbTh=0.144";
69 //
70 // Usage: 
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.
74 //         
75 //  AliEMCALGeometry* g = AliEMCALGeometry::GetInstance(name,title); // first time
76 //  ..
77 //  g = AliEMCALGeometry::GetInstance();                             // after first time
78 //
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();
83 // TGeoManager::Import("geometry.root");
84
85 AliEMCALGeometry::AliEMCALGeometry() 
86   : AliGeometry(),
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) 
99
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 ");
104 }
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) 
120 {
121   // ctor only for internal usage (singleton)
122   AliDebug(2, Form("AliEMCALGeometry(%s,%s) ", name,title));
123
124   Init();
125
126   CreateListOfTrd1Modules();
127
128   if (AliDebugLevel()>=2) {
129     PrintGeometry();
130   }
131
132 }
133 //______________________________________________________________________
134 AliEMCALGeometry::AliEMCALGeometry(const AliEMCALGeometry& geom)
135   : AliGeometry(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),
150     fNZ(geom.fNZ),
151     fNPhi(geom.fNPhi),
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),
183     fTubsR(geom.fTubsR),
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) 
193 {
194   //copy ctor
195 }
196
197 //______________________________________________________________________
198 AliEMCALGeometry::~AliEMCALGeometry(void){
199     // dtor
200 }
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
212   //
213   // Oct 30,2006 - SHISH_TRD1_CURRENT_1X1, SHISH_TRD1_CURRENT_2X2 or SHISH_TRD1_CURRENT_3X3;
214   //
215
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)
222
223   fNAdditionalOpts = sizeof(fAdditionalOpts) / sizeof(char*);
224
225   fgInit = kFALSE; // Assume failed until proven otherwise.
226   fGeoName   = GetName();
227   fGeoName.ToUpper();
228   fKey110DEG = 0;
229   if(fGeoName.Contains("110DEG") || fGeoName.Contains("CURRENT")) fKey110DEG = 1; // for GetAbsCellId
230   fShishKebabTrd1Modules = 0;
231   fTrd2AngleY = f2Trd2Dy2 = fEmptySpace = fTubsR = fTubsTurnAngle = 0;
232
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
242   // geometry
243   if(fGeoName.Contains("SHISH")){ // Only shahslyk now
244     // 7-sep-05; integration issue
245     fArm1PhiMin     = 80.0;     // 60  -> 80
246     fArm1PhiMax     = 180.0;    // 180 -> 190
247
248     fNumberOfSuperModules = 10; // 12 = 6 * 2 (6 in phi, 2 in Z);
249     fSteelFrontThick = 2.54;    //  9-sep-04
250     fIPDistance      = 460.0;
251     fFrontSteelStrip = fPassiveScintThick = 0.0; // 13-may-05
252     fLateralSteelStrip = 0.025; // before MAY 2005 
253     fPhiModuleSize   = fEtaModuleSize   = 11.4;
254     fPhiTileSize = fEtaTileSize      = 5.52; // (11.4-5.52*2)/2. = 0.18 cm (wall thickness)
255     fNPhi            = 14;
256     fNZ              = 30;
257     fAlFrontThick    = fGap2Active = 0;
258     fNPHIdiv = fNETAdiv = 2;
259
260     fNECLayers       = 62;
261     fECScintThick    = fECPbRadThickness = 0.2;
262     fSampling        = 1.;  // 30-aug-04 - should be calculated
263     if(fGeoName.Contains("TWIST")) { // all about EMCAL module
264       fNZ             = 27;  // 16-sep-04
265     } else if(fGeoName.Contains("TRD")) {
266       fIPDistance      = 428.0;  //  11-may-05
267       fSteelFrontThick = 0.0;    // 3.17 -> 0.0; 28-mar-05 : no stell plate
268       fNPhi            = 12;
269       fSampling       = 12.327;
270       fPhiModuleSize = fEtaModuleSize = 12.26;
271       fNZ            = 26;     // 11-oct-04
272       fTrd1Angle     = 1.3;    // in degree
273 // 18-nov-04; 1./0.08112=12.327
274 // http://pdsfweb01.nersc.gov/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
275       if(fGeoName.Contains("TRD1")) {       // 30-jan-05
276         // for final design
277         fPhiGapForSM    = 2.;         // cm, only for final TRD1 geometry
278         if(fGeoName.Contains("MAY05") || fGeoName.Contains("WSUC") || fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")){
279           fNumberOfSuperModules = 12; // 20-may-05
280           if(fGeoName.Contains("WSUC")) fNumberOfSuperModules = 1; // 27-may-05
281           fNECLayers     = 77;       // (13-may-05 from V.Petrov)
282           fPhiModuleSize = 12.5;     // 20-may-05 - rectangular shape
283           fEtaModuleSize = 11.9;
284           fECScintThick  = fECPbRadThickness = 0.16;// (13-may-05 from V.Petrov)
285           fFrontSteelStrip   = 0.025;// 0.025cm = 0.25mm  (13-may-05 from V.Petrov)
286           fLateralSteelStrip = 0.01; // 0.01cm  = 0.1mm   (13-may-05 from V.Petrov) - was 0.025
287           fPassiveScintThick = 0.8;  // 0.8cm   = 8mm     (13-may-05 from V.Petrov)
288           fNZ                = 24;
289           fTrd1Angle         = 1.5;  // 1.3 or 1.5
290
291           if(fGeoName.Contains("FINAL") || fGeoName.Contains("CURRENT")) { // 9-sep-05
292             fNumberOfSuperModules = 10;
293             if(GetKey110DEG()) {
294               fNumberOfSuperModules = 12;// last two modules have size 10 degree in phi (180<phi<190)
295               fArm1PhiMax = 200.0;       // for XEN1 and turn angle of super modules
296             }
297             if(fGeoName.Contains("FINAL")) {
298               fPhiModuleSize = 12.26 - fPhiGapForSM / Float_t(fNPhi); // first assumption
299             } else if(fGeoName.Contains("CURRENT")) {
300               fECScintThick      = 0.176; // 10% of weight reduction
301               fECPbRadThickness  = 0.144; //
302               fLateralSteelStrip = 0.015; // 0.015cm  = 0.15mm (Oct 30, from Fred)
303               fPhiModuleSize     = 12.00;
304               fPhiGapForSM       = (12.26 - fPhiModuleSize)*fNPhi; // have to check
305             }
306             fEtaModuleSize = fPhiModuleSize;
307             if(fGeoName.Contains("HUGE")) fNECLayers *= 3; // 28-oct-05 for analysing leakage    
308           }
309         }
310       }
311       fNPHIdiv = fNETAdiv  = 2;   // 13-oct-04 - division again
312       if(fGeoName.Contains("3X3")) {   // 23-nov-04
313         fNPHIdiv = fNETAdiv  = 3;
314       } else if(fGeoName.Contains("4X4")) {
315         fNPHIdiv = fNETAdiv  = 4;
316       } else if(fGeoName.Contains("1X1")) {
317         fNPHIdiv = fNETAdiv  = 1;
318       }
319     }
320     if(fGeoName.Contains("25")){
321       fNECLayers     = 25;
322       fECScintThick  = fECPbRadThickness = 0.5;
323     }
324     if(fGeoName.Contains("WSUC")){ // 18-may-05 - about common structure
325       fShellThickness = 30.;       // should be change 
326       fNPhi = fNZ = 4; 
327     }
328
329     CheckAdditionalOptions();
330     DefineSamplingFraction();
331
332     fPhiTileSize = fPhiModuleSize/double(fNPHIdiv) - fLateralSteelStrip; // 13-may-05 
333     fEtaTileSize = fEtaModuleSize/double(fNETAdiv) - fLateralSteelStrip; // 13-may-05 
334
335     // constant for transition absid <--> indexes
336     fNCellsInModule  = fNPHIdiv*fNETAdiv;
337     fNCellsInSupMod = fNCellsInModule*fNPhi*fNZ;
338     fNCells         = fNCellsInSupMod*fNumberOfSuperModules;
339     if(GetKey110DEG()) fNCells -= fNCellsInSupMod;
340
341     fLongModuleSize = fNECLayers*(fECScintThick + fECPbRadThickness);
342     if(fGeoName.Contains("MAY05")) fLongModuleSize += (fFrontSteelStrip + fPassiveScintThick);
343
344     // 30-sep-04
345     if(fGeoName.Contains("TRD")) {
346       f2Trd1Dx2 = fEtaModuleSize + 2.*fLongModuleSize*TMath::Tan(fTrd1Angle*TMath::DegToRad()/2.);
347     }
348   } else Fatal("Init", "%s is an undefined geometry!", fGeoName.Data()) ; 
349
350   fNPhiSuperModule = fNumberOfSuperModules/2;
351   if(fNPhiSuperModule<1) fNPhiSuperModule = 1;
352
353   fShellThickness = fAlFrontThick + fGap2Active + fNECLayers*GetECScintThick()+(fNECLayers-1)*GetECPbRadThick();
354   if(fGeoName.Contains("SHISH")) {
355     fShellThickness = fSteelFrontThick + fLongModuleSize;
356     if(fGeoName.Contains("TWIST")) { // 13-sep-04
357       fShellThickness  = TMath::Sqrt(fLongModuleSize*fLongModuleSize + fPhiModuleSize*fEtaModuleSize);
358       fShellThickness += fSteelFrontThick;
359     } else if(fGeoName.Contains("TRD")) { // 1-oct-04
360       fShellThickness  = TMath::Sqrt(fLongModuleSize*fLongModuleSize + f2Trd1Dx2*f2Trd1Dx2);
361       fShellThickness += fSteelFrontThick;
362       // Local coordinates
363       fParSM[0] = GetShellThickness()/2.;        
364       fParSM[1] = GetPhiModuleSize() * GetNPhi()/2.;
365       fParSM[2] = 350./2.;
366     }
367   }
368
369   fZLength        = 2.*ZFromEtaR(fIPDistance+fShellThickness,fArm1EtaMax); // Z coverage
370   fEnvelop[0]     = fIPDistance; // mother volume inner radius
371   fEnvelop[1]     = fIPDistance + fShellThickness; // mother volume outer r.
372   fEnvelop[2]     = 1.00001*fZLength; // add some padding for mother volume. 
373
374   fNumberOfSuperModules = 12;
375
376   // SM phi boundaries - (0,1),(2,3) .. (10,11) - has the same boundaries; Nov 7, 2006 
377   fPhiBoundariesOfSM.Set(fNumberOfSuperModules);
378   fPhiCentersOfSM.Set(fNumberOfSuperModules/2);
379   fPhiBoundariesOfSM[0] = TMath::PiOver2() - TMath::ATan2(fParSM[1] , fIPDistance); // 1th and 2th modules)
380   fPhiBoundariesOfSM[1] = TMath::PiOver2() + TMath::ATan2(fParSM[1] , fIPDistance);
381   fPhiCentersOfSM[0]     = TMath::PiOver2();
382   for(int i=1; i<=4; i++) { // from 2th ro 9th
383     fPhiBoundariesOfSM[2*i]   = fPhiBoundariesOfSM[0] + 20.*TMath::DegToRad()*i;
384     fPhiBoundariesOfSM[2*i+1] = fPhiBoundariesOfSM[1] + 20.*TMath::DegToRad()*i;
385     fPhiCentersOfSM[i]         = fPhiCentersOfSM[0]     + 20.*TMath::DegToRad()*i;
386   }
387   fPhiBoundariesOfSM[11] = 190.*TMath::DegToRad();
388   fPhiBoundariesOfSM[10] = fPhiBoundariesOfSM[11] - TMath::ATan2((fParSM[1]) , fIPDistance);
389   fPhiCentersOfSM[5]      = (fPhiBoundariesOfSM[10]+fPhiBoundariesOfSM[11])/2.; 
390
391   //TRU parameters. These parameters values are not the final ones.
392   fNTRUEta = 3 ;
393   fNTRUPhi = 1 ;
394   fNCellsInTRUEta = 16 ;
395   fNCellsInTRUPhi = 24 ;
396
397   if(fGeoName.Contains("WSUC")) fNumberOfSuperModules = 1; // Jul 12, 2007
398
399   fgInit = kTRUE; 
400 }
401
402 void AliEMCALGeometry::PrintGeometry()
403 {
404   // Separate routine is callable from broswer; Nov 7,2006
405   printf("\nInit: geometry of EMCAL named %s :\n", fGeoName.Data());
406   if(fArrayOpts) {
407     for(Int_t i=0; i<fArrayOpts->GetEntries(); i++){
408       TObjString *o = (TObjString*)fArrayOpts->At(i);
409       printf(" %i : %s \n", i, o->String().Data());
410     }
411   }
412   printf("Granularity: %d in eta and %d in phi\n", GetNZ(), GetNPhi()) ;
413   printf("Layout: phi = (%7.1f, %7.1f), eta = (%5.2f, %5.2f), IP = %7.2f -> for EMCAL envelope only\n",  
414            GetArm1PhiMin(), GetArm1PhiMax(),GetArm1EtaMin(), GetArm1EtaMax(), GetIPDistance() );
415
416   printf( "               ECAL      : %d x (%f cm Pb, %f cm Sc) \n", 
417   GetNECLayers(), GetECPbRadThick(), GetECScintThick() ) ; 
418   printf("                fSampling %5.2f \n",  fSampling );
419   if(fGeoName.Contains("SHISH")){
420     printf(" fIPDistance       %6.3f cm \n", fIPDistance);
421     if(fSteelFrontThick>0.) 
422     printf(" fSteelFrontThick  %6.3f cm \n", fSteelFrontThick);
423     printf(" fNPhi %i   |  fNZ %i \n", fNPhi, fNZ);
424     printf(" fNCellsInModule %i : fNCellsInSupMod %i : fNCells %i\n",fNCellsInModule, fNCellsInSupMod, fNCells);
425     if(fGeoName.Contains("MAY05")){
426       printf(" fFrontSteelStrip         %6.4f cm (thickness of front steel strip)\n", 
427       fFrontSteelStrip);
428       printf(" fLateralSteelStrip       %6.4f cm (thickness of lateral steel strip)\n", 
429       fLateralSteelStrip);
430       printf(" fPassiveScintThick  %6.4f cm (thickness of front passive Sc tile)\n",
431       fPassiveScintThick);
432     }
433     printf(" X:Y module size     %6.3f , %6.3f cm \n", fPhiModuleSize, fEtaModuleSize);
434     printf(" X:Y   tile size     %6.3f , %6.3f cm \n", fPhiTileSize, fEtaTileSize);
435     printf(" #of sampling layers %i(fNECLayers) \n", fNECLayers);
436     printf(" fLongModuleSize     %6.3f cm \n", fLongModuleSize);
437     printf(" #supermodule in phi direction %i \n", fNPhiSuperModule );
438   }
439   printf(" fILOSS %i : fIHADR %i \n", fILOSS, fIHADR);
440   if(fGeoName.Contains("TRD")) {
441     printf(" fTrd1Angle %7.4f\n", fTrd1Angle);
442     printf(" f2Trd1Dx2  %7.4f\n",  f2Trd1Dx2);
443     if(fGeoName.Contains("TRD1")){
444       printf("SM dimensions(TRD1) : dx %7.2f dy %7.2f dz %7.2f (SMOD, BOX)\n", 
445       fParSM[0],fParSM[1],fParSM[2]);
446       printf(" fPhiGapForSM  %7.4f cm (%7.4f <- phi size in degree)\n",  
447       fPhiGapForSM, TMath::ATan2(fPhiGapForSM,fIPDistance)*TMath::RadToDeg());
448       if(GetKey110DEG()) printf(" Last two modules have size 10 degree in  phi (180<phi<190)\n");
449       printf(" phi SM boundaries \n"); 
450       for(int i=0; i<fPhiBoundariesOfSM.GetSize()/2.; i++) {
451         printf(" %i : %7.5f(%7.2f) -> %7.5f(%7.2f) : center %7.5f(%7.2f) \n", i, 
452         fPhiBoundariesOfSM[2*i], fPhiBoundariesOfSM[2*i]*TMath::RadToDeg(),
453                fPhiBoundariesOfSM[2*i+1], fPhiBoundariesOfSM[2*i+1]*TMath::RadToDeg(),
454                fPhiCentersOfSM[i], fPhiCentersOfSM[i]*TMath::RadToDeg());
455       }
456       printf(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n", 
457                fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1);
458
459       printf("\n Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize());
460       for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
461         printf(" ind %2.2i : z %8.3f : x %8.3f \n", i, 
462                fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i));
463         int ind=0; // Nov 21,2006
464         for(Int_t iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
465           ind = iphi*fCentersOfCellsEtaDir.GetSize() + i;
466           printf("%6.4f ", fEtaCentersOfCells[ind]);
467           if((iphi+1)%12 == 0) printf("\n");
468         }
469         printf("\n");
470
471       }
472
473       printf("\n Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize());
474       for(Int_t i=0; i<fCentersOfCellsPhiDir.GetSize(); i++) {
475         double phi=fPhiCentersOfCells.At(i);
476         printf(" ind %2.2i : y %8.3f : phi %7.5f(%6.2f) \n", i, fCentersOfCellsPhiDir.At(i), 
477                phi, phi*TMath::RadToDeg());
478       }
479     }
480   }
481 }
482
483 void AliEMCALGeometry::PrintCellIndexes(Int_t absId, int pri, char *tit)
484 {
485   // Service methods
486   Int_t nSupMod, nModule, nIphi, nIeta;
487   Int_t iphi, ieta;
488   TVector3 vg;
489
490   GetCellIndex(absId,  nSupMod, nModule, nIphi, nIeta);
491   printf(" %s | absId : %i -> nSupMod %i nModule %i nIphi %i nIeta %i \n", tit, absId,  nSupMod, nModule, nIphi, nIeta);
492   if(pri>0) {
493     GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi,ieta);
494     printf(" local SM index : iphi %i : ieta %i \n", iphi,ieta);
495     GetGlobal(absId, vg);
496     printf(" vglob : mag %7.2f : perp %7.2f : z %7.2f : eta %6.4f : phi %6.4f(%6.2f) \n", 
497            vg.Mag(), vg.Perp(), vg.Z(), vg.Eta(), vg.Phi(), vg.Phi()*TMath::RadToDeg());
498   }
499 }
500
501 //______________________________________________________________________
502 void AliEMCALGeometry::CheckAdditionalOptions()
503 {
504   // Feb 06,2006
505   // Additional options that
506   // can be used to select
507   // the specific geometry of 
508   // EMCAL to run
509   // Dec 27,2006
510   // adeed allILOSS= and allIHADR= for MIP investigation
511   fArrayOpts = new TObjArray;
512   Int_t nopt = AliEMCALHistoUtilities::ParseString(fGeoName, *fArrayOpts);
513   if(nopt==1) { // no aditional option(s)
514     fArrayOpts->Delete();
515     delete fArrayOpts;
516     fArrayOpts = 0; 
517     return;
518   }              
519   for(Int_t i=1; i<nopt; i++){
520     TObjString *o = (TObjString*)fArrayOpts->At(i); 
521
522     TString addOpt = o->String();
523     Int_t indj=-1;
524     for(Int_t j=0; j<fNAdditionalOpts; j++) {
525       TString opt = fAdditionalOpts[j];
526       if(addOpt.Contains(opt,TString::kIgnoreCase)) {
527           indj = j;
528         break;
529       }
530     }
531     if(indj<0) {
532       AliDebug(2,Form("<E> option |%s| unavailable : ** look to the file AliEMCALGeometry.h **\n", 
533                       addOpt.Data()));
534       assert(0);
535     } else {
536       AliDebug(2,Form("<I> option |%s| is valid : number %i : |%s|\n", 
537                       addOpt.Data(), indj, fAdditionalOpts[indj]));
538       if       (addOpt.Contains("NL=",TString::kIgnoreCase))   {// number of sampling layers
539         sscanf(addOpt.Data(),"NL=%i", &fNECLayers);
540         AliDebug(2,Form(" fNECLayers %i (new) \n", fNECLayers));
541       } else if(addOpt.Contains("PBTH=",TString::kIgnoreCase)) {//Thickness of the Pb(fECPbRadThicknes)
542         sscanf(addOpt.Data(),"PBTH=%f", &fECPbRadThickness);
543       } else if(addOpt.Contains("SCTH=",TString::kIgnoreCase)) {//Thickness of the Sc(fECScintThick)
544         sscanf(addOpt.Data(),"SCTH=%f", &fECScintThick);
545       } else if(addOpt.Contains("LATSS=",TString::kIgnoreCase)) {// Thickness of lateral steel strip (fLateralSteelStrip)
546         sscanf(addOpt.Data(),"LATSS=%f", &fLateralSteelStrip);
547         AliDebug(2,Form(" fLateralSteelStrip %f (new) \n", fLateralSteelStrip));
548       } else if(addOpt.Contains("ILOSS=",TString::kIgnoreCase)) {// As in Geant
549         sscanf(addOpt.Data(),"ALLILOSS=%i", &fILOSS);
550         AliDebug(2,Form(" fILOSS %i \n", fILOSS));
551       } else if(addOpt.Contains("IHADR=",TString::kIgnoreCase)) {// As in Geant
552         sscanf(addOpt.Data(),"ALLIHADR=%i", &fIHADR);
553         AliDebug(2,Form(" fIHADR %i \n", fIHADR));
554       }
555     }
556   }
557 }
558
559 void AliEMCALGeometry::DefineSamplingFraction()
560 {
561   // Jun 05,2006
562   // Look http://rhic.physics.wayne.edu/~pavlinov/ALICE/SHISHKEBAB/RES/linearityAndResolutionForTRD1.html
563   // Keep for compatibilty
564   //
565   if(fNECLayers == 69) {        // 10% layer reduction
566     fSampling = 12.55;
567   } else if(fNECLayers == 61) { // 20% layer reduction
568     fSampling = 12.80;
569   } else if(fNECLayers == 77) {
570     if       (fECScintThick>0.175 && fECScintThick<0.177) { // 10% Pb thicknes reduction
571       fSampling = 10.5; // fECScintThick = 0.176, fECPbRadThickness=0.144;
572     } else if(fECScintThick>0.191 && fECScintThick<0.193) { // 20% Pb thicknes reduction
573       fSampling = 8.93; // fECScintThick = 0.192, fECPbRadThickness=0.128;
574     }
575   }
576 }
577
578 //______________________________________________________________________
579 void AliEMCALGeometry::GetCellPhiEtaIndexInSModuleFromTRUIndex(const Int_t itru, const Int_t iphitru, const Int_t ietatru, Int_t &iphiSM, Int_t &ietaSM) const 
580 {
581   
582   // This method transforms the (eta,phi) index of cells in a 
583   // TRU matrix into Super Module (eta,phi) index.
584   
585   // Calculate in which row and column where the TRU are 
586   // ordered in the SM
587
588   Int_t col = itru/ fNTRUPhi ;
589   Int_t row = itru - col*fNTRUPhi ;
590    
591   iphiSM = fNCellsInTRUPhi*row + iphitru  ;
592   ietaSM = fNCellsInTRUEta*col + ietatru  ; 
593 }
594
595 //______________________________________________________________________
596 AliEMCALGeometry *  AliEMCALGeometry::GetInstance(){ 
597   // Returns the pointer of the unique instance
598   
599   AliEMCALGeometry * rv = static_cast<AliEMCALGeometry *>( fgGeom );
600   return rv; 
601 }
602
603 //______________________________________________________________________
604 AliEMCALGeometry* AliEMCALGeometry::GetInstance(const Text_t* name,
605                                                 const Text_t* title){
606     // Returns the pointer of the unique instance
607
608     AliEMCALGeometry * rv = 0; 
609     if ( fgGeom == 0 ) {
610       if ( strcmp(name,"") == 0 ) { // get default geometry
611          fgGeom = new AliEMCALGeometry(fgDefaultGeometryName, title);
612       } else {
613          fgGeom = new AliEMCALGeometry(name, title);
614       }  // end if strcmp(name,"")
615       if ( fgInit ) rv = (AliEMCALGeometry * ) fgGeom;
616       else {
617          rv = 0; 
618          delete fgGeom; 
619          fgGeom = 0; 
620       } // end if fgInit
621     }else{
622         if ( strcmp(fgGeom->GetName(), name) != 0) {
623           printf("\ncurrent geometry is %s : ", fgGeom->GetName());
624           printf(" you cannot call %s ",name);  
625         }else{
626           rv = (AliEMCALGeometry *) fgGeom; 
627         } // end 
628     }  // end if fgGeom
629     return rv; 
630 }
631
632 Bool_t AliEMCALGeometry::IsInEMCAL(Double_t x, Double_t y, Double_t z) const {
633   // Checks whether point is inside the EMCal volume, used in AliEMCALv*.cxx
634   //
635   // Code uses cylindrical approximation made of inner radius (for speed)
636   //
637   // Points behind EMCAl, i.e. R > outer radius, but eta, phi in acceptance 
638   // are considered to inside
639
640   Double_t r=sqrt(x*x+y*y);
641
642   if ( r > fEnvelop[0] ) {
643      Double_t theta;
644      theta  =    TMath::ATan2(r,z);
645      Double_t eta;
646      if(theta == 0) 
647        eta = 9999;
648      else 
649        eta    =   -TMath::Log(TMath::Tan(theta/2.));
650      if (eta < fArm1EtaMin || eta > fArm1EtaMax)
651        return 0;
652  
653      Double_t phi = TMath::ATan2(y,x) * 180./TMath::Pi();
654      if (phi < 0) phi += 360;  // phi should go from 0 to 360 in this case
655      if (phi > fArm1PhiMin && phi < fArm1PhiMax)
656        return 1;
657   }
658   return 0;
659 }
660 // ==
661
662 //
663 // == Shish-kebab cases ==
664 //
665 Int_t AliEMCALGeometry::GetAbsCellId(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta) const
666
667   // 27-aug-04; 
668   // corr. 21-sep-04; 
669   //       13-oct-05; 110 degree case
670   // May 31, 2006; ALICE numbering scheme:
671   // 0 <= nSupMod < fNumberOfSuperModules
672   // 0 <= nModule  < fNPHI * fNZ ( fNPHI * fNZ/2 for fKey110DEG=1)
673   // 0 <= nIphi   < fNPHIdiv
674   // 0 <= nIeta   < fNETAdiv
675   // 0 <= absid   < fNCells
676   static Int_t id=0; // have to change from 0 to fNCells-1
677   if(fKey110DEG == 1 && nSupMod >= 10) { // 110 degree case; last two supermodules
678     id  = fNCellsInSupMod*10 + (fNCellsInSupMod/2)*(nSupMod-10);
679   } else {
680     id  = fNCellsInSupMod*nSupMod;
681   }
682   id += fNCellsInModule *nModule;
683   id += fNPHIdiv *nIphi;
684   id += nIeta;
685   if(id<0 || id >= fNCells) {
686 //     printf(" wrong numerations !!\n");
687 //     printf("    id      %6i(will be force to -1)\n", id);
688 //     printf("    fNCells %6i\n", fNCells);
689 //     printf("    nSupMod %6i\n", nSupMod);
690 //     printf("    nModule  %6i\n", nModule);
691 //     printf("    nIphi   %6i\n", nIphi);
692 //     printf("    nIeta   %6i\n", nIeta);
693     id = -TMath::Abs(id); // if negative something wrong
694   }
695   return id;
696 }
697
698 Bool_t  AliEMCALGeometry::CheckAbsCellId(Int_t absId) const
699
700   // May 31, 2006; only trd1 now
701   if(absId<0 || absId >= fNCells) return kFALSE;
702   else                            return kTRUE;
703 }
704
705 Bool_t AliEMCALGeometry::GetCellIndex(Int_t absId,Int_t &nSupMod,Int_t &nModule,Int_t &nIphi,Int_t &nIeta) const
706
707   // 21-sep-04; 19-oct-05;
708   // May 31, 2006; ALICE numbering scheme:
709   // 
710   // In:
711   // absId   - cell is as in Geant,     0<= absId   < fNCells;
712   // Out:
713   // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
714   // nModule  - module number in SM,     0<= nModule  < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
715   // nIphi   - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv; 
716   // nIeta   - cell number in eta driection inside module; 0<= nIeta < fNETAdiv; 
717   // 
718   static Int_t tmp=0, sm10=0;
719   if(!CheckAbsCellId(absId)) return kFALSE;
720
721   sm10 = fNCellsInSupMod*10;
722   if(fKey110DEG == 1 && absId >= sm10) { // 110 degree case; last two supermodules  
723     nSupMod = (absId-sm10) / (fNCellsInSupMod/2) + 10;
724     tmp     = (absId-sm10) % (fNCellsInSupMod/2);
725   } else {
726     nSupMod = absId / fNCellsInSupMod;
727     tmp     = absId % fNCellsInSupMod;
728   }
729
730   nModule  = tmp / fNCellsInModule;
731   tmp     = tmp % fNCellsInModule;
732   nIphi   = tmp / fNPHIdiv;
733   nIeta   = tmp % fNPHIdiv;
734
735   return kTRUE;
736 }
737
738 void AliEMCALGeometry::GetModulePhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule,  int &iphim, int &ietam) const
739
740   // added nSupMod; - 19-oct-05 !
741   // Alice numbering scheme        - Jun 01,2006 
742   // ietam, iphi - indexes of module in two dimensional grid of SM
743   // ietam - have to change from 0 to fNZ-1
744   // iphim - have to change from 0 to nphi-1 (fNPhi-1 or fNPhi/2-1)
745   static Int_t nphi;
746
747   if(fKey110DEG == 1 && nSupMod>=10) nphi = fNPhi/2;
748   else                               nphi = fNPhi;
749
750   ietam = nModule/nphi;
751   iphim = nModule%nphi;
752 }
753
754 void AliEMCALGeometry::GetCellPhiEtaIndexInSModule(Int_t nSupMod, Int_t nModule, Int_t nIphi, Int_t nIeta, 
755 int &iphi, int &ieta) const
756
757   // 
758   // Added nSupMod; Nov 25, 05
759   // Alice numbering scheme  - Jun 01,2006 
760   // IN:
761   // nSupMod - super module(SM) number, 0<= nSupMod < fNumberOfSuperModules;
762   // nModule  - module number in SM,     0<= nModule  < fNCellsInSupMod/fNCellsInSupMod or(/2) for tow last SM (10th and 11th);
763   // nIphi   - cell number in phi driection inside module; 0<= nIphi < fNPHIdiv; 
764   // nIeta   - cell number in eta driection inside module; 0<= nIeta < fNETAdiv; 
765   // 
766  // OUT:
767   // ieta, iphi - indexes of cell(tower) in two dimensional grid of SM
768   // ieta - have to change from 0 to (fNZ*fNETAdiv-1)
769   // iphi - have to change from 0 to (fNPhi*fNPHIdiv-1 or fNPhi*fNPHIdiv/2-1)
770   //
771   static Int_t iphim, ietam;
772
773   GetModulePhiEtaIndexInSModule(nSupMod,nModule, iphim, ietam); 
774   //  ieta  = ietam*fNETAdiv + (1-nIeta); // x(module) = -z(SM) 
775   ieta  = ietam*fNETAdiv + (fNETAdiv - 1 - nIeta); // x(module) = -z(SM) 
776   iphi  = iphim*fNPHIdiv + nIphi;     // y(module) =  y(SM) 
777
778   if(iphi<0 || ieta<0)
779   AliDebug(1,Form(" nSupMod %i nModule %i nIphi %i nIeta %i => ieta %i iphi %i\n", 
780   nSupMod, nModule, nIphi, nIeta, ieta, iphi));
781 }
782
783 Int_t  AliEMCALGeometry::GetSuperModuleNumber(Int_t absId)  const
784 {
785   // Return the number of the  supermodule given the absolute
786   // ALICE numbering id
787
788   static Int_t nSupMod, nModule, nIphi, nIeta;
789   GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
790   return nSupMod;
791
792
793 void  AliEMCALGeometry::GetModuleIndexesFromCellIndexesInSModule(Int_t nSupMod, Int_t iphi, Int_t ieta, 
794                         Int_t &iphim, Int_t &ietam, Int_t &nModule) const
795 {
796   // Transition from cell indexes (ieta,iphi) to module indexes (ietam,iphim, nModule)
797   static Int_t nphi;
798   nphi  = GetNumberOfModuleInPhiDirection(nSupMod);  
799
800   ietam  = ieta/fNETAdiv;
801   iphim  = iphi/fNPHIdiv;
802   nModule = ietam * nphi + iphim; 
803 }
804
805 Int_t  AliEMCALGeometry::GetAbsCellIdFromCellIndexes(Int_t nSupMod, Int_t iphi, Int_t ieta) const
806 {
807   // Transition from super module number(nSupMod) and cell indexes (ieta,iphi) to absId
808   static Int_t ietam, iphim, nModule;
809   static Int_t nIeta, nIphi; // cell indexes in module
810
811   GetModuleIndexesFromCellIndexesInSModule(nSupMod, iphi, ieta, ietam, iphim, nModule);
812
813   nIeta = ieta%fNETAdiv;
814   nIeta = fNETAdiv - 1 - nIeta;
815   nIphi = iphi%fNPHIdiv;
816
817   return GetAbsCellId(nSupMod, nModule, nIphi, nIeta);
818 }
819
820
821 // Methods for AliEMCALRecPoint - Feb 19, 2006
822 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t &xr, Double_t &yr, Double_t &zr) const
823 {
824   // Look to see what the relative
825   // position inside a given cell is
826   // for a recpoint.
827   // Alice numbering scheme - Jun 08, 2006
828   // In:
829   // absId   - cell is as in Geant,     0<= absId   < fNCells;
830   // OUT:
831   // xr,yr,zr - x,y,z coordinates of cell with absId inside SM 
832
833   // Shift index taking into account the difference between standard SM 
834   // and SM of half size in phi direction
835   const Int_t kphiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
836   static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
837   if(!CheckAbsCellId(absId)) return kFALSE;
838
839   GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
840   GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta); 
841  
842   xr = fCentersOfCellsXDir.At(ieta);
843   zr = fCentersOfCellsEtaDir.At(ieta);
844
845   if(nSupMod<10) {
846     yr = fCentersOfCellsPhiDir.At(iphi);
847   } else {
848     yr = fCentersOfCellsPhiDir.At(iphi + kphiIndexShift);
849   }
850   AliDebug(1,Form("absId %i nSupMod %i iphi %i ieta %i xr %f yr %f zr %f ",absId,nSupMod,iphi,ieta,xr,yr,zr));
851
852   return kTRUE;
853 }
854
855 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t loc[3]) const
856 {
857   // Alice numbering scheme - Jun 03, 2006
858   loc[0] = loc[1] = loc[2]=0.0;
859   if(RelPosCellInSModule(absId, loc[0],loc[1],loc[2])) {
860     return kTRUE;
861   }
862   return kFALSE;
863 }
864
865 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, TVector3 &vloc) const
866 {
867   static Double_t loc[3];
868   if(RelPosCellInSModule(absId,loc)) {
869     vloc.SetXYZ(loc[0], loc[1], loc[2]);
870     return kTRUE;
871   } else {
872     vloc.SetXYZ(0,0,0);
873     return kFALSE;
874   }
875   // Alice numbering scheme - Jun 03, 2006
876 }
877
878 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Double_t distEff, Double_t &xr, Double_t &yr, Double_t &zr) const
879 {
880   // Jul 30, 2007 - taking into account position of shower max
881   // Look to see what the relative
882   // position inside a given cell is
883   // for a recpoint.
884   // In:
885   // absId   - cell is as in Geant,     0<= absId   < fNCells;
886   // e       - cluster energy
887   // OUT:
888   // xr,yr,zr - x,y,z coordinates of cell with absId inside SM 
889
890   // Shift index taking into account the difference between standard SM 
891   // and SM of half size in phi direction
892   const  Int_t kphiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
893   static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
894   static Int_t iphim, ietam;
895   static AliEMCALShishKebabTrd1Module *mod = 0;
896   static TVector2 v;
897   if(!CheckAbsCellId(absId)) return kFALSE;
898
899   GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
900   GetModulePhiEtaIndexInSModule(nSupMod, nModule, iphim, ietam);
901   GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta); 
902  
903   mod = GetShishKebabModule(ietam);
904   mod->GetPositionAtCenterCellLine(nIeta, distEff, v); 
905   xr = v.Y() - fParSM[0];
906   zr = v.X() - fParSM[2];
907
908   if(nSupMod<10) {
909     yr = fCentersOfCellsPhiDir.At(iphi);
910   } else {
911     yr = fCentersOfCellsPhiDir.At(iphi + kphiIndexShift);
912   }
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));
914
915   return kTRUE;
916 }
917
918 Bool_t AliEMCALGeometry::RelPosCellInSModule(Int_t absId, Int_t maxAbsId, Double_t distEff, Double_t &xr, Double_t &yr, Double_t &zr) const
919 {
920   // Jul 31, 2007 - taking into account position of shower max and apply coor2.
921   // Look to see what the relative
922   // position inside a given cell is
923   // for a recpoint.
924   // In:
925   // absId     - cell is as in Geant,     0<= absId   < fNCells;
926   // maxAbsId  - abs id of cell with highest energy
927   // e         - cluster energy
928   // OUT:
929   // xr,yr,zr - x,y,z coordinates of cell with absId inside SM 
930
931   // Shift index taking into account the difference between standard SM 
932   // and SM of half size in phi direction
933   const  Int_t kphiIndexShift = fCentersOfCellsPhiDir.GetSize()/4; // Nov 22, 2006; was 6 for cas 2X2
934   static Int_t nSupMod, nModule, nIphi, nIeta, iphi, ieta;
935   static Int_t iphim, ietam;
936   static AliEMCALShishKebabTrd1Module *mod = 0;
937   static TVector2 v;
938
939   static Int_t nSupModM, nModuleM, nIphiM, nIetaM, iphiM, ietaM;
940   static Int_t iphimM, ietamM, maxAbsIdCopy=-1;
941   static AliEMCALShishKebabTrd1Module *modM = 0;
942   static Double_t distCorr;
943
944   if(!CheckAbsCellId(absId)) return kFALSE;
945
946   GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
947   GetModulePhiEtaIndexInSModule(nSupMod, nModule, iphim, ietam);
948   GetCellPhiEtaIndexInSModule(nSupMod,nModule,nIphi,nIeta, iphi, ieta); 
949   mod = GetShishKebabModule(ietam);
950
951   if(absId != maxAbsId) {
952     distCorr = 0.;
953     if(maxAbsIdCopy != maxAbsId) {
954       GetCellIndex(maxAbsId, nSupModM, nModuleM, nIphiM, nIetaM);
955       GetModulePhiEtaIndexInSModule(nSupModM, nModuleM, iphimM, ietamM);
956       GetCellPhiEtaIndexInSModule(nSupModM,nModuleM,nIphiM,nIetaM, iphiM, ietaM); 
957       modM = GetShishKebabModule(ietamM); // do I need this ?
958       maxAbsIdCopy = maxAbsId;
959     }
960     if(ietamM !=0) {
961       distCorr = GetEtaModuleSize()*(ietam-ietamM)/TMath::Tan(modM->GetTheta()); // Stay here
962       //printf(" distCorr %f | dist %f | ietam %i -> etamM %i\n", distCorr, dist, ietam, ietamM);  
963     }
964     // distEff += distCorr;
965   }
966   // Bad resolution in this case, strong bias vs phi
967   // distEff = 0.0; 
968   mod->GetPositionAtCenterCellLine(nIeta, distEff, v); // Stay here
969   xr = v.Y() - fParSM[0];
970   zr = v.X() - fParSM[2];
971
972   if(nSupMod<10) {
973     yr = fCentersOfCellsPhiDir.At(iphi);
974   } else {
975     yr = fCentersOfCellsPhiDir.At(iphi + kphiIndexShift);
976   }
977   AliDebug(1,Form("absId %i nSupMod %i iphi %i ieta %i xr %f yr %f zr %f ",absId,nSupMod,iphi,ieta,xr,yr,zr));
978
979   return kTRUE;
980 }
981
982 void AliEMCALGeometry::CreateListOfTrd1Modules()
983 {
984   // Generate the list of Trd1 modules
985   // which will make up the EMCAL
986   // geometry
987
988   AliDebug(2,Form(" AliEMCALGeometry::CreateListOfTrd1Modules() started "));
989
990   AliEMCALShishKebabTrd1Module *mod=0, *mTmp=0; // current module
991   if(fShishKebabTrd1Modules == 0) {
992     fShishKebabTrd1Modules = new TList;
993     fShishKebabTrd1Modules->SetName("ListOfTRD1");
994     for(int iz=0; iz< GetNZ(); iz++) { 
995       if(iz==0) { 
996         mod  = new AliEMCALShishKebabTrd1Module(TMath::Pi()/2.,this);
997       } else {
998         mTmp  = new AliEMCALShishKebabTrd1Module(*mod);
999         mod   = mTmp;
1000       }
1001       fShishKebabTrd1Modules->Add(mod);
1002     }
1003   } else {
1004     AliDebug(2,Form(" Already exits : "));
1005   }
1006   mod = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(fShishKebabTrd1Modules->GetSize()-1);
1007   fEtaMaxOfTRD1 = mod->GetMaxEtaOfModule(0);
1008
1009   AliDebug(2,Form(" fShishKebabTrd1Modules has %i modules : max eta %5.4f \n", 
1010                   fShishKebabTrd1Modules->GetSize(),fEtaMaxOfTRD1));
1011   // Feb 20,2006;
1012   // Jun 01, 2006 - ALICE numbering scheme
1013   // define grid for cells in eta(z) and x directions in local coordinates system of SM
1014   // Works just for 2x2 case only -- ?? start here
1015   // 
1016   //
1017   // Define grid for cells in phi(y) direction in local coordinates system of SM
1018   // as for 2X2 as for 3X3 - Nov 8,2006
1019   // 
1020   AliDebug(2,Form(" Cells grid in phi directions : size %i\n", fCentersOfCellsPhiDir.GetSize()));
1021   Int_t ind=0; // this is phi index
1022   Int_t ieta=0, nModule=0, iphiTemp;
1023   Double_t xr, zr, theta, phi, eta, r, x,y;
1024   TVector3 vglob;
1025   Double_t ytCenterModule=0.0, ytCenterCell=0.0;
1026
1027   fCentersOfCellsPhiDir.Set(fNPhi*fNPHIdiv);
1028   fPhiCentersOfCells.Set(fNPhi*fNPHIdiv);
1029
1030   Double_t r0 = GetIPDistance() + GetLongModuleSize()/2.;
1031   for(Int_t it=0; it<fNPhi; it++) { // cycle on modules
1032     ytCenterModule = -fParSM[1] + fPhiModuleSize*(2*it+1)/2;  // center of module
1033     for(Int_t ic=0; ic<fNPHIdiv; ic++) { // cycle on cells in module
1034       if(fNPHIdiv==2) {
1035         ytCenterCell = ytCenterModule + fPhiTileSize *(2*ic-1)/2.;
1036       } else if(fNPHIdiv==3){
1037         ytCenterCell = ytCenterModule + fPhiTileSize *(ic-1);
1038       } else if(fNPHIdiv==1){
1039         ytCenterCell = ytCenterModule;
1040       }
1041       fCentersOfCellsPhiDir.AddAt(ytCenterCell,ind);
1042       // Define grid on phi direction
1043       // Grid is not the same for different eta bin;
1044       // Effect is small but is still here
1045       phi = TMath::ATan2(ytCenterCell, r0);
1046       fPhiCentersOfCells.AddAt(phi, ind);
1047
1048       AliDebug(2,Form(" ind %2.2i : y %8.3f ", ind, fCentersOfCellsPhiDir.At(ind))); 
1049       ind++;
1050     }
1051   }
1052
1053   fCentersOfCellsEtaDir.Set(fNZ *fNETAdiv);
1054   fCentersOfCellsXDir.Set(fNZ *fNETAdiv);
1055   fEtaCentersOfCells.Set(fNZ *fNETAdiv * fNPhi*fNPHIdiv);
1056   AliDebug(2,Form(" Cells grid in eta directions : size %i\n", fCentersOfCellsEtaDir.GetSize()));
1057   for(Int_t it=0; it<fNZ; it++) {
1058     AliEMCALShishKebabTrd1Module *trd1 = GetShishKebabModule(it);
1059     nModule = fNPhi*it;
1060     for(Int_t ic=0; ic<fNETAdiv; ic++) {
1061       if(fNPHIdiv==2) {
1062         trd1->GetCenterOfCellInLocalCoordinateofSM(ic, xr, zr);      // case of 2X2
1063         GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta); 
1064       } if(fNPHIdiv==3) {
1065         trd1->GetCenterOfCellInLocalCoordinateofSM_3X3(ic, xr, zr);  // case of 3X3
1066         GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta); 
1067       } if(fNPHIdiv==1) {
1068         trd1->GetCenterOfCellInLocalCoordinateofSM_1X1(xr, zr);      // case of 1X1
1069         GetCellPhiEtaIndexInSModule(0, nModule, 0, ic, iphiTemp, ieta); 
1070       }
1071       fCentersOfCellsXDir.AddAt(float(xr) - fParSM[0],ieta);
1072       fCentersOfCellsEtaDir.AddAt(float(zr) - fParSM[2],ieta);
1073       // Define grid on eta direction for each bin in phi
1074       for(int iphi=0; iphi<fCentersOfCellsPhiDir.GetSize(); iphi++) {
1075         x = xr + trd1->GetRadius();
1076         y = fCentersOfCellsPhiDir[iphi];
1077         r = TMath::Sqrt(x*x + y*y + zr*zr);
1078         theta = TMath::ACos(zr/r);
1079         eta   = AliEMCALShishKebabTrd1Module::ThetaToEta(theta);
1080         //        ind   = ieta*fCentersOfCellsPhiDir.GetSize() + iphi;
1081         ind   = iphi*fCentersOfCellsEtaDir.GetSize() + ieta;
1082         fEtaCentersOfCells.AddAt(eta, ind);
1083       }
1084       //printf(" ieta %i : xr + trd1->GetRadius() %f : zr %f : eta %f \n", ieta, xr + trd1->GetRadius(), zr, eta);
1085     }
1086   }
1087   for(Int_t i=0; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1088     AliDebug(2,Form(" ind %2.2i : z %8.3f : x %8.3f", i+1, 
1089                     fCentersOfCellsEtaDir.At(i),fCentersOfCellsXDir.At(i)));
1090   }
1091
1092 }
1093
1094 void AliEMCALGeometry::GetGlobal(const Double_t *loc, Double_t *glob, int ind) const
1095 {
1096   // Figure out the global numbering
1097   // of a given supermodule from the
1098   // local numbering and the transformation
1099   // matrix stored by the geometry manager (allows for misaligned
1100   // geometry)
1101
1102   if(ind>=0 && ind < GetNumberOfSuperModules()) {
1103     TString volpath = "ALIC_1/XEN1_1/SMOD_";
1104     volpath += ind+1;
1105
1106     if(GetKey110DEG() && ind>=10) {
1107       volpath = "ALIC_1/XEN1_1/SM10_";
1108       volpath += ind-10+1;
1109     }
1110
1111     if(!gGeoManager->cd(volpath.Data()))
1112       AliFatal(Form("AliEMCALGeometry::GeoManager cannot find path %s!",volpath.Data()));
1113
1114     TGeoHMatrix* m = gGeoManager->GetCurrentMatrix();
1115     if(m) {
1116       m->LocalToMaster(loc, glob);
1117     } else {
1118       AliFatal("Geo matrixes are not loaded \n") ;
1119     }
1120   }
1121 }
1122
1123 void AliEMCALGeometry::GetGlobal(const TVector3 &vloc, TVector3 &vglob, int ind) const
1124 {
1125   //Figure out the global numbering
1126   //of a given supermodule from the
1127   //local numbering given a 3-vector location
1128
1129   static Double_t tglob[3], tloc[3];
1130   vloc.GetXYZ(tloc);
1131   GetGlobal(tloc, tglob, ind);
1132   vglob.SetXYZ(tglob[0], tglob[1], tglob[2]);
1133 }
1134
1135 void AliEMCALGeometry::GetGlobal(Int_t absId , double glob[3]) const
1136
1137   // Alice numbering scheme - Jun 03, 2006
1138   static Int_t nSupMod, nModule, nIphi, nIeta;
1139   static double loc[3];
1140
1141   if (!gGeoManager || !gGeoManager->IsClosed()) {
1142     AliError("Can't get the global coordinates! gGeoManager doesn't exist or it is still open!");
1143     return;
1144   }
1145
1146   glob[0]=glob[1]=glob[2]=0.0; // bad case
1147   if(RelPosCellInSModule(absId, loc)) {
1148     GetCellIndex(absId, nSupMod, nModule, nIphi, nIeta);
1149
1150     TString volpath = "ALIC_1/XEN1_1/SMOD_";
1151     volpath += (nSupMod+1);
1152
1153     if(GetKey110DEG() && nSupMod>=10) {
1154       volpath = "ALIC_1/XEN1_1/SM10_";
1155       volpath += (nSupMod-10+1);
1156     }
1157     if(!gGeoManager->cd(volpath.Data()))
1158       AliFatal(Form("GeoManager cannot find path %s!",volpath.Data()));
1159
1160     TGeoHMatrix* m = gGeoManager->GetCurrentMatrix();
1161     if(m) {
1162       m->LocalToMaster(loc, glob);
1163     } else {
1164       AliFatal("Geo matrixes are not loaded \n") ;
1165     }
1166   }
1167 }
1168
1169 //___________________________________________________________________
1170 void AliEMCALGeometry::GetGlobal(Int_t absId , TVector3 &vglob) const
1171
1172   // Alice numbering scheme - Jun 03, 2006
1173   static Double_t glob[3];
1174
1175   GetGlobal(absId, glob);
1176   vglob.SetXYZ(glob[0], glob[1], glob[2]);
1177
1178 }
1179
1180 //____________________________________________________________________________
1181 void AliEMCALGeometry::GetGlobal(const AliRecPoint* /*rp*/, TVector3& /* vglob */) const
1182 {
1183   AliFatal(Form("Please use GetGlobalEMCAL(recPoint,gpos) instead of GetGlobal!"));
1184 }
1185
1186 //_________________________________________________________________________________
1187 void AliEMCALGeometry::GetGlobalEMCAL(const AliEMCALRecPoint *rp, TVector3 &vglob) const
1188 {
1189   // Figure out the global numbering
1190   // of a given supermodule from the
1191   // local numbering for RecPoints
1192
1193   static TVector3 vloc;
1194   static Int_t nSupMod, nModule, nIphi, nIeta;
1195
1196   const AliEMCALRecPoint *rpTmp = rp;
1197   const AliEMCALRecPoint *rpEmc = rpTmp;
1198
1199   GetCellIndex(rpEmc->GetAbsId(0), nSupMod, nModule, nIphi, nIeta);
1200   rpTmp->GetLocalPosition(vloc);
1201   GetGlobal(vloc, vglob, nSupMod);
1202 }
1203
1204 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Double_t &eta,Double_t &phi) const
1205 {
1206   // Nov 16, 2006- float to double
1207   // version for TRD1 only
1208   static TVector3 vglob;
1209   GetGlobal(absId, vglob);
1210   eta = vglob.Eta();
1211   phi = vglob.Phi();
1212 }
1213
1214 void AliEMCALGeometry::EtaPhiFromIndex(Int_t absId,Float_t &eta,Float_t &phi) const
1215 {
1216   // Nov 16,2006 - should be discard in future
1217   static TVector3 vglob;
1218   GetGlobal(absId, vglob);
1219   eta = float(vglob.Eta());
1220   phi = float(vglob.Phi());
1221 }
1222
1223 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSM(Int_t nSupMod, Double_t &phiMin, Double_t &phiMax) const
1224 {
1225   // 0<= nSupMod <=11; phi in rad
1226   static int i;
1227   if(nSupMod<0 || nSupMod >11) return kFALSE; 
1228   i = nSupMod/2;
1229   phiMin = fPhiBoundariesOfSM[2*i];
1230   phiMax = fPhiBoundariesOfSM[2*i+1];
1231   return kTRUE; 
1232 }
1233
1234 Bool_t AliEMCALGeometry::GetPhiBoundariesOfSMGap(Int_t nPhiSec, Double_t &phiMin, Double_t &phiMax) const
1235 {
1236   // 0<= nPhiSec <=4; phi in rad
1237   // 0;  gap boundaries between  0th&2th  | 1th&3th SM
1238   // 1;  gap boundaries between  2th&4th  | 3th&5th SM
1239   // 2;  gap boundaries between  4th&6th  | 5th&7th SM
1240   // 3;  gap boundaries between  6th&8th  | 7th&9th SM
1241   // 4;  gap boundaries between  8th&10th | 9th&11th SM
1242   if(nPhiSec<0 || nPhiSec >4) return kFALSE; 
1243   phiMin = fPhiBoundariesOfSM[2*nPhiSec+1];
1244   phiMax = fPhiBoundariesOfSM[2*nPhiSec+2];
1245   return kTRUE; 
1246 }
1247
1248 Bool_t AliEMCALGeometry::SuperModuleNumberFromEtaPhi(Double_t eta, Double_t phi, Int_t &nSupMod) const
1249
1250   // Return false if phi belongs a phi cracks between SM
1251  
1252   static Int_t i;
1253
1254   if(TMath::Abs(eta) > fEtaMaxOfTRD1) return kFALSE;
1255
1256   phi = TVector2::Phi_0_2pi(phi); // move phi to (0,2pi) boundaries
1257   for(i=0; i<6; i++) {
1258     if(phi>=fPhiBoundariesOfSM[2*i] && phi<=fPhiBoundariesOfSM[2*i+1]) {
1259       nSupMod = 2*i;
1260       if(eta < 0.0) nSupMod++;
1261       AliDebug(1,Form("eta %f phi %f(%5.2f) : nSupMod %i : #bound %i", eta,phi,phi*TMath::RadToDeg(), nSupMod,i));
1262       return kTRUE;
1263     }
1264   }
1265   return kFALSE;
1266 }
1267
1268 Bool_t AliEMCALGeometry::GetAbsCellIdFromEtaPhi(Double_t eta, Double_t phi, Int_t &absId) const
1269 {
1270   // Nov 17,2006
1271   // stay here - phi problem as usual 
1272   static Int_t nSupMod, i, ieta, iphi, etaShift, nphi;
1273   static Double_t absEta=0.0, d=0.0, dmin=0.0, phiLoc;
1274   absId = nSupMod = - 1;
1275   if(SuperModuleNumberFromEtaPhi(eta, phi, nSupMod)) {
1276     // phi index first
1277     phi    = TVector2::Phi_0_2pi(phi);
1278     phiLoc = phi - fPhiCentersOfSM[nSupMod/2];
1279     nphi   = fPhiCentersOfCells.GetSize();
1280     if(nSupMod>=10) {
1281       phiLoc = phi - 190.*TMath::DegToRad();
1282       nphi  /= 2;
1283     }
1284
1285     dmin   = TMath::Abs(fPhiCentersOfCells[0]-phiLoc);
1286     iphi   = 0;
1287     for(i=1; i<nphi; i++) {
1288       d = TMath::Abs(fPhiCentersOfCells[i] - phiLoc);
1289       if(d < dmin) {
1290         dmin = d;
1291         iphi = i;
1292       }
1293       //      printf(" i %i : d %f : dmin %f : fPhiCentersOfCells[i] %f \n", i, d, dmin, fPhiCentersOfCells[i]);
1294     }
1295     // odd SM are turned with respect of even SM - reverse indexes
1296     AliDebug(2,Form(" iphi %i : dmin %f (phi %f, phiLoc %f ) ", iphi, dmin, phi, phiLoc));
1297     // eta index
1298     absEta   = TMath::Abs(eta);
1299     etaShift = iphi*fCentersOfCellsEtaDir.GetSize();
1300     dmin     = TMath::Abs(fEtaCentersOfCells[etaShift]-absEta);
1301     ieta     = 0;
1302     for(i=1; i<fCentersOfCellsEtaDir.GetSize(); i++) {
1303       d = TMath::Abs(fEtaCentersOfCells[i+etaShift] - absEta);
1304       if(d < dmin) {
1305         dmin = d;
1306         ieta = i;
1307       }
1308     }
1309     AliDebug(2,Form(" ieta %i : dmin %f (eta=%f) : nSupMod %i ", ieta, dmin, eta, nSupMod));
1310
1311     if(eta<0) iphi = (nphi-1) - iphi;
1312     absId = GetAbsCellIdFromCellIndexes(nSupMod, iphi, ieta);
1313
1314     return kTRUE;
1315   }
1316   return kFALSE;
1317 }
1318
1319 AliEMCALShishKebabTrd1Module* AliEMCALGeometry::GetShishKebabModule(Int_t neta) const
1320 {
1321   //This method was too long to be
1322   //included in the header file - the
1323   //rule checker complained about it's
1324   //length, so we move it here.  It returns the
1325   //shishkebabmodule at a given eta index point.
1326
1327   static AliEMCALShishKebabTrd1Module* trd1=0;
1328   if(fShishKebabTrd1Modules && neta>=0 && neta<fShishKebabTrd1Modules->GetSize()) {
1329     trd1 = (AliEMCALShishKebabTrd1Module*)fShishKebabTrd1Modules->At(neta);
1330   } else trd1 = 0;
1331   return trd1;
1332 }
1333
1334 void AliEMCALGeometry::Browse(TBrowser* b)
1335 {
1336   //Browse the modules
1337   if(fShishKebabTrd1Modules) b->Add(fShishKebabTrd1Modules);
1338 }
1339
1340 Bool_t AliEMCALGeometry::IsFolder() const
1341 {
1342   //Check if fShishKebabTrd1Modules is in folder
1343   if(fShishKebabTrd1Modules) return kTRUE;
1344   else                       return kFALSE;
1345 }
1346
1347 Double_t AliEMCALGeometry::GetPhiCenterOfSM(Int_t nsupmod) const
1348 {
1349   //returns center of supermodule in phi 
1350   int i = nsupmod/2;
1351   return fPhiCentersOfSM[i];
1352
1353 }