1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 /* History of cvs commits:
20 * Revision 1.94 2007/10/18 08:40:02 kharlov
21 * Misalignment-related bug fixed
23 * Revision 1.93 2007/10/06 22:24:40 kharlov
24 * Bug in strip unit geometry is corrected
26 * Revision 1.92 2007/07/04 16:38:19 policheh
27 * Tracking2LocalCS matrices corrected for CPV.
29 * Revision 1.91 2007/07/02 14:50:49 policheh
30 * Tracking2LocalCS matrices corrected.
32 * Revision 1.90 2007/05/24 13:04:05 policheh
33 * AddAlignableVolumes: local to tracking CS transformation matrices creates for each
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
39 * Revision 1.88 2007/04/19 15:28:30 kharlov
40 * Modify strip unit geometry according to the final drawings (Timur)
42 * Revision 1.87 2007/04/01 07:37:10 kharlov
43 * TGeo RS to Local RS transf matr added
45 * Revision 1.86 2007/03/06 06:55:46 kharlov
46 * DP:Misalignment of CPV added
48 * Revision 1.85 2007/03/01 11:37:37 kharlov
49 * Strip units changed from 8x1 to 8x2 (T.Pocheptsov)
51 * Revision 1.84 2006/12/20 16:56:43 kharlov
52 * Optional geometry without CPV
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
57 * Revision 1.82 2006/09/27 19:55:57 kharlov
58 * Alignment object with symbolic volume names are introduced
60 * Revision 1.81 2006/03/04 20:25:56 kharlov
61 * Set geom parameters from CDB
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
66 * Revision 1.79 2005/05/28 14:19:05 schutz
67 * Compilation warnings fixed by T.P.
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
76 //*-- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (RRC KI & SUBATECH)
79 // --- ROOT system ---
82 #include <TGeometry.h>
86 #include <TVirtualMC.h>
87 #include <TGeoPhysicalNode.h>
88 #include <TGeoManager.h>
89 #include <TGeoMatrix.h>
92 // --- Standard library ---
97 // --- AliRoot header files ---
100 #include "AliPHOSGeometry.h"
101 #include "AliPHOSLoader.h"
102 #include "AliPHOSv0.h"
105 #include "AliGeomManager.h"
109 //____________________________________________________________________________
110 AliPHOSv0::AliPHOSv0(const char *name, const char *title):
113 // ctor : title is used to identify the layout
117 //____________________________________________________________________________
118 void AliPHOSv0::CreateGeometry()
120 // Create the PHOS geometry for Geant
122 AliPHOSv0 *phostmp = dynamic_cast<AliPHOSv0*>(gAlice->GetModule("PHOS")) ;
124 if ( phostmp == NULL ) {
126 fprintf(stderr, "PHOS detector not found!\n") ;
131 AliPHOSGeometry * geom = GetGeometry() ;
133 // Get pointer to the array containing media indeces
134 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
136 // Create a PHOS module.
138 gMC->Gsvolu("PHOS", "TRD1", idtmed[798], geom->GetPHOSParams(), 4) ;
140 this->CreateGeometryforEMC() ;
142 if (strstr(fTitle.Data(),"noCPV") == 0)
143 this->CreateGeometryforCPV() ;
145 this->CreateGeometryforSupport() ;
147 // --- Position PHOS mdules in ALICE setup ---
151 Bool_t anyModuleCreated=0 ;
152 for (Int_t iModule = 0; iModule < 5 ; iModule++ ) {
153 snprintf(im,5,"%d",iModule+1) ;
154 if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
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]) ;
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") ;
172 if(!anyModuleCreated)
173 AliError("No one PHOS module was created") ;
176 //____________________________________________________________________________
177 void AliPHOSv0::CreateGeometryforEMC()
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)
189 Geant3 geometry tree of PHOS-EMC in ALICE
192 <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/EMCinAlice.gif">
197 // Get pointer to the array containing media indexes
198 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
200 AliPHOSGeometry * geom = GetGeometry() ;
201 AliPHOSEMCAGeometry * emcg = geom->GetEMCAGeometry() ;
205 // ======= Define the strip ===============
207 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetStripHalfSize() + ipar);
208 gMC->Gsvolu("PSTR", "BOX ", idtmed[716], par, 3) ; //Made of steel
210 // --- define steel volume (cell of the strip unit)
211 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetAirCellHalfSize() + ipar);
212 gMC->Gsvolu("PCEL", "BOX ", idtmed[798], par, 3);
214 // --- define wrapped crystal and put it into steel cell
216 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetWrappedHalfSize() + ipar);
217 gMC->Gsvolu("PWRA", "BOX ", idtmed[702], par, 3);
218 const Float_t * pin = emcg->GetAPDHalfSize() ;
219 const Float_t * preamp = emcg->GetPreampHalfSize() ;
220 Float_t y = (emcg->GetAirGapLed()-2*pin[1]-2*preamp[1])/2;
221 gMC->Gspos("PWRA", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ;
223 // --- Define crystal and put it into wrapped crystall ---
224 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetCrystalHalfSize() + ipar);
225 gMC->Gsvolu("PXTL", "BOX ", idtmed[699], par, 3) ;
226 gMC->Gspos("PXTL", 1, "PWRA", 0.0, 0.0, 0.0, 0, "ONLY") ;
228 // --- define APD/PIN preamp and put it into AirCell
230 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetAPDHalfSize() + ipar);
231 gMC->Gsvolu("PPIN", "BOX ", idtmed[705], par, 3) ;
232 const Float_t * crystal = emcg->GetCrystalHalfSize() ;
233 y = crystal[1] + emcg->GetAirGapLed() /2 - preamp[1];
234 gMC->Gspos("PPIN", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ;
235 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetPreampHalfSize() + ipar);
236 gMC->Gsvolu("PREA", "BOX ", idtmed[711], par, 3) ; // Here I assumed preamp as a printed Circuit
237 y = crystal[1] + emcg->GetAirGapLed() /2 + pin[1] ; // May it should be changed
238 gMC->Gspos("PREA", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ; // to ceramics?
241 // --- Fill strip with wrapped cristals in steel cells
243 const Float_t* splate = emcg->GetSupportPlateHalfSize();
245 const Float_t* acel = emcg->GetAirCellHalfSize() ;
247 for(Int_t lev = 2, icel = 1;
248 icel <= emcg->GetNCellsXInStrip()*emcg->GetNCellsZInStrip();
249 icel += 2, lev += 2) {
250 Float_t x = (2*(lev / 2) - 1 - emcg->GetNCellsXInStrip())* acel[0] ;
252 gMC->Gspos("PCEL", icel, "PSTR", x, y, +z, 0, "ONLY") ;
253 gMC->Gspos("PCEL", icel + 1, "PSTR", x, y, -z, 0, "ONLY") ;
256 // --- define the support plate, hole in it and position it in strip ----
257 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetSupportPlateHalfSize() + ipar);
258 gMC->Gsvolu("PSUP", "BOX ", idtmed[701], par, 3) ;
260 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetSupportPlateInHalfSize() + ipar);
261 gMC->Gsvolu("PSHO", "BOX ", idtmed[798], par, 3) ;
262 Float_t z = emcg->GetSupportPlateThickness()/2 ;
263 gMC->Gspos("PSHO", 1, "PSUP", 0.0, 0.0, z, 0, "ONLY") ;
266 gMC->Gspos("PSUP", 1, "PSTR", 0.0, y, 0.0, 0, "ONLY") ;
269 // ========== Fill module with strips and put them into inner thermoinsulation=============
270 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetInnerThermoHalfSize() + ipar);
271 gMC->Gsvolu("PTII", "BOX ", idtmed[706], par, 3) ;
273 const Float_t * inthermo = emcg->GetInnerThermoHalfSize() ;
274 const Float_t * strip = emcg->GetStripHalfSize() ;
275 y = inthermo[1] - strip[1] ;
280 for(irow = 0; irow < emcg->GetNStripX(); irow ++){
281 Float_t x = (2*irow + 1 - emcg->GetNStripX())* strip[0] ;
282 for(icol = 0; icol < emcg->GetNStripZ(); icol ++){
283 z = (2*icol + 1 - emcg->GetNStripZ()) * strip[2] ;
284 gMC->Gspos("PSTR", nr, "PTII", x, y, z, 0, "ONLY") ;
290 // ------- define the air gap between thermoinsulation and cooler
291 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetAirGapHalfSize() + ipar);
292 gMC->Gsvolu("PAGA", "BOX ", idtmed[798], par, 3) ;
293 const Float_t * agap = emcg->GetAirGapHalfSize() ;
294 y = agap[1] - inthermo[1] ;
296 gMC->Gspos("PTII", 1, "PAGA", 0.0, y, 0.0, 0, "ONLY") ;
299 // ------- define the Al passive cooler
300 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetCoolerHalfSize() + ipar);
301 gMC->Gsvolu("PCOR", "BOX ", idtmed[701], par, 3) ;
302 const Float_t * cooler = emcg->GetCoolerHalfSize() ;
303 y = cooler[1] - agap[1] ;
305 gMC->Gspos("PAGA", 1, "PCOR", 0.0, y, 0.0, 0, "ONLY") ;
307 // ------- define the outer thermoinsulating cover
308 for (ipar=0; ipar<4; ipar++) par[ipar] = *(emcg->GetOuterThermoParams() + ipar);
309 gMC->Gsvolu("PTIO", "TRD1", idtmed[706], par, 4) ;
310 const Float_t * outparams = emcg->GetOuterThermoParams() ;
313 AliMatrix(idrotm[1], 90.0, 0.0, 0.0, 0.0, 90.0, 270.0) ;
314 // Frame in outer thermoinsulation and so on: z out of beam, y along beam, x across beam
316 z = outparams[3] - cooler[1] ;
317 gMC->Gspos("PCOR", 1, "PTIO", 0., 0.0, z, idrotm[1], "ONLY") ;
319 // -------- Define the outer Aluminium cover -----
320 for (ipar=0; ipar<4; ipar++) par[ipar] = *(emcg->GetAlCoverParams() + ipar);
321 gMC->Gsvolu("PCOL", "TRD1", idtmed[701], par, 4) ;
322 const Float_t * covparams = emcg->GetAlCoverParams() ;
323 z = covparams[3] - outparams[3] ;
324 gMC->Gspos("PTIO", 1, "PCOL", 0., 0.0, z, 0, "ONLY") ;
326 // --------- Define front fiberglass cover -----------
327 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetFiberGlassHalfSize() + ipar);
328 gMC->Gsvolu("PFGC", "BOX ", idtmed[717], par, 3) ;
330 gMC->Gspos("PFGC", 1, "PCOL", 0., 0.0, z, 0, "ONLY") ;
332 //=============This is all with cold section==============
335 //------ Warm Section --------------
336 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetWarmAlCoverHalfSize() + ipar);
337 gMC->Gsvolu("PWAR", "BOX ", idtmed[701], par, 3) ;
338 const Float_t * warmcov = emcg->GetWarmAlCoverHalfSize() ;
340 // --- Define the outer thermoinsulation ---
341 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetWarmThermoHalfSize() + ipar);
342 gMC->Gsvolu("PWTI", "BOX ", idtmed[706], par, 3) ;
343 const Float_t * warmthermo = emcg->GetWarmThermoHalfSize() ;
344 z = -warmcov[2] + warmthermo[2] ;
346 gMC->Gspos("PWTI", 1, "PWAR", 0., 0.0, z, 0, "ONLY") ;
348 // --- Define cables area and put in it T-supports ----
349 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetTCables1HalfSize() + ipar);
350 gMC->Gsvolu("PCA1", "BOX ", idtmed[718], par, 3) ;
351 const Float_t * cbox = emcg->GetTCables1HalfSize() ;
353 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetTSupport1HalfSize() + ipar);
354 gMC->Gsvolu("PBE1", "BOX ", idtmed[701], par, 3) ;
355 const Float_t * beams = emcg->GetTSupport1HalfSize() ;
357 for(isup = 0; isup < emcg->GetNTSuppots(); isup++){
358 Float_t x = -cbox[0] + beams[0] + (2*beams[0]+emcg->GetTSupportDist())*isup ;
359 gMC->Gspos("PBE1", isup, "PCA1", x, 0.0, 0.0, 0, "ONLY") ;
362 z = -warmthermo[2] + cbox[2];
363 gMC->Gspos("PCA1", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;
365 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetTCables2HalfSize() + ipar);
366 gMC->Gsvolu("PCA2", "BOX ", idtmed[718], par, 3) ;
367 const Float_t * cbox2 = emcg->GetTCables2HalfSize() ;
369 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetTSupport2HalfSize() + ipar);
370 gMC->Gsvolu("PBE2", "BOX ", idtmed[701], par, 3) ;
371 for(isup = 0; isup < emcg->GetNTSuppots(); isup++){
372 Float_t x = -cbox[0] + beams[0] + (2*beams[0]+emcg->GetTSupportDist())*isup ;
373 gMC->Gspos("PBE2", isup, "PCA2", x, 0.0, 0.0, 0, "ONLY") ;
376 z = -warmthermo[2] + 2*cbox[2] + cbox2[2];
377 gMC->Gspos("PCA2", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;
380 // --- Define frame ---
381 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetFrameXHalfSize() + ipar);
382 gMC->Gsvolu("PFRX", "BOX ", idtmed[716], par, 3) ;
383 const Float_t * posit1 = emcg->GetFrameXPosition() ;
384 gMC->Gspos("PFRX", 1, "PWTI", posit1[0], posit1[1], posit1[2], 0, "ONLY") ;
385 gMC->Gspos("PFRX", 2, "PWTI", posit1[0], -posit1[1], posit1[2], 0, "ONLY") ;
387 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetFrameZHalfSize() + ipar);
388 gMC->Gsvolu("PFRZ", "BOX ", idtmed[716], par, 3) ;
389 const Float_t * posit2 = emcg->GetFrameZPosition() ;
390 gMC->Gspos("PFRZ", 1, "PWTI", posit2[0], posit2[1], posit2[2], 0, "ONLY") ;
391 gMC->Gspos("PFRZ", 2, "PWTI", -posit2[0], posit2[1], posit2[2], 0, "ONLY") ;
393 // --- Define Fiber Glass support ---
394 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetFGupXHalfSize() + ipar);
395 gMC->Gsvolu("PFG1", "BOX ", idtmed[717], par, 3) ;
396 const Float_t * posit3 = emcg->GetFGupXPosition() ;
397 gMC->Gspos("PFG1", 1, "PWTI", posit3[0], posit3[1], posit3[2], 0, "ONLY") ;
398 gMC->Gspos("PFG1", 2, "PWTI", posit3[0], -posit3[1], posit3[2], 0, "ONLY") ;
400 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetFGupZHalfSize() + ipar);
401 gMC->Gsvolu("PFG2", "BOX ", idtmed[717], par, 3) ;
402 const Float_t * posit4 = emcg->GetFGupZPosition();
403 gMC->Gspos("PFG2", 1, "PWTI", posit4[0], posit4[1], posit4[2], 0, "ONLY") ;
404 gMC->Gspos("PFG2", 2, "PWTI", -posit4[0], posit4[1], posit4[2], 0, "ONLY") ;
406 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetFGlowXHalfSize() + ipar);
407 gMC->Gsvolu("PFG3", "BOX ", idtmed[717], par, 3) ;
408 const Float_t * posit5 = emcg->GetFGlowXPosition() ;
409 gMC->Gspos("PFG3", 1, "PWTI", posit5[0], posit5[1], posit5[2], 0, "ONLY") ;
410 gMC->Gspos("PFG3", 2, "PWTI", posit5[0], -posit5[1], posit5[2], 0, "ONLY") ;
412 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetFGlowZHalfSize() + ipar);
413 gMC->Gsvolu("PFG4", "BOX ", idtmed[717], par, 3) ;
414 const Float_t * posit6 = emcg->GetFGlowZPosition() ;
415 gMC->Gspos("PFG4", 1, "PWTI", posit6[0], posit6[1], posit6[2], 0, "ONLY") ;
416 gMC->Gspos("PFG4", 2, "PWTI", -posit6[0], posit6[1], posit6[2], 0, "ONLY") ;
418 // --- Define Air Gap for FEE electronics -----
420 for (ipar=0; ipar<3; ipar++) par[ipar] = *(emcg->GetFEEAirHalfSize() + ipar);
421 gMC->Gsvolu("PAFE", "BOX ", idtmed[798], par, 3) ;
422 const Float_t * posit7 = emcg->GetFEEAirPosition() ;
423 gMC->Gspos("PAFE", 1, "PWTI", posit7[0], posit7[1], posit7[2], 0, "ONLY") ;
425 // Define the EMC module volume and combine Cool and Warm sections
427 for (ipar=0; ipar<4; ipar++) par[ipar] = *(emcg->GetEMCParams() + ipar);
428 gMC->Gsvolu("PEMC", "TRD1", idtmed[798], par, 4) ;
430 gMC->Gspos("PCOL", 1, "PEMC", 0., 0., z, 0, "ONLY") ;
432 gMC->Gspos("PWAR", 1, "PEMC", 0., 0., z, 0, "ONLY") ;
435 // Put created EMC geometry into PHOS volume
437 z = geom->GetCPVBoxSize(1) / 2. ;
438 gMC->Gspos("PEMC", 1, "PHOS", 0., 0., z, 0, "ONLY") ;
442 //____________________________________________________________________________
443 void AliPHOSv0::CreateGeometryforCPV()
445 // Create the PHOS-CPV geometry for GEANT
446 // Author: Yuri Kharlov 11 September 2000
450 Geant3 geometry of PHOS-CPV in ALICE
455 <td>CPV perspective view</td>
456 <td>CPV front view </td>
460 <td> <img height=300 width=290 src="../images/CPVallPersp.gif"> </td>
461 <td> <img height=300 width=290 src="../images/CPVallFront.gif"> </td>
465 <td>One CPV module, perspective view </td>
466 <td>One CPV module, front view (extended in vertical direction) </td>
470 <td><img height=300 width=290 src="../images/CPVmodulePers.gif"></td>
471 <td><img height=300 width=290 src="../images/CPVmoduleSide.gif"></td>
477 Geant3 geometry tree of PHOS-CPV in ALICE
480 <img height=300 width=290 src="../images/CPVtree.gif">
485 Float_t par[3], x,y,z;
487 // Get pointer to the array containing media indexes
488 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
490 AliPHOSGeometry * geom = GetGeometry() ;
492 // The box containing all CPV for one PHOS module filled with air
493 par[0] = geom->GetCPVBoxSize(0) / 2.0 ;
494 par[1] = geom->GetCPVBoxSize(1) / 2.0 ;
495 par[2] = geom->GetCPVBoxSize(2) / 2.0 ;
496 gMC->Gsvolu("PCPV", "BOX ", idtmed[798], par, 3) ;
498 const Float_t * emcParams = geom->GetEMCAGeometry()->GetEMCParams() ;
501 AliMatrix(rotm, 90.,0., 0., 0., 90., 90.) ;
503 gMC->Gspos("PCPV", 1, "PHOS", 0.0, 0.0, z, rotm, "ONLY") ;
507 par[0] = geom->GetGassiplexChipSize(0)/2.;
508 par[1] = geom->GetGassiplexChipSize(1)/2.;
509 par[2] = geom->GetGassiplexChipSize(2)/2.;
510 gMC->Gsvolu("PCPC","BOX ",idtmed[707],par,3);
512 // Cu+Ni foil covers Gassiplex board
514 par[1] = geom->GetCPVCuNiFoilThickness()/2;
515 gMC->Gsvolu("PCPD","BOX ",idtmed[710],par,3);
516 y = -(geom->GetGassiplexChipSize(1)/2 - par[1]);
517 gMC->Gspos("PCPD",1,"PCPC",0,y,0,0,"ONLY");
519 // Position of the chip inside CPV
521 Float_t xStep = geom->GetCPVActiveSize(0) / (geom->GetNumberOfCPVChipsPhi() + 1);
522 Float_t zStep = geom->GetCPVActiveSize(1) / (geom->GetNumberOfCPVChipsZ() + 1);
524 y = geom->GetCPVFrameSize(1)/2 - geom->GetFTPosition(0) +
525 geom->GetCPVTextoliteThickness() / 2 + geom->GetGassiplexChipSize(1) / 2 + 0.1;
526 for (Int_t ix=0; ix<geom->GetNumberOfCPVChipsPhi(); ix++) {
527 x = xStep * (ix+1) - geom->GetCPVActiveSize(0)/2;
528 for (Int_t iz=0; iz<geom->GetNumberOfCPVChipsZ(); iz++) {
530 z = zStep * (iz+1) - geom->GetCPVActiveSize(1)/2;
531 gMC->Gspos("PCPC",copy,"PCPV",x,y,z,0,"ONLY");
535 // Foiled textolite (1 mm of textolite + 50 mkm of Cu + 6 mkm of Ni)
537 par[0] = geom->GetCPVActiveSize(0) / 2;
538 par[1] = geom->GetCPVTextoliteThickness() / 2;
539 par[2] = geom->GetCPVActiveSize(1) / 2;
540 gMC->Gsvolu("PCPF","BOX ",idtmed[707],par,3);
544 par[1] = (geom->GetFTPosition(2) - geom->GetFTPosition(1) - geom->GetCPVTextoliteThickness()) / 2;
545 gMC->Gsvolu("PCPG","BOX ",idtmed[715],par,3);
547 for (Int_t i=0; i<4; i++) {
548 y = geom->GetCPVFrameSize(1) / 2 - geom->GetFTPosition(i) + geom->GetCPVTextoliteThickness()/2;
549 gMC->Gspos("PCPF",i+1,"PCPV",0,y,0,0,"ONLY");
551 y-= (geom->GetFTPosition(2) - geom->GetFTPosition(1)) / 2;
552 gMC->Gspos("PCPG",1,"PCPV ",0,y,0,0,"ONLY");
556 // Dummy sensitive plane in the middle of argone gas volume
559 gMC->Gsvolu("PCPQ","BOX ",idtmed[715],par,3);
560 gMC->Gspos ("PCPQ",1,"PCPG",0,0,0,0,"ONLY");
562 // Cu+Ni foil covers textolite
564 par[1] = geom->GetCPVCuNiFoilThickness() / 2;
565 gMC->Gsvolu("PCP1","BOX ",idtmed[710],par,3);
566 y = geom->GetCPVTextoliteThickness()/2 - par[1];
567 gMC->Gspos ("PCP1",1,"PCPF",0,y,0,0,"ONLY");
569 // Aluminum frame around CPV
571 par[0] = geom->GetCPVFrameSize(0)/2;
572 par[1] = geom->GetCPVFrameSize(1)/2;
573 par[2] = geom->GetCPVBoxSize(2) /2;
574 gMC->Gsvolu("PCF1","BOX ",idtmed[701],par,3);
576 par[0] = geom->GetCPVBoxSize(0)/2 - geom->GetCPVFrameSize(0);
577 par[1] = geom->GetCPVFrameSize(1)/2;
578 par[2] = geom->GetCPVFrameSize(2)/2;
579 gMC->Gsvolu("PCF2","BOX ",idtmed[701],par,3);
581 for (Int_t j=0; j<=1; j++) {
582 x = TMath::Sign(1,2*j-1) * (geom->GetCPVBoxSize(0) - geom->GetCPVFrameSize(0)) / 2;
583 gMC->Gspos("PCF1",j+1,"PCPV", x,0,0,0,"ONLY");
584 z = TMath::Sign(1,2*j-1) * (geom->GetCPVBoxSize(2) - geom->GetCPVFrameSize(2)) / 2;
585 gMC->Gspos("PCF2",j+1,"PCPV",0, 0,z,0,"ONLY");
591 //____________________________________________________________________________
592 void AliPHOSv0::CreateGeometryforSupport()
594 // Create the PHOS' support geometry for GEANT
598 Geant3 geometry of the PHOS's support
601 <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/PHOS_support.gif">
606 Float_t par[5], x0,y0,z0 ;
609 // Get pointer to the array containing media indexes
610 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
612 AliPHOSGeometry * geom = GetGeometry() ;
614 // --- Dummy box containing two rails on which PHOS support moves
615 // --- Put these rails to the bottom of the L3 magnet
617 par[0] = geom->GetRailRoadSize(0) / 2.0 ;
618 par[1] = geom->GetRailRoadSize(1) / 2.0 ;
619 par[2] = geom->GetRailRoadSize(2) / 2.0 ;
620 gMC->Gsvolu("PRRD", "BOX ", idtmed[798], par, 3) ;
622 y0 = -(geom->GetRailsDistanceFromIP() - geom->GetRailRoadSize(1) / 2.0) ;
623 gMC->Gspos("PRRD", 1, "ALIC", 0.0, y0, 0.0, 0, "ONLY") ;
625 // --- Dummy box containing one rail
627 par[0] = geom->GetRailOuterSize(0) / 2.0 ;
628 par[1] = geom->GetRailOuterSize(1) / 2.0 ;
629 par[2] = geom->GetRailOuterSize(2) / 2.0 ;
630 gMC->Gsvolu("PRAI", "BOX ", idtmed[798], par, 3) ;
632 for (i=0; i<2; i++) {
633 x0 = (2*i-1) * geom->GetDistanceBetwRails() / 2.0 ;
634 gMC->Gspos("PRAI", i, "PRRD", x0, 0.0, 0.0, 0, "ONLY") ;
637 // --- Upper and bottom steel parts of the rail
639 par[0] = geom->GetRailPart1(0) / 2.0 ;
640 par[1] = geom->GetRailPart1(1) / 2.0 ;
641 par[2] = geom->GetRailPart1(2) / 2.0 ;
642 gMC->Gsvolu("PRP1", "BOX ", idtmed[716], par, 3) ;
644 y0 = - (geom->GetRailOuterSize(1) - geom->GetRailPart1(1)) / 2.0 ;
645 gMC->Gspos("PRP1", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
646 y0 = (geom->GetRailOuterSize(1) - geom->GetRailPart1(1)) / 2.0 - geom->GetRailPart3(1);
647 gMC->Gspos("PRP1", 2, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
649 // --- The middle vertical steel parts of the rail
651 par[0] = geom->GetRailPart2(0) / 2.0 ;
652 par[1] = geom->GetRailPart2(1) / 2.0 ;
653 par[2] = geom->GetRailPart2(2) / 2.0 ;
654 gMC->Gsvolu("PRP2", "BOX ", idtmed[716], par, 3) ;
656 y0 = - geom->GetRailPart3(1) / 2.0 ;
657 gMC->Gspos("PRP2", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
659 // --- The most upper steel parts of the rail
661 par[0] = geom->GetRailPart3(0) / 2.0 ;
662 par[1] = geom->GetRailPart3(1) / 2.0 ;
663 par[2] = geom->GetRailPart3(2) / 2.0 ;
664 gMC->Gsvolu("PRP3", "BOX ", idtmed[716], par, 3) ;
666 y0 = (geom->GetRailOuterSize(1) - geom->GetRailPart3(1)) / 2.0 ;
667 gMC->Gspos("PRP3", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
669 // --- The wall of the cradle
670 // --- The wall is empty: steel thin walls and air inside
672 par[1] = TMath::Sqrt(TMath::Power((geom->GetIPtoCPVDistance() + geom->GetOuterBoxSize(3)),2) +
673 TMath::Power((geom->GetOuterBoxSize(1)/2),2))+10. ;
674 par[0] = par[1] - geom->GetCradleWall(1) ;
675 par[2] = geom->GetCradleWall(2) / 2.0 ;
676 par[3] = geom->GetCradleWall(3) ;
677 par[4] = geom->GetCradleWall(4) ;
678 gMC->Gsvolu("PCRA", "TUBS", idtmed[716], par, 5) ;
680 par[0] += geom->GetCradleWallThickness() ;
681 par[1] -= geom->GetCradleWallThickness() ;
682 par[2] -= geom->GetCradleWallThickness() ;
683 gMC->Gsvolu("PCRE", "TUBS", idtmed[798], par, 5) ;
684 gMC->Gspos ("PCRE", 1, "PCRA", 0.0, 0.0, 0.0, 0, "ONLY") ;
686 for (i=0; i<2; i++) {
687 z0 = (2*i-1) * (geom->GetOuterBoxSize(2) + geom->GetCradleWall(2) )/ 2.0 ;
688 gMC->Gspos("PCRA", i, "ALIC", 0.0, 0.0, z0, 0, "ONLY") ;
691 // --- The "wheels" of the cradle
693 par[0] = geom->GetCradleWheel(0) / 2;
694 par[1] = geom->GetCradleWheel(1) / 2;
695 par[2] = geom->GetCradleWheel(2) / 2;
696 gMC->Gsvolu("PWHE", "BOX ", idtmed[716], par, 3) ;
698 y0 = -(geom->GetRailsDistanceFromIP() - geom->GetRailRoadSize(1) -
699 geom->GetCradleWheel(1)/2) ;
700 for (i=0; i<2; i++) {
701 z0 = (2*i-1) * ((geom->GetOuterBoxSize(2) + geom->GetCradleWheel(2))/ 2.0 +
702 geom->GetCradleWall(2));
703 for (j=0; j<2; j++) {
705 x0 = (2*j-1) * geom->GetDistanceBetwRails() / 2.0 ;
706 gMC->Gspos("PWHE", copy, "ALIC", x0, y0, z0, 0, "ONLY") ;
712 //_____________________________________________________________________________
713 void AliPHOSv0::AddAlignableVolumes() const
716 // Create entries for alignable volumes associating the symbolic volume
717 // name with the corresponding volume path. Needs to be syncronized with
718 // eventual changes in the geometry
719 // Alignable volumes are:
720 // 1) PHOS modules as a whole
723 // 4) Strip units (group of 2x8 crystals)
725 TString volpath, symname;
728 // Volume path /ALIC_1/PHOS_<i> => symbolic name /PHOS/Module<i>, <i>=1,2,3,4,5
730 AliGeomManager::ELayerID idPHOS1 = AliGeomManager::kPHOS1;
731 AliGeomManager::ELayerID idPHOS2 = AliGeomManager::kPHOS2;
732 Int_t modUID, modnum = 0;
733 TString physModulePath="/ALIC_1/PHOS_";
734 TString symbModuleName="PHOS/Module";
735 Int_t nModules = GetGeometry()->GetNModules();
738 for(Int_t iModule=1; iModule<=nModules; iModule++){
739 snprintf(im,5,"%d",iModule) ;
740 modUID = AliGeomManager::LayerToVolUID(idPHOS1,modnum++);
741 if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
743 volpath = physModulePath;
745 // volpath += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1";
747 // Check the volume path if not all 5 modules exist
748 if (!gGeoManager->CheckPath(volpath.Data())) {
749 AliError(Form("Volume path %s not valid!",volpath.Data()));
753 symname = symbModuleName;
755 if(!gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data(),modUID))
757 // AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", symname.Data(),volpath.Data()));
759 // Creates the Tracking to Local transformation matrix for PHOS modules
760 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
762 Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
763 TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
765 TGeoHMatrix *matTtoL = new TGeoHMatrix;
766 matTtoL->RotateZ(-90.+angle);
767 matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
768 alignableEntry->SetMatrix(matTtoL);
771 //Aligning of CPV should be done for volume PCPV_1
772 symbModuleName="PHOS/Module";
774 for(Int_t iModule=1; iModule<=nModules; iModule++){
775 if(strstr(GetTitle(),"noCPV"))
777 snprintf(im,5,"%d",iModule) ;
778 modUID = AliGeomManager::LayerToVolUID(idPHOS2,modnum++);
779 if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0)
781 volpath = physModulePath;
783 volpath += "/PCPV_1";
784 // Check the volume path
785 if (!gGeoManager->CheckPath(volpath.Data())) {
786 AliError(Form("Volume path %s not valid!",volpath.Data()));
790 symname = symbModuleName;
793 if(!gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data(),modUID))
794 AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", symname.Data(),volpath.Data()));
796 // Creates the TGeo Local to Tracking transformation matrix ...
797 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
799 Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
800 TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
802 TGeoHMatrix *matTtoL = new TGeoHMatrix;
803 matTtoL->RotateZ(-90.+angle);
804 matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
805 alignableEntry->SetMatrix(matTtoL);
810 // Alignable cradle walls
811 // Volume path /ALIC_1/PCRA_<i> => symbolic name /PHOS/Cradle<i>, <i>=0,1
813 TString physCradlePath="/ALIC_1/PCRA_";
814 TString symbCradleName="PHOS/Cradle";
817 for(Int_t iCradle=0; iCradle<nCradles; iCradle++){
818 volpath = physCradlePath;
820 symname = symbCradleName;
822 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
826 // Volume path /ALIC_1/PWHE_<i> => symbolic name /PHOS/Wheel<i>, i=0,1,2,3
828 TString physWheelPath="/ALIC_1/PWHE_";
829 TString symbWheelName="PHOS/Wheel";
832 for(Int_t iWheel=0; iWheel<nWheels; iWheel++){
833 volpath = physWheelPath;
835 symname = symbWheelName;
837 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
840 //Physical strip path is a combination of: physModulePath + module number +
841 //physStripPath + strip number == ALIC_1/PHOS_N/..../PSTR_M
842 const Int_t nStripsX = GetGeometry()->GetEMCAGeometry()->GetNStripX();
843 const Int_t nStripsZ = GetGeometry()->GetEMCAGeometry()->GetNStripZ();
844 TString partialPhysStripName(100);
845 TString fullPhysStripName(100);
846 TString partialSymbStripName(100);
847 TString fullSymbStripName(100);
849 for(Int_t module = 1; module <= nModules; ++module){
851 snprintf(im,5,"%d",module) ;
852 if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
855 volpath = physModulePath;
857 // Check the volume path if not all 5 modules exist
858 if (!gGeoManager->CheckPath(volpath.Data())) {
859 AliError(Form("Volume path %s does not exist",volpath.Data())) ;
863 partialPhysStripName = physModulePath;
864 partialPhysStripName += module;
865 partialPhysStripName += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1/PSTR_";
867 partialSymbStripName = symbModuleName;
868 partialSymbStripName += module;
869 partialSymbStripName += "/Strip_";
871 for(Int_t i = 0, ind1D = 1; i < nStripsX; ++i){//ind1D starts from 1 (PSTR_1...PSTR_224...)
872 for(Int_t j = 0; j < nStripsZ; ++j, ++ind1D){
873 fullPhysStripName = partialPhysStripName;
874 fullPhysStripName += ind1D;
876 fullSymbStripName = partialSymbStripName;
877 fullSymbStripName += i;//ind1D;
878 fullSymbStripName += '_';
879 fullSymbStripName += j;
881 gGeoManager->SetAlignableEntry(fullSymbStripName.Data(), fullPhysStripName.Data());
883 // Creates the TGeo Local to Tracking transformation matrix ...
884 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntry(fullSymbStripName.Data()) ;
885 const char *path = alignableEntry->GetTitle();
886 if (!gGeoManager->cd(path))
887 AliFatal(Form("Volume path %s not valid!",path));
888 TGeoHMatrix matLtoT = *gGeoManager->GetCurrentMatrix() ;
889 Double_t refl[3]={-1.,-1.,-1.} ;
890 matLtoT.SetScale(refl) ;
891 TGeoHMatrix *matTtoL = new TGeoHMatrix(matLtoT.Inverse());
894 snprintf(phosPath,50,"/ALIC_1/PHOS_%d",module) ;
895 if (!gGeoManager->cd(phosPath)){
896 AliFatal("Geo manager can not find path \n");
898 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
900 matTtoL->Multiply(mPHOS);
902 AliFatal("Geo matrixes are not loaded \n") ;
905 Double_t rot[9]={1.,0.,0., 0.,1.,0., 0.,0.,1.} ;
906 matTtoL->SetRotation(rot) ;
907 alignableEntry->SetMatrix(matTtoL);
910 //Check poisition of corner cell of the strip
911 AliPHOSGeometry * geom = AliPHOSGeometry::GetInstance() ;
917 Int_t raw = geom->GetEMCAGeometry()->GetNCellsXInStrip()*((iStrip-1)/geom->GetEMCAGeometry()->GetNStripZ()) +
918 1 + (icell-1)/geom->GetEMCAGeometry()->GetNCellsZInStrip() ;
919 Int_t col = geom->GetEMCAGeometry()->GetNCellsZInStrip()*(1+(iStrip-1)%geom->GetEMCAGeometry()->GetNStripZ()) -
920 (icell-1)%geom->GetEMCAGeometry()->GetNCellsZInStrip() ;
921 if(col==0) col=geom->GetNZ() ;
925 geom->RelPosInModule(relid, xG, zG) ;
926 printf("============\n") ;
927 printf("Geometry: x=%f, z=%f \n",xG,zG) ;
929 geom->RelToAbsNumbering(relid,absid) ;
930 Double_t pos[3]= {-2.2*3.5,0.0,1.1}; //Position incide the strip (Y coordinalte is not important)
931 Double_t posC[3]={0.0,0.0,0.}; //Global position
933 matTtoL->MasterToLocal(pos,posC);
934 printf("Matrix: x=%f, z=%f, y=%f \n",posC[0],posC[2],posC[1]) ;
941 //____________________________________________________________________________
942 Float_t AliPHOSv0::ZMin(void) const
944 // Overall dimension of the PHOS (min)
946 AliPHOSGeometry * geom = GetGeometry() ;
948 return -geom->GetOuterBoxSize(2)/2.;
951 //____________________________________________________________________________
952 Float_t AliPHOSv0::ZMax(void) const
954 // Overall dimension of the PHOS (max)
956 AliPHOSGeometry * geom = GetGeometry() ;
958 return geom->GetOuterBoxSize(2)/2.;
961 //____________________________________________________________________________
962 void AliPHOSv0::Init(void)
964 // Just prints an information message
968 if(AliLog::GetGlobalDebugLevel()>0) {
972 Info("Init", "%s", st.Data()) ;
973 // Here the PHOS initialisation code (if any!)
975 AliPHOSGeometry * geom = GetGeometry() ;
978 Info("Init", "AliPHOS%s: PHOS geometry intialized for %s", Version().Data(), geom->GetName()) ;
980 Info("Init", "AliPHOS%s: PHOS geometry initialization failed !", Version().Data()) ;
982 Info("Init", "%s", st.Data()) ;