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