]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PHOS/AliPHOSv0.cxx
add aliroot macros to look at data from strip modules and from LED reference system
[u/mrichter/AliRoot.git] / PHOS / AliPHOSv0.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 /* $Id$ */
16
17 /* History of cvs commits:
18  *
19  * $Log$
20  * Revision 1.94  2007/10/18 08:40:02  kharlov
21  * Misalignment-related bug fixed
22  *
23  * Revision 1.93  2007/10/06 22:24:40  kharlov
24  * Bug in strip unit geometry is corrected
25  *
26  * Revision 1.92  2007/07/04 16:38:19  policheh
27  * Tracking2LocalCS matrices corrected for CPV.
28  *
29  * Revision 1.91  2007/07/02 14:50:49  policheh
30  * Tracking2LocalCS matrices corrected.
31  *
32  * Revision 1.90  2007/05/24 13:04:05  policheh
33  * AddAlignableVolumes: local to tracking CS transformation matrices creates for each
34  * PHOS supermodule
35  *
36  * Revision 1.89  2007/04/24 14:34:39  hristov
37  * Additional protection: do not search for alignable object if the CPV is not in the geometry
38  *
39  * Revision 1.88  2007/04/19 15:28:30  kharlov
40  * Modify strip unit geometry according to the final drawings (Timur)
41  *
42  * Revision 1.87  2007/04/01 07:37:10  kharlov
43  * TGeo RS to Local RS transf matr added
44  *
45  * Revision 1.86  2007/03/06 06:55:46  kharlov
46  * DP:Misalignment of CPV added
47  *
48  * Revision 1.85  2007/03/01 11:37:37  kharlov
49  * Strip units changed from 8x1 to 8x2 (T.Pocheptsov)
50  *
51  * Revision 1.84  2006/12/20 16:56:43  kharlov
52  * Optional geometry without CPV
53  *
54  * Revision 1.83  2006/11/14 17:11:15  hristov
55  * Removing inheritances from TAttLine, TAttMarker and AliRndm in AliModule. The copy constructor and assignment operators are moved to the private part of the class and not implemented. The corresponding changes are propagated to the detectors
56  *
57  * Revision 1.82  2006/09/27 19:55:57  kharlov
58  * Alignment object with symbolic volume names are introduced
59  *
60  * Revision 1.81  2006/03/04 20:25:56  kharlov
61  * Set geom parameters from CDB
62  *
63  * Revision 1.80  2005/06/17 07:39:07  hristov
64  * Removing GetDebug and SetDebug from AliRun and AliModule. Using AliLog for the messages
65  *
66  * Revision 1.79  2005/05/28 14:19:05  schutz
67  * Compilation warnings fixed by T.P.
68  *
69  */
70
71 //_________________________________________________________________________
72 // Implementation version v0 of PHOS Manager class 
73 // An object of this class does not produce hits nor digits
74 // It is the one to use if you do not want to produce outputs in TREEH or TREED
75 //                  
76 //*-- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (RRC KI & SUBATECH)
77
78
79 // --- ROOT system ---
80
81 #include <TBRIK.h>
82 #include <TFolder.h>
83 #include <TGeometry.h>
84 #include <TNode.h>
85 #include <TROOT.h>
86 #include <TRandom.h>
87 #include <TTRD1.h>
88 #include <TTree.h>
89 #include <TVirtualMC.h>
90 #include <TGeoPhysicalNode.h>
91 #include <TGeoManager.h>
92 #include <TGeoMatrix.h>
93 #include <TVector3.h>
94
95 // --- Standard library ---
96
97 #include <string.h>
98 #include <stdlib.h>
99
100 // --- AliRoot header files ---
101
102 #include "AliConst.h"
103 #include "AliPHOSGeometry.h"
104 #include "AliPHOSLoader.h"
105 #include "AliPHOSv0.h"
106 #include "AliRun.h"
107 #include "AliLog.h"
108 #include "AliGeomManager.h"
109
110 ClassImp(AliPHOSv0)
111
112 //____________________________________________________________________________
113 AliPHOSv0::AliPHOSv0(const char *name, const char *title):
114   AliPHOS(name,title)
115 {
116   // ctor : title is used to identify the layout
117   GetGeometry() ; 
118 }
119
120 //____________________________________________________________________________
121 void AliPHOSv0::CreateGeometry()
122 {
123   // Create the PHOS geometry for Geant
124
125   AliPHOSv0 *phostmp = dynamic_cast<AliPHOSv0*>(gAlice->GetModule("PHOS")) ;
126
127   if ( phostmp == NULL ) {
128     
129     fprintf(stderr, "PHOS detector not found!\n") ;
130     return;
131     
132   }
133
134   AliPHOSGeometry * geom = GetGeometry() ; 
135
136   // Get pointer to the array containing media indeces
137   Int_t *idtmed = fIdtmed->GetArray() - 699 ;
138
139   // Create a PHOS module.
140   
141   gMC->Gsvolu("PHOS", "TRD1", idtmed[798], geom->GetPHOSParams(), 4) ;        
142   
143   this->CreateGeometryforEMC() ; 
144
145   if (strstr(fTitle.Data(),"noCPV") == 0) 
146     this->CreateGeometryforCPV() ;
147   
148   this->CreateGeometryforSupport() ; 
149   
150   // --- Position  PHOS mdules in ALICE setup ---
151   Int_t idrotm[99] ;
152   Int_t iXYZ,iAngle;
153   char im[5] ;
154   Bool_t anyModuleCreated=0 ;
155   for (Int_t iModule = 0; iModule < 5 ; iModule++ ) {
156     sprintf(im,"%d",iModule+1) ;
157     if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
158       continue ;
159     anyModuleCreated=1 ;
160     Float_t angle[3][2];
161     for (iXYZ=0; iXYZ<3; iXYZ++)
162       for (iAngle=0; iAngle<2; iAngle++)
163         angle[iXYZ][iAngle] = geom->GetModuleAngle(iModule,iXYZ, iAngle);
164     AliMatrix(idrotm[iModule],
165               angle[0][0],angle[0][1],
166               angle[1][0],angle[1][1],
167               angle[2][0],angle[2][1]) ;
168     
169     Float_t pos[3];
170     for (iXYZ=0; iXYZ<3; iXYZ++)
171       pos[iXYZ] = geom->GetModuleCenter(iModule,iXYZ);
172     gMC->Gspos("PHOS", iModule+1, "ALIC", pos[0], pos[1], pos[2],
173                idrotm[iModule], "ONLY") ;
174   }
175   if(!anyModuleCreated)
176     AliError("No one PHOS module was created") ;
177 }
178
179 //____________________________________________________________________________
180 void AliPHOSv0::CreateGeometryforEMC()
181 {
182   // Create the PHOS-EMC geometry for GEANT
183   // Author: Dmitri Peressounko August 2001
184   // The used coordinate system: 
185   //   1. in Module: X along longer side, Y out of beam, Z along shorter side (along beam)
186   //   2. In Strip the same: X along longer side, Y out of beam, Z along shorter side (along beam)
187
188
189     //BEGIN_HTML
190   /*
191     <H2>
192     Geant3 geometry tree of PHOS-EMC in ALICE
193     </H2>
194     <P><CENTER>
195     <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/EMCinAlice.gif"> 
196     </CENTER><P>
197   */
198   //END_HTML  
199   
200   // Get pointer to the array containing media indexes
201   Int_t *idtmed = fIdtmed->GetArray() - 699 ;
202
203   AliPHOSGeometry * geom = GetGeometry() ; 
204   AliPHOSEMCAGeometry * emcg = geom->GetEMCAGeometry() ;
205
206   // ======= Define the strip ===============
207
208   gMC->Gsvolu("PSTR", "BOX ", idtmed[716], emcg->GetStripHalfSize(), 3) ;  //Made of steel
209    
210       // --- define steel volume (cell of the strip unit)
211 //       gMC->Gsvolu("PCEL", "BOX ", idtmed[798], emcg->GetSteelCellHalfSize(), 3);
212       gMC->Gsvolu("PCEL", "BOX ", idtmed[798], emcg->GetAirCellHalfSize(), 3);
213
214       // --- define wrapped crystal and put it into steel cell
215
216       gMC->Gsvolu("PWRA", "BOX ", idtmed[702], emcg->GetWrappedHalfSize(), 3);
217       Float_t * pin = emcg->GetAPDHalfSize() ; 
218       Float_t * preamp = emcg->GetPreampHalfSize() ;
219       Float_t y = (emcg->GetAirGapLed()-2*pin[1]-2*preamp[1])/2;
220       gMC->Gspos("PWRA", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ;
221     
222       // --- Define crystal and put it into wrapped crystall ---
223       gMC->Gsvolu("PXTL", "BOX ", idtmed[699], emcg->GetCrystalHalfSize(), 3) ;
224       gMC->Gspos("PXTL", 1, "PWRA", 0.0, 0.0, 0.0, 0, "ONLY") ;
225       
226       // --- define APD/PIN preamp and put it into AirCell
227  
228       gMC->Gsvolu("PPIN", "BOX ", idtmed[705], emcg->GetAPDHalfSize(), 3) ;
229       Float_t * crystal = emcg->GetCrystalHalfSize() ;
230       y = crystal[1] + emcg->GetAirGapLed() /2 - preamp[1]; 
231       gMC->Gspos("PPIN", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ;
232
233       gMC->Gsvolu("PREA", "BOX ", idtmed[711], emcg->GetPreampHalfSize(), 3) ;   // Here I assumed preamp
234                                                                                  // as a printed Circuit
235       y = crystal[1] + emcg->GetAirGapLed() /2 + pin[1]  ;                  // May it should be changed
236       gMC->Gspos("PREA", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ;                    // to ceramics?
237    
238
239       // --- Fill strip with wrapped cristals in steel cells
240
241       Float_t* splate = emcg->GetSupportPlateHalfSize();  
242       y = -splate[1] ;
243 //       Float_t* acel = emcg->GetSteelCellHalfSize() ;
244       Float_t* acel = emcg->GetAirCellHalfSize() ;
245
246       for(Int_t lev = 2, icel = 1; icel <= emcg->GetNCellsXInStrip()*emcg->GetNCellsZInStrip(); icel += 2, lev += 2){
247          Float_t x = (2*(lev / 2) - 1 - emcg->GetNCellsXInStrip())* acel[0] ;
248          Float_t z = acel[2];
249          gMC->Gspos("PCEL", icel, "PSTR", x, y, +z, 0, "ONLY") ;
250          gMC->Gspos("PCEL", icel + 1, "PSTR", x, y, -z, 0, "ONLY") ;
251       }
252
253       // --- define the support plate, hole in it and position it in strip ----
254       gMC->Gsvolu("PSUP", "BOX ", idtmed[701], emcg->GetSupportPlateHalfSize(), 3) ;
255
256       gMC->Gsvolu("PSHO", "BOX ", idtmed[798], emcg->GetSupportPlateInHalfSize(), 3) ;
257       Float_t z = emcg->GetSupportPlateThickness()/2 ;
258       gMC->Gspos("PSHO", 1, "PSUP", 0.0, 0.0, z, 0, "ONLY") ;
259
260       y = acel[1] ;
261       gMC->Gspos("PSUP", 1, "PSTR", 0.0, y, 0.0, 0, "ONLY") ;
262
263
264     // ========== Fill module with strips and put them into inner thermoinsulation=============
265       gMC->Gsvolu("PTII", "BOX ", idtmed[706], emcg->GetInnerThermoHalfSize(), 3) ;     
266
267       Float_t * inthermo = emcg->GetInnerThermoHalfSize() ;
268       Float_t * strip = emcg->GetStripHalfSize() ;
269       y = inthermo[1] - strip[1] ;
270       Int_t irow;
271       Int_t nr = 1 ;
272       Int_t icol ;
273
274       for(irow = 0; irow < emcg->GetNStripX(); irow ++){
275         Float_t x = (2*irow + 1 - emcg->GetNStripX())* strip[0] ;
276         for(icol = 0; icol < emcg->GetNStripZ(); icol ++){
277           z = (2*icol + 1 - emcg->GetNStripZ()) * strip[2] ;
278           gMC->Gspos("PSTR", nr, "PTII", x, y, z, 0, "ONLY") ;
279           nr++ ;
280         }
281       }
282           
283
284    // ------- define the air gap between thermoinsulation and cooler
285       gMC->Gsvolu("PAGA", "BOX ", idtmed[798], emcg->GetAirGapHalfSize(), 3) ;   
286       Float_t * agap = emcg->GetAirGapHalfSize() ;
287       y = agap[1] - inthermo[1]  ;
288       
289       gMC->Gspos("PTII", 1, "PAGA", 0.0, y, 0.0, 0, "ONLY") ;
290
291
292
293    // ------- define the Al passive cooler 
294       gMC->Gsvolu("PCOR", "BOX ", idtmed[701], emcg->GetCoolerHalfSize(), 3) ;   
295       Float_t * cooler = emcg->GetCoolerHalfSize() ;
296       y = cooler[1] - agap[1]  ;
297       
298       gMC->Gspos("PAGA", 1, "PCOR", 0.0, y, 0.0, 0, "ONLY") ;
299
300    // ------- define the outer thermoinsulating cover
301       gMC->Gsvolu("PTIO", "TRD1", idtmed[706], emcg->GetOuterThermoParams(), 4) ;        
302       Float_t * outparams = emcg->GetOuterThermoParams() ; 
303
304       Int_t idrotm[99] ;
305       AliMatrix(idrotm[1], 90.0, 0.0, 0.0, 0.0, 90.0, 270.0) ;
306       // Frame in outer thermoinsulation and so on: z out of beam, y along beam, x across beam
307  
308       z = outparams[3] - cooler[1] ;
309       gMC->Gspos("PCOR", 1, "PTIO", 0., 0.0, z, idrotm[1], "ONLY") ;
310        
311   // -------- Define the outer Aluminium cover -----
312       gMC->Gsvolu("PCOL", "TRD1", idtmed[701], emcg->GetAlCoverParams(), 4) ;        
313       Float_t * covparams = emcg->GetAlCoverParams() ; 
314       z = covparams[3] - outparams[3] ;
315       gMC->Gspos("PTIO", 1, "PCOL", 0., 0.0, z, 0, "ONLY") ;
316
317  // --------- Define front fiberglass cover -----------
318       gMC->Gsvolu("PFGC", "BOX ", idtmed[717], emcg->GetFiberGlassHalfSize(), 3) ;  
319       z = - outparams[3] ;
320       gMC->Gspos("PFGC", 1, "PCOL", 0., 0.0, z, 0, "ONLY") ;
321
322  //=============This is all with cold section==============
323
324
325       //------ Warm Section --------------
326       gMC->Gsvolu("PWAR", "BOX ", idtmed[701], emcg->GetWarmAlCoverHalfSize(), 3) ; 
327       Float_t * warmcov = emcg->GetWarmAlCoverHalfSize() ;
328
329       // --- Define the outer thermoinsulation ---
330       gMC->Gsvolu("PWTI", "BOX ", idtmed[706], emcg->GetWarmThermoHalfSize(), 3) ; 
331       Float_t * warmthermo = emcg->GetWarmThermoHalfSize() ;
332       z = -warmcov[2] + warmthermo[2] ;
333
334       gMC->Gspos("PWTI", 1, "PWAR", 0., 0.0, z, 0, "ONLY") ;     
335
336       // --- Define cables area and put in it T-supports ---- 
337       gMC->Gsvolu("PCA1", "BOX ", idtmed[718], emcg->GetTCables1HalfSize(), 3) ; 
338       Float_t * cbox = emcg->GetTCables1HalfSize() ;
339
340       gMC->Gsvolu("PBE1", "BOX ", idtmed[701], emcg->GetTSupport1HalfSize(), 3) ;
341       Float_t * beams = emcg->GetTSupport1HalfSize() ;
342       Int_t isup ;
343       for(isup = 0; isup < emcg->GetNTSuppots(); isup++){
344         Float_t x = -cbox[0] + beams[0] + (2*beams[0]+emcg->GetTSupportDist())*isup ;
345         gMC->Gspos("PBE1", isup, "PCA1", x, 0.0, 0.0, 0, "ONLY") ;
346       }
347
348       z = -warmthermo[2] + cbox[2];
349       gMC->Gspos("PCA1", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;     
350
351       gMC->Gsvolu("PCA2", "BOX ", idtmed[718], emcg->GetTCables2HalfSize(), 3) ; 
352       Float_t * cbox2 = emcg->GetTCables2HalfSize() ;
353
354       gMC->Gsvolu("PBE2", "BOX ", idtmed[701], emcg->GetTSupport2HalfSize(), 3) ;
355       for(isup = 0; isup < emcg->GetNTSuppots(); isup++){
356         Float_t x = -cbox[0] + beams[0] + (2*beams[0]+emcg->GetTSupportDist())*isup ;
357         gMC->Gspos("PBE2", isup, "PCA2", x, 0.0, 0.0, 0, "ONLY") ;
358       }
359
360       z = -warmthermo[2] + 2*cbox[2] + cbox2[2];
361       gMC->Gspos("PCA2", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;     
362
363
364   // --- Define frame ---
365       gMC->Gsvolu("PFRX", "BOX ", idtmed[716], emcg->GetFrameXHalfSize(), 3) ; 
366       Float_t * posit = emcg->GetFrameXPosition() ;
367       gMC->Gspos("PFRX", 1, "PWTI", posit[0],  posit[1], posit[2], 0, "ONLY") ;
368       gMC->Gspos("PFRX", 2, "PWTI", posit[0], -posit[1], posit[2], 0, "ONLY") ;
369
370       gMC->Gsvolu("PFRZ", "BOX ", idtmed[716], emcg->GetFrameZHalfSize(), 3) ; 
371       posit = emcg->GetFrameZPosition() ;
372       gMC->Gspos("PFRZ", 1, "PWTI", posit[0], posit[1],  posit[2], 0, "ONLY") ;
373       gMC->Gspos("PFRZ", 2, "PWTI", -posit[0], posit[1], posit[2], 0, "ONLY") ;
374
375  // --- Define Fiber Glass support ---
376       gMC->Gsvolu("PFG1", "BOX ", idtmed[717], emcg->GetFGupXHalfSize(), 3) ; 
377       posit = emcg->GetFGupXPosition() ;
378       gMC->Gspos("PFG1", 1, "PWTI", posit[0],  posit[1], posit[2], 0, "ONLY") ;
379       gMC->Gspos("PFG1", 2, "PWTI", posit[0], -posit[1], posit[2], 0, "ONLY") ;
380
381       gMC->Gsvolu("PFG2", "BOX ", idtmed[717], emcg->GetFGupZHalfSize(), 3) ; 
382       posit = emcg->GetFGupZPosition();
383       gMC->Gspos("PFG2", 1, "PWTI",  posit[0], posit[1], posit[2], 0, "ONLY") ;
384       gMC->Gspos("PFG2", 2, "PWTI", -posit[0], posit[1], posit[2], 0, "ONLY") ;
385
386       gMC->Gsvolu("PFG3", "BOX ", idtmed[717], emcg->GetFGlowXHalfSize(), 3) ; 
387       posit = emcg->GetFGlowXPosition() ;
388       gMC->Gspos("PFG3", 1, "PWTI", posit[0],  posit[1], posit[2], 0, "ONLY") ;
389       gMC->Gspos("PFG3", 2, "PWTI", posit[0], -posit[1], posit[2], 0, "ONLY") ;
390
391       gMC->Gsvolu("PFG4", "BOX ", idtmed[717], emcg->GetFGlowZHalfSize(), 3) ; 
392       posit = emcg->GetFGlowZPosition() ;
393       gMC->Gspos("PFG4", 1, "PWTI",  posit[0], posit[1], posit[2], 0, "ONLY") ;
394       gMC->Gspos("PFG4", 2, "PWTI", -posit[0], posit[1], posit[2], 0, "ONLY") ;
395
396       // --- Define Air Gap for FEE electronics ----- 
397
398       gMC->Gsvolu("PAFE", "BOX ", idtmed[798], emcg->GetFEEAirHalfSize(), 3) ; 
399       posit = emcg->GetFEEAirPosition() ;
400       gMC->Gspos("PAFE", 1, "PWTI",  posit[0], posit[1], posit[2], 0, "ONLY") ;
401
402       // Define the EMC module volume and combine Cool and Warm sections
403
404       gMC->Gsvolu("PEMC", "TRD1", idtmed[798], emcg->GetEMCParams(), 4) ;        
405
406       z =  - warmcov[2] ;
407       gMC->Gspos("PCOL", 1, "PEMC",  0., 0., z, 0, "ONLY") ;
408       z = covparams[3] ;
409       gMC->Gspos("PWAR", 1, "PEMC",  0., 0., z, 0, "ONLY") ;
410
411
412       // Put created EMC geometry into PHOS volume
413       
414       z = geom->GetCPVBoxSize(1) / 2. ;
415       gMC->Gspos("PEMC", 1, "PHOS", 0., 0., z, 0, "ONLY") ; 
416             
417 }
418
419 //____________________________________________________________________________
420 void AliPHOSv0::CreateGeometryforCPV()
421 {
422   // Create the PHOS-CPV geometry for GEANT
423   // Author: Yuri Kharlov 11 September 2000
424   //BEGIN_HTML
425   /*
426     <H2>
427     Geant3 geometry of PHOS-CPV in ALICE
428     </H2>
429     <table width=700>
430
431     <tr>
432          <td>CPV perspective view</td>
433          <td>CPV front view      </td>
434     </tr>
435
436     <tr>
437          <td> <img height=300 width=290 src="../images/CPVallPersp.gif"> </td>
438          <td> <img height=300 width=290 src="../images/CPVallFront.gif"> </td>
439     </tr>
440
441     <tr>
442          <td>One CPV module, perspective view                            </td>
443          <td>One CPV module, front view (extended in vertical direction) </td>
444     </tr>
445
446     <tr>
447          <td><img height=300 width=290 src="../images/CPVmodulePers.gif"></td>
448          <td><img height=300 width=290 src="../images/CPVmoduleSide.gif"></td>
449     </tr>
450
451     </table>
452
453     <H2>
454     Geant3 geometry tree of PHOS-CPV in ALICE
455     </H2>
456     <center>
457     <img height=300 width=290 src="../images/CPVtree.gif">
458     </center>
459   */
460   //END_HTML  
461
462   Float_t par[3], x,y,z;
463
464   // Get pointer to the array containing media indexes
465   Int_t *idtmed = fIdtmed->GetArray() - 699 ;
466
467   AliPHOSGeometry * geom = GetGeometry() ; 
468
469   // The box containing all CPV for one PHOS module filled with air 
470   par[0] = geom->GetCPVBoxSize(0) / 2.0 ;  
471   par[1] = geom->GetCPVBoxSize(1) / 2.0 ; 
472   par[2] = geom->GetCPVBoxSize(2) / 2.0 ;
473   gMC->Gsvolu("PCPV", "BOX ", idtmed[798], par, 3) ;
474
475   Float_t * emcParams = geom->GetEMCAGeometry()->GetEMCParams() ;
476   z = - emcParams[3] ;
477   Int_t rotm ;
478   AliMatrix(rotm, 90.,0., 0., 0., 90., 90.) ;
479
480   gMC->Gspos("PCPV", 1, "PHOS", 0.0, 0.0, z, rotm, "ONLY") ; 
481   
482   // Gassiplex board
483   
484   par[0] = geom->GetGassiplexChipSize(0)/2.;
485   par[1] = geom->GetGassiplexChipSize(1)/2.;
486   par[2] = geom->GetGassiplexChipSize(2)/2.;
487   gMC->Gsvolu("PCPC","BOX ",idtmed[707],par,3);
488   
489   // Cu+Ni foil covers Gassiplex board
490
491   par[1] = geom->GetCPVCuNiFoilThickness()/2;
492   gMC->Gsvolu("PCPD","BOX ",idtmed[710],par,3);
493   y      = -(geom->GetGassiplexChipSize(1)/2 - par[1]);
494   gMC->Gspos("PCPD",1,"PCPC",0,y,0,0,"ONLY");
495
496   // Position of the chip inside CPV
497
498   Float_t xStep = geom->GetCPVActiveSize(0) / (geom->GetNumberOfCPVChipsPhi() + 1);
499   Float_t zStep = geom->GetCPVActiveSize(1) / (geom->GetNumberOfCPVChipsZ()   + 1);
500   Int_t   copy  = 0;
501   y = geom->GetCPVFrameSize(1)/2           - geom->GetFTPosition(0) +
502     geom->GetCPVTextoliteThickness() / 2 + geom->GetGassiplexChipSize(1) / 2 + 0.1;
503   for (Int_t ix=0; ix<geom->GetNumberOfCPVChipsPhi(); ix++) {
504     x = xStep * (ix+1) - geom->GetCPVActiveSize(0)/2;
505     for (Int_t iz=0; iz<geom->GetNumberOfCPVChipsZ(); iz++) {
506       copy++;
507       z = zStep * (iz+1) - geom->GetCPVActiveSize(1)/2;
508       gMC->Gspos("PCPC",copy,"PCPV",x,y,z,0,"ONLY");
509     }
510   }
511
512   // Foiled textolite (1 mm of textolite + 50 mkm of Cu + 6 mkm of Ni)
513   
514   par[0] = geom->GetCPVActiveSize(0)        / 2;
515   par[1] = geom->GetCPVTextoliteThickness() / 2;
516   par[2] = geom->GetCPVActiveSize(1)        / 2;
517   gMC->Gsvolu("PCPF","BOX ",idtmed[707],par,3);
518
519   // Argon gas volume
520
521   par[1] = (geom->GetFTPosition(2) - geom->GetFTPosition(1) - geom->GetCPVTextoliteThickness()) / 2;
522   gMC->Gsvolu("PCPG","BOX ",idtmed[715],par,3);
523
524   for (Int_t i=0; i<4; i++) {
525     y = geom->GetCPVFrameSize(1) / 2 - geom->GetFTPosition(i) + geom->GetCPVTextoliteThickness()/2;
526     gMC->Gspos("PCPF",i+1,"PCPV",0,y,0,0,"ONLY");
527     if(i==1){
528       y-= (geom->GetFTPosition(2) - geom->GetFTPosition(1)) / 2;
529       gMC->Gspos("PCPG",1,"PCPV ",0,y,0,0,"ONLY");
530     }
531   }
532
533   // Dummy sensitive plane in the middle of argone gas volume
534
535   par[1]=0.001;
536   gMC->Gsvolu("PCPQ","BOX ",idtmed[715],par,3);
537   gMC->Gspos ("PCPQ",1,"PCPG",0,0,0,0,"ONLY");
538
539   // Cu+Ni foil covers textolite
540
541   par[1] = geom->GetCPVCuNiFoilThickness() / 2;
542   gMC->Gsvolu("PCP1","BOX ",idtmed[710],par,3);
543   y = geom->GetCPVTextoliteThickness()/2 - par[1];
544   gMC->Gspos ("PCP1",1,"PCPF",0,y,0,0,"ONLY");
545
546   // Aluminum frame around CPV
547
548   par[0] = geom->GetCPVFrameSize(0)/2;
549   par[1] = geom->GetCPVFrameSize(1)/2;
550   par[2] = geom->GetCPVBoxSize(2)  /2;
551   gMC->Gsvolu("PCF1","BOX ",idtmed[701],par,3);
552
553   par[0] = geom->GetCPVBoxSize(0)/2 - geom->GetCPVFrameSize(0);
554   par[1] = geom->GetCPVFrameSize(1)/2;
555   par[2] = geom->GetCPVFrameSize(2)/2;
556   gMC->Gsvolu("PCF2","BOX ",idtmed[701],par,3);
557
558   for (Int_t j=0; j<=1; j++) {
559     x = TMath::Sign(1,2*j-1) * (geom->GetCPVBoxSize(0) - geom->GetCPVFrameSize(0)) / 2;
560     gMC->Gspos("PCF1",j+1,"PCPV", x,0,0,0,"ONLY");
561     z = TMath::Sign(1,2*j-1) * (geom->GetCPVBoxSize(2) - geom->GetCPVFrameSize(2)) / 2;
562     gMC->Gspos("PCF2",j+1,"PCPV",0, 0,z,0,"ONLY");
563   }
564
565 }
566
567
568 //____________________________________________________________________________
569 void AliPHOSv0::CreateGeometryforSupport()
570 {
571   // Create the PHOS' support geometry for GEANT
572     //BEGIN_HTML
573   /*
574     <H2>
575     Geant3 geometry of the PHOS's support
576     </H2>
577     <P><CENTER>
578     <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/PHOS_support.gif"> 
579     </CENTER><P>
580   */
581   //END_HTML  
582   
583   Float_t par[5], x0,y0,z0 ; 
584   Int_t   i,j,copy;
585
586   // Get pointer to the array containing media indexes
587   Int_t *idtmed = fIdtmed->GetArray() - 699 ;
588
589   AliPHOSGeometry * geom = GetGeometry() ; 
590
591   // --- Dummy box containing two rails on which PHOS support moves
592   // --- Put these rails to the bottom of the L3 magnet
593
594   par[0] =  geom->GetRailRoadSize(0) / 2.0 ;
595   par[1] =  geom->GetRailRoadSize(1) / 2.0 ;
596   par[2] =  geom->GetRailRoadSize(2) / 2.0 ;
597   gMC->Gsvolu("PRRD", "BOX ", idtmed[798], par, 3) ;
598
599   y0     = -(geom->GetRailsDistanceFromIP() - geom->GetRailRoadSize(1) / 2.0) ;
600   gMC->Gspos("PRRD", 1, "ALIC", 0.0, y0, 0.0, 0, "ONLY") ; 
601
602   // --- Dummy box containing one rail
603
604   par[0] =  geom->GetRailOuterSize(0) / 2.0 ;
605   par[1] =  geom->GetRailOuterSize(1) / 2.0 ;
606   par[2] =  geom->GetRailOuterSize(2) / 2.0 ;
607   gMC->Gsvolu("PRAI", "BOX ", idtmed[798], par, 3) ;
608
609   for (i=0; i<2; i++) {
610     x0     = (2*i-1) * geom->GetDistanceBetwRails()  / 2.0 ;
611     gMC->Gspos("PRAI", i, "PRRD", x0, 0.0, 0.0, 0, "ONLY") ; 
612   }
613
614   // --- Upper and bottom steel parts of the rail
615
616   par[0] =  geom->GetRailPart1(0) / 2.0 ;
617   par[1] =  geom->GetRailPart1(1) / 2.0 ;
618   par[2] =  geom->GetRailPart1(2) / 2.0 ;
619   gMC->Gsvolu("PRP1", "BOX ", idtmed[716], par, 3) ;
620
621   y0     = - (geom->GetRailOuterSize(1) - geom->GetRailPart1(1))  / 2.0 ;
622   gMC->Gspos("PRP1", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
623   y0     =   (geom->GetRailOuterSize(1) - geom->GetRailPart1(1))  / 2.0 - geom->GetRailPart3(1);
624   gMC->Gspos("PRP1", 2, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
625
626   // --- The middle vertical steel parts of the rail
627
628   par[0] =  geom->GetRailPart2(0) / 2.0 ;
629   par[1] =  geom->GetRailPart2(1) / 2.0 ;
630   par[2] =  geom->GetRailPart2(2) / 2.0 ;
631   gMC->Gsvolu("PRP2", "BOX ", idtmed[716], par, 3) ;
632
633   y0     =   - geom->GetRailPart3(1) / 2.0 ;
634   gMC->Gspos("PRP2", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ; 
635
636   // --- The most upper steel parts of the rail
637
638   par[0] =  geom->GetRailPart3(0) / 2.0 ;
639   par[1] =  geom->GetRailPart3(1) / 2.0 ;
640   par[2] =  geom->GetRailPart3(2) / 2.0 ;
641   gMC->Gsvolu("PRP3", "BOX ", idtmed[716], par, 3) ;
642
643   y0     =   (geom->GetRailOuterSize(1) - geom->GetRailPart3(1))  / 2.0 ;
644   gMC->Gspos("PRP3", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ; 
645
646   // --- The wall of the cradle
647   // --- The wall is empty: steel thin walls and air inside
648
649   par[1] =  TMath::Sqrt(TMath::Power((geom->GetIPtoCPVDistance() + geom->GetOuterBoxSize(3)),2) +
650                         TMath::Power((geom->GetOuterBoxSize(1)/2),2))+10. ;
651   par[0] =  par[1] - geom->GetCradleWall(1) ;
652   par[2] =  geom->GetCradleWall(2) / 2.0 ;
653   par[3] =  geom->GetCradleWall(3) ;
654   par[4] =  geom->GetCradleWall(4) ;
655   gMC->Gsvolu("PCRA", "TUBS", idtmed[716], par, 5) ;
656
657   par[0] +=  geom->GetCradleWallThickness() ;
658   par[1] -=  geom->GetCradleWallThickness() ;
659   par[2] -=  geom->GetCradleWallThickness() ;
660   gMC->Gsvolu("PCRE", "TUBS", idtmed[798], par, 5) ;
661   gMC->Gspos ("PCRE", 1, "PCRA", 0.0, 0.0, 0.0, 0, "ONLY") ; 
662
663   for (i=0; i<2; i++) {
664     z0 = (2*i-1) * (geom->GetOuterBoxSize(2) + geom->GetCradleWall(2) )/ 2.0  ;
665         gMC->Gspos("PCRA", i, "ALIC", 0.0, 0.0, z0, 0, "ONLY") ; 
666   }
667
668   // --- The "wheels" of the cradle
669   
670   par[0] = geom->GetCradleWheel(0) / 2;
671   par[1] = geom->GetCradleWheel(1) / 2;
672   par[2] = geom->GetCradleWheel(2) / 2;
673   gMC->Gsvolu("PWHE", "BOX ", idtmed[716], par, 3) ;
674
675   y0 = -(geom->GetRailsDistanceFromIP() - geom->GetRailRoadSize(1) -
676          geom->GetCradleWheel(1)/2) ;
677   for (i=0; i<2; i++) {
678     z0 = (2*i-1) * ((geom->GetOuterBoxSize(2) + geom->GetCradleWheel(2))/ 2.0 +
679                     geom->GetCradleWall(2));
680     for (j=0; j<2; j++) {
681       copy = 2*i + j;
682       x0 = (2*j-1) * geom->GetDistanceBetwRails()  / 2.0 ;
683       gMC->Gspos("PWHE", copy, "ALIC", x0, y0, z0, 0, "ONLY") ; 
684     }
685   }
686
687 }
688
689 //_____________________________________________________________________________
690 void AliPHOSv0::AddAlignableVolumes() const
691 {
692   //
693   // Create entries for alignable volumes associating the symbolic volume
694   // name with the corresponding volume path. Needs to be syncronized with
695   // eventual changes in the geometry
696   // Alignable volumes are:
697   // 1) PHOS modules as a whole
698   // 2) Cradle
699   // 3) Cradle wheels
700   // 4) Strip units (group of 2x8 crystals)
701
702   TString volpath, symname;
703
704   // Alignable modules
705   // Volume path /ALIC_1/PHOS_<i> => symbolic name /PHOS/Module<i>, <i>=1,2,3,4,5
706   
707   AliGeomManager::ELayerID idPHOS1 = AliGeomManager::kPHOS1;
708   AliGeomManager::ELayerID idPHOS2 = AliGeomManager::kPHOS2;
709   Int_t modUID, modnum = 0;
710   TString physModulePath="/ALIC_1/PHOS_";
711   TString symbModuleName="PHOS/Module";
712   Int_t nModules = GetGeometry()->GetNModules();
713   
714   char im[5] ;
715   for(Int_t iModule=1; iModule<=nModules; iModule++){
716     sprintf(im,"%d",iModule) ;
717     modUID = AliGeomManager::LayerToVolUID(idPHOS1,modnum++);
718     if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
719       continue ;
720     volpath = physModulePath;
721     volpath += iModule;
722     //    volpath += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1";
723  
724    // Check the volume path if not all 5 modules exist
725     if (!gGeoManager->CheckPath(volpath.Data())) {                                                                                         
726       AliError(Form("Volume path %s not valid!",volpath.Data()));                                                                          
727       continue;                                                                                                                            
728     }                                                                                                                                      
729  
730     symname = symbModuleName;
731     symname += iModule;
732     if(!gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data(),modUID))
733       continue ;
734 //      AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", symname.Data(),volpath.Data()));
735
736     // Creates the Tracking to Local transformation matrix for PHOS modules
737     TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
738
739     Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
740     TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
741
742     TGeoHMatrix *matTtoL = new TGeoHMatrix;
743     matTtoL->RotateZ(-90.+angle);
744     matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
745     alignableEntry->SetMatrix(matTtoL);
746   }
747
748   //Aligning of CPV should be done for volume PCPV_1
749   symbModuleName="PHOS/Module";
750   modnum=0;
751   for(Int_t iModule=1; iModule<=nModules; iModule++){
752     if(strstr(GetTitle(),"noCPV"))
753       continue ;
754     sprintf(im,"%d",iModule) ;
755     modUID = AliGeomManager::LayerToVolUID(idPHOS2,modnum++);
756     if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0)
757       continue ;
758     volpath = physModulePath;
759     volpath += iModule;
760     volpath += "/PCPV_1";
761     // Check the volume path
762     if (!gGeoManager->CheckPath(volpath.Data())) {
763       AliError(Form("Volume path %s not valid!",volpath.Data()));
764       continue;
765     }
766
767     symname = symbModuleName;
768     symname += iModule;
769     symname += "/CPV";
770     if(!gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data(),modUID))
771       AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", symname.Data(),volpath.Data()));
772           
773     // Creates the TGeo Local to Tracking transformation matrix ...
774     TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
775
776     Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
777     TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
778
779     TGeoHMatrix *matTtoL = new TGeoHMatrix;
780     matTtoL->RotateZ(-90.+angle);
781     matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
782     alignableEntry->SetMatrix(matTtoL);
783     
784   }
785  
786
787   // Alignable cradle walls
788   // Volume path /ALIC_1/PCRA_<i> => symbolic name /PHOS/Cradle<i>, <i>=0,1
789
790   TString physCradlePath="/ALIC_1/PCRA_";
791   TString symbCradleName="PHOS/Cradle";
792   Int_t nCradles = 2;
793
794   for(Int_t iCradle=0; iCradle<nCradles; iCradle++){
795     volpath = physCradlePath;
796     volpath += iCradle;
797     symname = symbCradleName;
798     symname += iCradle;
799     gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
800   }
801
802   // Alignable wheels
803   // Volume path /ALIC_1/PWHE_<i> => symbolic name /PHOS/Wheel<i>, i=0,1,2,3
804
805   TString physWheelPath="/ALIC_1/PWHE_";
806   TString symbWheelName="PHOS/Wheel";
807   Int_t nWheels = 4;
808
809   for(Int_t iWheel=0; iWheel<nWheels; iWheel++){
810     volpath = physWheelPath;
811     volpath += iWheel;
812     symname = symbWheelName;
813     symname += iWheel;
814     gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
815   }
816
817   //Physical strip path is a combination of: physModulePath + module number + 
818   //physStripPath + strip number == ALIC_1/PHOS_N/..../PSTR_M
819   const Int_t nStripsX = GetGeometry()->GetEMCAGeometry()->GetNStripX();
820   const Int_t nStripsZ = GetGeometry()->GetEMCAGeometry()->GetNStripZ();
821   TString partialPhysStripName(100);
822   TString fullPhysStripName(100);
823   TString partialSymbStripName(100);
824   TString fullSymbStripName(100);
825
826   for(Int_t module = 1; module <= nModules; ++module){
827
828     sprintf(im,"%d",module) ;
829     if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
830       continue ;
831
832     volpath = physModulePath;
833     volpath += module;
834     // Check the volume path if not all 5 modules exist
835     if (!gGeoManager->CheckPath(volpath.Data())) {
836       AliError(Form("Volume path %s does not exist",volpath.Data())) ;
837       continue;
838     }
839
840     partialPhysStripName  = physModulePath;
841     partialPhysStripName += module;
842     partialPhysStripName += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1/PSTR_";
843
844     partialSymbStripName  = symbModuleName;
845     partialSymbStripName += module;
846     partialSymbStripName += "/Strip_";
847
848     for(Int_t i = 0, ind1D = 1; i < nStripsX; ++i){//ind1D starts from 1 (PSTR_1...PSTR_224...)
849       for(Int_t j = 0; j < nStripsZ; ++j, ++ind1D){
850          fullPhysStripName = partialPhysStripName;
851          fullPhysStripName += ind1D;
852          
853          fullSymbStripName  = partialSymbStripName;
854          fullSymbStripName += i;//ind1D;
855          fullSymbStripName += '_';
856          fullSymbStripName += j;
857
858          gGeoManager->SetAlignableEntry(fullSymbStripName.Data(), fullPhysStripName.Data());
859
860          // Creates the TGeo Local to Tracking transformation matrix ...
861          TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntry(fullSymbStripName.Data()) ;
862          const char *path = alignableEntry->GetTitle();
863          if (!gGeoManager->cd(path))
864            AliFatal(Form("Volume path %s not valid!",path));
865          TGeoHMatrix matLtoT = *gGeoManager->GetCurrentMatrix() ;
866          Double_t refl[3]={-1.,-1.,-1.} ;
867          matLtoT.SetScale(refl) ;
868          TGeoHMatrix *matTtoL = new TGeoHMatrix(matLtoT.Inverse());
869  
870          char phosPath[50] ;
871          sprintf(phosPath,"/ALIC_1/PHOS_%d",module) ;
872          if (!gGeoManager->cd(phosPath)){
873             AliFatal("Geo manager can not find path \n");
874          }
875          TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
876          if (mPHOS) 
877            matTtoL->Multiply(mPHOS);
878          else{
879            AliFatal("Geo matrixes are not loaded \n") ;
880          }
881          //Switch y<->z
882          Double_t rot[9]={1.,0.,0.,  0.,1.,0., 0.,0.,1.} ;
883          matTtoL->SetRotation(rot) ;
884          alignableEntry->SetMatrix(matTtoL);
885
886 /*
887   //Check poisition of corner cell of the strip
888   AliPHOSGeometry * geom = AliPHOSGeometry::GetInstance() ;
889   Int_t relid[4] ; 
890   relid[0] = module ;
891   relid[1] = 0 ;
892   Int_t iStrip=ind1D ;
893   Int_t icell=1 ;
894   Int_t raw = geom->GetEMCAGeometry()->GetNCellsXInStrip()*((iStrip-1)/geom->GetEMCAGeometry()->GetNStripZ()) +
895                 1 + (icell-1)/geom->GetEMCAGeometry()->GetNCellsZInStrip() ;
896   Int_t col = geom->GetEMCAGeometry()->GetNCellsZInStrip()*(1+(iStrip-1)%geom->GetEMCAGeometry()->GetNStripZ()) - 
897                 (icell-1)%geom->GetEMCAGeometry()->GetNCellsZInStrip() ;
898   if(col==0) col=geom->GetNZ() ;
899   relid[2] = raw ;
900   relid[3] = col ;
901   Float_t xG,zG ; 
902   geom->RelPosInModule(relid, xG, zG) ;
903 printf("============\n") ;
904 printf("Geometry: x=%f, z=%f \n",xG,zG) ;
905   Int_t absid ; 
906   geom->RelToAbsNumbering(relid,absid) ;
907   Double_t pos[3]= {-2.2*3.5,0.0,1.1}; //Position incide the strip (Y coordinalte is not important)
908   Double_t posC[3]={0.0,0.0,0.}; //Global position
909  
910   matTtoL->MasterToLocal(pos,posC);
911 printf("Matrix:   x=%f, z=%f, y=%f \n",posC[0],posC[2],posC[1]) ;
912 */
913       }
914     }
915   }
916 }
917
918 //____________________________________________________________________________
919 Float_t AliPHOSv0::ZMin(void) const
920 {
921   // Overall dimension of the PHOS (min)
922
923   AliPHOSGeometry * geom = GetGeometry() ; 
924
925   return -geom->GetOuterBoxSize(2)/2.;
926 }
927
928 //____________________________________________________________________________
929 Float_t AliPHOSv0::ZMax(void) const
930 {
931   // Overall dimension of the PHOS (max)
932
933   AliPHOSGeometry * geom = GetGeometry() ; 
934
935   return  geom->GetOuterBoxSize(2)/2.;
936 }
937
938 //____________________________________________________________________________
939 void AliPHOSv0::Init(void)
940 {
941   // Just prints an information message
942   
943   Int_t i;
944
945   if(AliLog::GetGlobalDebugLevel()>0) {
946     TString st ; 
947     for(i=0;i<35;i++) 
948       st += "*";
949     Info("Init", "%s", st.Data()) ;  
950     // Here the PHOS initialisation code (if any!)
951     
952     AliPHOSGeometry * geom = GetGeometry() ; 
953
954     if (geom!=0)  
955       Info("Init", "AliPHOS%s: PHOS geometry intialized for %s", Version().Data(), geom->GetName()) ;
956     else
957       Info("Init", "AliPHOS%s: PHOS geometry initialization failed !", Version().Data()) ;       
958
959     Info("Init", "%s", st.Data()) ;  
960   }
961 }