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 ---
83 #include <TGeometry.h>
89 #include <TVirtualMC.h>
90 #include <TGeoPhysicalNode.h>
91 #include <TGeoManager.h>
92 #include <TGeoMatrix.h>
95 // --- Standard library ---
100 // --- AliRoot header files ---
102 #include "AliConst.h"
103 #include "AliPHOSGeometry.h"
104 #include "AliPHOSLoader.h"
105 #include "AliPHOSv0.h"
108 #include "AliGeomManager.h"
112 //____________________________________________________________________________
113 AliPHOSv0::AliPHOSv0(const char *name, const char *title):
116 // ctor : title is used to identify the layout
120 //____________________________________________________________________________
121 void AliPHOSv0::CreateGeometry()
123 // Create the PHOS geometry for Geant
125 AliPHOSv0 *phostmp = dynamic_cast<AliPHOSv0*>(gAlice->GetModule("PHOS")) ;
127 if ( phostmp == NULL ) {
129 fprintf(stderr, "PHOS detector not found!\n") ;
134 AliPHOSGeometry * geom = GetGeometry() ;
136 // Get pointer to the array containing media indeces
137 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
139 // Create a PHOS module.
141 gMC->Gsvolu("PHOS", "TRD1", idtmed[798], geom->GetPHOSParams(), 4) ;
143 this->CreateGeometryforEMC() ;
145 if (strstr(fTitle.Data(),"noCPV") == 0)
146 this->CreateGeometryforCPV() ;
148 this->CreateGeometryforSupport() ;
150 // --- Position PHOS mdules in ALICE setup ---
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)
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]) ;
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") ;
175 if(!anyModuleCreated)
176 AliError("No one PHOS module was created") ;
179 //____________________________________________________________________________
180 void AliPHOSv0::CreateGeometryforEMC()
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)
192 Geant3 geometry tree of PHOS-EMC in ALICE
195 <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/EMCinAlice.gif">
200 // Get pointer to the array containing media indexes
201 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
203 AliPHOSGeometry * geom = GetGeometry() ;
204 AliPHOSEMCAGeometry * emcg = geom->GetEMCAGeometry() ;
206 // ======= Define the strip ===============
208 gMC->Gsvolu("PSTR", "BOX ", idtmed[716], emcg->GetStripHalfSize(), 3) ; //Made of steel
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);
214 // --- define wrapped crystal and put it into steel cell
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") ;
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") ;
226 // --- define APD/PIN preamp and put it into AirCell
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") ;
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?
239 // --- Fill strip with wrapped cristals in steel cells
241 Float_t* splate = emcg->GetSupportPlateHalfSize();
243 // Float_t* acel = emcg->GetSteelCellHalfSize() ;
244 Float_t* acel = emcg->GetAirCellHalfSize() ;
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] ;
249 gMC->Gspos("PCEL", icel, "PSTR", x, y, +z, 0, "ONLY") ;
250 gMC->Gspos("PCEL", icel + 1, "PSTR", x, y, -z, 0, "ONLY") ;
253 // --- define the support plate, hole in it and position it in strip ----
254 gMC->Gsvolu("PSUP", "BOX ", idtmed[701], emcg->GetSupportPlateHalfSize(), 3) ;
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") ;
261 gMC->Gspos("PSUP", 1, "PSTR", 0.0, y, 0.0, 0, "ONLY") ;
264 // ========== Fill module with strips and put them into inner thermoinsulation=============
265 gMC->Gsvolu("PTII", "BOX ", idtmed[706], emcg->GetInnerThermoHalfSize(), 3) ;
267 Float_t * inthermo = emcg->GetInnerThermoHalfSize() ;
268 Float_t * strip = emcg->GetStripHalfSize() ;
269 y = inthermo[1] - strip[1] ;
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") ;
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] ;
289 gMC->Gspos("PTII", 1, "PAGA", 0.0, y, 0.0, 0, "ONLY") ;
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] ;
298 gMC->Gspos("PAGA", 1, "PCOR", 0.0, y, 0.0, 0, "ONLY") ;
300 // ------- define the outer thermoinsulating cover
301 gMC->Gsvolu("PTIO", "TRD1", idtmed[706], emcg->GetOuterThermoParams(), 4) ;
302 Float_t * outparams = emcg->GetOuterThermoParams() ;
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
308 z = outparams[3] - cooler[1] ;
309 gMC->Gspos("PCOR", 1, "PTIO", 0., 0.0, z, idrotm[1], "ONLY") ;
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") ;
317 // --------- Define front fiberglass cover -----------
318 gMC->Gsvolu("PFGC", "BOX ", idtmed[717], emcg->GetFiberGlassHalfSize(), 3) ;
320 gMC->Gspos("PFGC", 1, "PCOL", 0., 0.0, z, 0, "ONLY") ;
322 //=============This is all with cold section==============
325 //------ Warm Section --------------
326 gMC->Gsvolu("PWAR", "BOX ", idtmed[701], emcg->GetWarmAlCoverHalfSize(), 3) ;
327 Float_t * warmcov = emcg->GetWarmAlCoverHalfSize() ;
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] ;
334 gMC->Gspos("PWTI", 1, "PWAR", 0., 0.0, z, 0, "ONLY") ;
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() ;
340 gMC->Gsvolu("PBE1", "BOX ", idtmed[701], emcg->GetTSupport1HalfSize(), 3) ;
341 Float_t * beams = emcg->GetTSupport1HalfSize() ;
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") ;
348 z = -warmthermo[2] + cbox[2];
349 gMC->Gspos("PCA1", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;
351 gMC->Gsvolu("PCA2", "BOX ", idtmed[718], emcg->GetTCables2HalfSize(), 3) ;
352 Float_t * cbox2 = emcg->GetTCables2HalfSize() ;
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") ;
360 z = -warmthermo[2] + 2*cbox[2] + cbox2[2];
361 gMC->Gspos("PCA2", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;
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") ;
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") ;
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") ;
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") ;
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") ;
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") ;
396 // --- Define Air Gap for FEE electronics -----
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") ;
402 // Define the EMC module volume and combine Cool and Warm sections
404 gMC->Gsvolu("PEMC", "TRD1", idtmed[798], emcg->GetEMCParams(), 4) ;
407 gMC->Gspos("PCOL", 1, "PEMC", 0., 0., z, 0, "ONLY") ;
409 gMC->Gspos("PWAR", 1, "PEMC", 0., 0., z, 0, "ONLY") ;
412 // Put created EMC geometry into PHOS volume
414 z = geom->GetCPVBoxSize(1) / 2. ;
415 gMC->Gspos("PEMC", 1, "PHOS", 0., 0., z, 0, "ONLY") ;
419 //____________________________________________________________________________
420 void AliPHOSv0::CreateGeometryforCPV()
422 // Create the PHOS-CPV geometry for GEANT
423 // Author: Yuri Kharlov 11 September 2000
427 Geant3 geometry of PHOS-CPV in ALICE
432 <td>CPV perspective view</td>
433 <td>CPV front view </td>
437 <td> <img height=300 width=290 src="../images/CPVallPersp.gif"> </td>
438 <td> <img height=300 width=290 src="../images/CPVallFront.gif"> </td>
442 <td>One CPV module, perspective view </td>
443 <td>One CPV module, front view (extended in vertical direction) </td>
447 <td><img height=300 width=290 src="../images/CPVmodulePers.gif"></td>
448 <td><img height=300 width=290 src="../images/CPVmoduleSide.gif"></td>
454 Geant3 geometry tree of PHOS-CPV in ALICE
457 <img height=300 width=290 src="../images/CPVtree.gif">
462 Float_t par[3], x,y,z;
464 // Get pointer to the array containing media indexes
465 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
467 AliPHOSGeometry * geom = GetGeometry() ;
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) ;
475 Float_t * emcParams = geom->GetEMCAGeometry()->GetEMCParams() ;
478 AliMatrix(rotm, 90.,0., 0., 0., 90., 90.) ;
480 gMC->Gspos("PCPV", 1, "PHOS", 0.0, 0.0, z, rotm, "ONLY") ;
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);
489 // Cu+Ni foil covers Gassiplex board
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");
496 // Position of the chip inside CPV
498 Float_t xStep = geom->GetCPVActiveSize(0) / (geom->GetNumberOfCPVChipsPhi() + 1);
499 Float_t zStep = geom->GetCPVActiveSize(1) / (geom->GetNumberOfCPVChipsZ() + 1);
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++) {
507 z = zStep * (iz+1) - geom->GetCPVActiveSize(1)/2;
508 gMC->Gspos("PCPC",copy,"PCPV",x,y,z,0,"ONLY");
512 // Foiled textolite (1 mm of textolite + 50 mkm of Cu + 6 mkm of Ni)
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);
521 par[1] = (geom->GetFTPosition(2) - geom->GetFTPosition(1) - geom->GetCPVTextoliteThickness()) / 2;
522 gMC->Gsvolu("PCPG","BOX ",idtmed[715],par,3);
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");
528 y-= (geom->GetFTPosition(2) - geom->GetFTPosition(1)) / 2;
529 gMC->Gspos("PCPG",1,"PCPV ",0,y,0,0,"ONLY");
533 // Dummy sensitive plane in the middle of argone gas volume
536 gMC->Gsvolu("PCPQ","BOX ",idtmed[715],par,3);
537 gMC->Gspos ("PCPQ",1,"PCPG",0,0,0,0,"ONLY");
539 // Cu+Ni foil covers textolite
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");
546 // Aluminum frame around CPV
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);
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);
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");
568 //____________________________________________________________________________
569 void AliPHOSv0::CreateGeometryforSupport()
571 // Create the PHOS' support geometry for GEANT
575 Geant3 geometry of the PHOS's support
578 <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/PHOS_support.gif">
583 Float_t par[5], x0,y0,z0 ;
586 // Get pointer to the array containing media indexes
587 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
589 AliPHOSGeometry * geom = GetGeometry() ;
591 // --- Dummy box containing two rails on which PHOS support moves
592 // --- Put these rails to the bottom of the L3 magnet
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) ;
599 y0 = -(geom->GetRailsDistanceFromIP() - geom->GetRailRoadSize(1) / 2.0) ;
600 gMC->Gspos("PRRD", 1, "ALIC", 0.0, y0, 0.0, 0, "ONLY") ;
602 // --- Dummy box containing one rail
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) ;
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") ;
614 // --- Upper and bottom steel parts of the rail
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) ;
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") ;
626 // --- The middle vertical steel parts of the rail
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) ;
633 y0 = - geom->GetRailPart3(1) / 2.0 ;
634 gMC->Gspos("PRP2", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
636 // --- The most upper steel parts of the rail
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) ;
643 y0 = (geom->GetRailOuterSize(1) - geom->GetRailPart3(1)) / 2.0 ;
644 gMC->Gspos("PRP3", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
646 // --- The wall of the cradle
647 // --- The wall is empty: steel thin walls and air inside
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) ;
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") ;
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") ;
668 // --- The "wheels" of the cradle
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) ;
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++) {
682 x0 = (2*j-1) * geom->GetDistanceBetwRails() / 2.0 ;
683 gMC->Gspos("PWHE", copy, "ALIC", x0, y0, z0, 0, "ONLY") ;
689 //_____________________________________________________________________________
690 void AliPHOSv0::AddAlignableVolumes() const
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
700 // 4) Strip units (group of 2x8 crystals)
702 TString volpath, symname;
705 // Volume path /ALIC_1/PHOS_<i> => symbolic name /PHOS/Module<i>, <i>=1,2,3,4,5
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();
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)
720 volpath = physModulePath;
722 // volpath += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1";
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()));
730 symname = symbModuleName;
732 if(!gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data(),modUID))
734 // AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", symname.Data(),volpath.Data()));
736 // Creates the Tracking to Local transformation matrix for PHOS modules
737 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
739 Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
740 TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
742 TGeoHMatrix *matTtoL = new TGeoHMatrix;
743 matTtoL->RotateZ(-90.+angle);
744 matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
745 alignableEntry->SetMatrix(matTtoL);
748 //Aligning of CPV should be done for volume PCPV_1
749 symbModuleName="PHOS/Module";
751 for(Int_t iModule=1; iModule<=nModules; iModule++){
752 if(strstr(GetTitle(),"noCPV"))
754 sprintf(im,"%d",iModule) ;
755 modUID = AliGeomManager::LayerToVolUID(idPHOS2,modnum++);
756 if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0)
758 volpath = physModulePath;
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()));
767 symname = symbModuleName;
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()));
773 // Creates the TGeo Local to Tracking transformation matrix ...
774 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
776 Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
777 TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
779 TGeoHMatrix *matTtoL = new TGeoHMatrix;
780 matTtoL->RotateZ(-90.+angle);
781 matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
782 alignableEntry->SetMatrix(matTtoL);
787 // Alignable cradle walls
788 // Volume path /ALIC_1/PCRA_<i> => symbolic name /PHOS/Cradle<i>, <i>=0,1
790 TString physCradlePath="/ALIC_1/PCRA_";
791 TString symbCradleName="PHOS/Cradle";
794 for(Int_t iCradle=0; iCradle<nCradles; iCradle++){
795 volpath = physCradlePath;
797 symname = symbCradleName;
799 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
803 // Volume path /ALIC_1/PWHE_<i> => symbolic name /PHOS/Wheel<i>, i=0,1,2,3
805 TString physWheelPath="/ALIC_1/PWHE_";
806 TString symbWheelName="PHOS/Wheel";
809 for(Int_t iWheel=0; iWheel<nWheels; iWheel++){
810 volpath = physWheelPath;
812 symname = symbWheelName;
814 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
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);
826 for(Int_t module = 1; module <= nModules; ++module){
828 sprintf(im,"%d",module) ;
829 if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
832 volpath = physModulePath;
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())) ;
840 partialPhysStripName = physModulePath;
841 partialPhysStripName += module;
842 partialPhysStripName += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1/PSTR_";
844 partialSymbStripName = symbModuleName;
845 partialSymbStripName += module;
846 partialSymbStripName += "/Strip_";
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;
853 fullSymbStripName = partialSymbStripName;
854 fullSymbStripName += i;//ind1D;
855 fullSymbStripName += '_';
856 fullSymbStripName += j;
858 gGeoManager->SetAlignableEntry(fullSymbStripName.Data(), fullPhysStripName.Data());
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());
871 sprintf(phosPath,"/ALIC_1/PHOS_%d",module) ;
872 if (!gGeoManager->cd(phosPath)){
873 AliFatal("Geo manager can not find path \n");
875 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
877 matTtoL->Multiply(mPHOS);
879 AliFatal("Geo matrixes are not loaded \n") ;
882 Double_t rot[9]={1.,0.,0., 0.,1.,0., 0.,0.,1.} ;
883 matTtoL->SetRotation(rot) ;
884 alignableEntry->SetMatrix(matTtoL);
887 //Check poisition of corner cell of the strip
888 AliPHOSGeometry * geom = AliPHOSGeometry::GetInstance() ;
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() ;
902 geom->RelPosInModule(relid, xG, zG) ;
903 printf("============\n") ;
904 printf("Geometry: x=%f, z=%f \n",xG,zG) ;
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
910 matTtoL->MasterToLocal(pos,posC);
911 printf("Matrix: x=%f, z=%f, y=%f \n",posC[0],posC[2],posC[1]) ;
918 //____________________________________________________________________________
919 Float_t AliPHOSv0::ZMin(void) const
921 // Overall dimension of the PHOS (min)
923 AliPHOSGeometry * geom = GetGeometry() ;
925 return -geom->GetOuterBoxSize(2)/2.;
928 //____________________________________________________________________________
929 Float_t AliPHOSv0::ZMax(void) const
931 // Overall dimension of the PHOS (max)
933 AliPHOSGeometry * geom = GetGeometry() ;
935 return geom->GetOuterBoxSize(2)/2.;
938 //____________________________________________________________________________
939 void AliPHOSv0::Init(void)
941 // Just prints an information message
945 if(AliLog::GetGlobalDebugLevel()>0) {
949 Info("Init", "%s", st.Data()) ;
950 // Here the PHOS initialisation code (if any!)
952 AliPHOSGeometry * geom = GetGeometry() ;
955 Info("Init", "AliPHOS%s: PHOS geometry intialized for %s", Version().Data(), geom->GetName()) ;
957 Info("Init", "AliPHOS%s: PHOS geometry initialization failed !", Version().Data()) ;
959 Info("Init", "%s", st.Data()) ;