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 sprintf(im,"%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() ;
203 // ======= Define the strip ===============
205 gMC->Gsvolu("PSTR", "BOX ", idtmed[716], emcg->GetStripHalfSize(), 3) ; //Made of steel
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);
211 // --- define wrapped crystal and put it into steel cell
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") ;
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") ;
223 // --- define APD/PIN preamp and put it into AirCell
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") ;
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?
236 // --- Fill strip with wrapped cristals in steel cells
238 Float_t* splate = emcg->GetSupportPlateHalfSize();
240 // Float_t* acel = emcg->GetSteelCellHalfSize() ;
241 Float_t* acel = emcg->GetAirCellHalfSize() ;
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] ;
246 gMC->Gspos("PCEL", icel, "PSTR", x, y, +z, 0, "ONLY") ;
247 gMC->Gspos("PCEL", icel + 1, "PSTR", x, y, -z, 0, "ONLY") ;
250 // --- define the support plate, hole in it and position it in strip ----
251 gMC->Gsvolu("PSUP", "BOX ", idtmed[701], emcg->GetSupportPlateHalfSize(), 3) ;
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") ;
258 gMC->Gspos("PSUP", 1, "PSTR", 0.0, y, 0.0, 0, "ONLY") ;
261 // ========== Fill module with strips and put them into inner thermoinsulation=============
262 gMC->Gsvolu("PTII", "BOX ", idtmed[706], emcg->GetInnerThermoHalfSize(), 3) ;
264 Float_t * inthermo = emcg->GetInnerThermoHalfSize() ;
265 Float_t * strip = emcg->GetStripHalfSize() ;
266 y = inthermo[1] - strip[1] ;
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") ;
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] ;
286 gMC->Gspos("PTII", 1, "PAGA", 0.0, y, 0.0, 0, "ONLY") ;
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] ;
295 gMC->Gspos("PAGA", 1, "PCOR", 0.0, y, 0.0, 0, "ONLY") ;
297 // ------- define the outer thermoinsulating cover
298 gMC->Gsvolu("PTIO", "TRD1", idtmed[706], emcg->GetOuterThermoParams(), 4) ;
299 Float_t * outparams = emcg->GetOuterThermoParams() ;
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
305 z = outparams[3] - cooler[1] ;
306 gMC->Gspos("PCOR", 1, "PTIO", 0., 0.0, z, idrotm[1], "ONLY") ;
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") ;
314 // --------- Define front fiberglass cover -----------
315 gMC->Gsvolu("PFGC", "BOX ", idtmed[717], emcg->GetFiberGlassHalfSize(), 3) ;
317 gMC->Gspos("PFGC", 1, "PCOL", 0., 0.0, z, 0, "ONLY") ;
319 //=============This is all with cold section==============
322 //------ Warm Section --------------
323 gMC->Gsvolu("PWAR", "BOX ", idtmed[701], emcg->GetWarmAlCoverHalfSize(), 3) ;
324 Float_t * warmcov = emcg->GetWarmAlCoverHalfSize() ;
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] ;
331 gMC->Gspos("PWTI", 1, "PWAR", 0., 0.0, z, 0, "ONLY") ;
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() ;
337 gMC->Gsvolu("PBE1", "BOX ", idtmed[701], emcg->GetTSupport1HalfSize(), 3) ;
338 Float_t * beams = emcg->GetTSupport1HalfSize() ;
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") ;
345 z = -warmthermo[2] + cbox[2];
346 gMC->Gspos("PCA1", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;
348 gMC->Gsvolu("PCA2", "BOX ", idtmed[718], emcg->GetTCables2HalfSize(), 3) ;
349 Float_t * cbox2 = emcg->GetTCables2HalfSize() ;
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") ;
357 z = -warmthermo[2] + 2*cbox[2] + cbox2[2];
358 gMC->Gspos("PCA2", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;
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") ;
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") ;
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") ;
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") ;
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") ;
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") ;
393 // --- Define Air Gap for FEE electronics -----
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") ;
399 // Define the EMC module volume and combine Cool and Warm sections
401 gMC->Gsvolu("PEMC", "TRD1", idtmed[798], emcg->GetEMCParams(), 4) ;
404 gMC->Gspos("PCOL", 1, "PEMC", 0., 0., z, 0, "ONLY") ;
406 gMC->Gspos("PWAR", 1, "PEMC", 0., 0., z, 0, "ONLY") ;
409 // Put created EMC geometry into PHOS volume
411 z = geom->GetCPVBoxSize(1) / 2. ;
412 gMC->Gspos("PEMC", 1, "PHOS", 0., 0., z, 0, "ONLY") ;
416 //____________________________________________________________________________
417 void AliPHOSv0::CreateGeometryforCPV()
419 // Create the PHOS-CPV geometry for GEANT
420 // Author: Yuri Kharlov 11 September 2000
424 Geant3 geometry of PHOS-CPV in ALICE
429 <td>CPV perspective view</td>
430 <td>CPV front view </td>
434 <td> <img height=300 width=290 src="../images/CPVallPersp.gif"> </td>
435 <td> <img height=300 width=290 src="../images/CPVallFront.gif"> </td>
439 <td>One CPV module, perspective view </td>
440 <td>One CPV module, front view (extended in vertical direction) </td>
444 <td><img height=300 width=290 src="../images/CPVmodulePers.gif"></td>
445 <td><img height=300 width=290 src="../images/CPVmoduleSide.gif"></td>
451 Geant3 geometry tree of PHOS-CPV in ALICE
454 <img height=300 width=290 src="../images/CPVtree.gif">
459 Float_t par[3], x,y,z;
461 // Get pointer to the array containing media indexes
462 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
464 AliPHOSGeometry * geom = GetGeometry() ;
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) ;
472 Float_t * emcParams = geom->GetEMCAGeometry()->GetEMCParams() ;
475 AliMatrix(rotm, 90.,0., 0., 0., 90., 90.) ;
477 gMC->Gspos("PCPV", 1, "PHOS", 0.0, 0.0, z, rotm, "ONLY") ;
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);
486 // Cu+Ni foil covers Gassiplex board
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");
493 // Position of the chip inside CPV
495 Float_t xStep = geom->GetCPVActiveSize(0) / (geom->GetNumberOfCPVChipsPhi() + 1);
496 Float_t zStep = geom->GetCPVActiveSize(1) / (geom->GetNumberOfCPVChipsZ() + 1);
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++) {
504 z = zStep * (iz+1) - geom->GetCPVActiveSize(1)/2;
505 gMC->Gspos("PCPC",copy,"PCPV",x,y,z,0,"ONLY");
509 // Foiled textolite (1 mm of textolite + 50 mkm of Cu + 6 mkm of Ni)
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);
518 par[1] = (geom->GetFTPosition(2) - geom->GetFTPosition(1) - geom->GetCPVTextoliteThickness()) / 2;
519 gMC->Gsvolu("PCPG","BOX ",idtmed[715],par,3);
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");
525 y-= (geom->GetFTPosition(2) - geom->GetFTPosition(1)) / 2;
526 gMC->Gspos("PCPG",1,"PCPV ",0,y,0,0,"ONLY");
530 // Dummy sensitive plane in the middle of argone gas volume
533 gMC->Gsvolu("PCPQ","BOX ",idtmed[715],par,3);
534 gMC->Gspos ("PCPQ",1,"PCPG",0,0,0,0,"ONLY");
536 // Cu+Ni foil covers textolite
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");
543 // Aluminum frame around CPV
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);
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);
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");
565 //____________________________________________________________________________
566 void AliPHOSv0::CreateGeometryforSupport()
568 // Create the PHOS' support geometry for GEANT
572 Geant3 geometry of the PHOS's support
575 <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/PHOS_support.gif">
580 Float_t par[5], x0,y0,z0 ;
583 // Get pointer to the array containing media indexes
584 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
586 AliPHOSGeometry * geom = GetGeometry() ;
588 // --- Dummy box containing two rails on which PHOS support moves
589 // --- Put these rails to the bottom of the L3 magnet
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) ;
596 y0 = -(geom->GetRailsDistanceFromIP() - geom->GetRailRoadSize(1) / 2.0) ;
597 gMC->Gspos("PRRD", 1, "ALIC", 0.0, y0, 0.0, 0, "ONLY") ;
599 // --- Dummy box containing one rail
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) ;
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") ;
611 // --- Upper and bottom steel parts of the rail
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) ;
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") ;
623 // --- The middle vertical steel parts of the rail
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) ;
630 y0 = - geom->GetRailPart3(1) / 2.0 ;
631 gMC->Gspos("PRP2", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
633 // --- The most upper steel parts of the rail
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) ;
640 y0 = (geom->GetRailOuterSize(1) - geom->GetRailPart3(1)) / 2.0 ;
641 gMC->Gspos("PRP3", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
643 // --- The wall of the cradle
644 // --- The wall is empty: steel thin walls and air inside
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) ;
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") ;
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") ;
665 // --- The "wheels" of the cradle
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) ;
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++) {
679 x0 = (2*j-1) * geom->GetDistanceBetwRails() / 2.0 ;
680 gMC->Gspos("PWHE", copy, "ALIC", x0, y0, z0, 0, "ONLY") ;
686 //_____________________________________________________________________________
687 void AliPHOSv0::AddAlignableVolumes() const
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
697 // 4) Strip units (group of 2x8 crystals)
699 TString volpath, symname;
702 // Volume path /ALIC_1/PHOS_<i> => symbolic name /PHOS/Module<i>, <i>=1,2,3,4,5
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();
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)
717 volpath = physModulePath;
719 // volpath += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1";
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()));
727 symname = symbModuleName;
729 if(!gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data(),modUID))
731 // AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", symname.Data(),volpath.Data()));
733 // Creates the Tracking to Local transformation matrix for PHOS modules
734 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
736 Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
737 TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
739 TGeoHMatrix *matTtoL = new TGeoHMatrix;
740 matTtoL->RotateZ(-90.+angle);
741 matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
742 alignableEntry->SetMatrix(matTtoL);
745 //Aligning of CPV should be done for volume PCPV_1
746 symbModuleName="PHOS/Module";
748 for(Int_t iModule=1; iModule<=nModules; iModule++){
749 if(strstr(GetTitle(),"noCPV"))
751 sprintf(im,"%d",iModule) ;
752 modUID = AliGeomManager::LayerToVolUID(idPHOS2,modnum++);
753 if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0)
755 volpath = physModulePath;
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()));
764 symname = symbModuleName;
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()));
770 // Creates the TGeo Local to Tracking transformation matrix ...
771 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID) ;
773 Float_t angle = GetGeometry()->GetPHOSAngle(iModule);
774 TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
776 TGeoHMatrix *matTtoL = new TGeoHMatrix;
777 matTtoL->RotateZ(-90.+angle);
778 matTtoL->MultiplyLeft(&(globMatrix->Inverse()));
779 alignableEntry->SetMatrix(matTtoL);
784 // Alignable cradle walls
785 // Volume path /ALIC_1/PCRA_<i> => symbolic name /PHOS/Cradle<i>, <i>=0,1
787 TString physCradlePath="/ALIC_1/PCRA_";
788 TString symbCradleName="PHOS/Cradle";
791 for(Int_t iCradle=0; iCradle<nCradles; iCradle++){
792 volpath = physCradlePath;
794 symname = symbCradleName;
796 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
800 // Volume path /ALIC_1/PWHE_<i> => symbolic name /PHOS/Wheel<i>, i=0,1,2,3
802 TString physWheelPath="/ALIC_1/PWHE_";
803 TString symbWheelName="PHOS/Wheel";
806 for(Int_t iWheel=0; iWheel<nWheels; iWheel++){
807 volpath = physWheelPath;
809 symname = symbWheelName;
811 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
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);
823 for(Int_t module = 1; module <= nModules; ++module){
825 sprintf(im,"%d",module) ;
826 if(strstr(GetTitle(),im)==0 && strcmp(GetTitle(),"IHEP")!=0 && strcmp(GetTitle(),"noCPV")!=0)
829 volpath = physModulePath;
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())) ;
837 partialPhysStripName = physModulePath;
838 partialPhysStripName += module;
839 partialPhysStripName += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1/PSTR_";
841 partialSymbStripName = symbModuleName;
842 partialSymbStripName += module;
843 partialSymbStripName += "/Strip_";
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;
850 fullSymbStripName = partialSymbStripName;
851 fullSymbStripName += i;//ind1D;
852 fullSymbStripName += '_';
853 fullSymbStripName += j;
855 gGeoManager->SetAlignableEntry(fullSymbStripName.Data(), fullPhysStripName.Data());
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());
868 sprintf(phosPath,"/ALIC_1/PHOS_%d",module) ;
869 if (!gGeoManager->cd(phosPath)){
870 AliFatal("Geo manager can not find path \n");
872 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
874 matTtoL->Multiply(mPHOS);
876 AliFatal("Geo matrixes are not loaded \n") ;
879 Double_t rot[9]={1.,0.,0., 0.,1.,0., 0.,0.,1.} ;
880 matTtoL->SetRotation(rot) ;
881 alignableEntry->SetMatrix(matTtoL);
884 //Check poisition of corner cell of the strip
885 AliPHOSGeometry * geom = AliPHOSGeometry::GetInstance() ;
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() ;
899 geom->RelPosInModule(relid, xG, zG) ;
900 printf("============\n") ;
901 printf("Geometry: x=%f, z=%f \n",xG,zG) ;
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
907 matTtoL->MasterToLocal(pos,posC);
908 printf("Matrix: x=%f, z=%f, y=%f \n",posC[0],posC[2],posC[1]) ;
915 //____________________________________________________________________________
916 Float_t AliPHOSv0::ZMin(void) const
918 // Overall dimension of the PHOS (min)
920 AliPHOSGeometry * geom = GetGeometry() ;
922 return -geom->GetOuterBoxSize(2)/2.;
925 //____________________________________________________________________________
926 Float_t AliPHOSv0::ZMax(void) const
928 // Overall dimension of the PHOS (max)
930 AliPHOSGeometry * geom = GetGeometry() ;
932 return geom->GetOuterBoxSize(2)/2.;
935 //____________________________________________________________________________
936 void AliPHOSv0::Init(void)
938 // Just prints an information message
942 if(AliLog::GetGlobalDebugLevel()>0) {
946 Info("Init", "%s", st.Data()) ;
947 // Here the PHOS initialisation code (if any!)
949 AliPHOSGeometry * geom = GetGeometry() ;
952 Info("Init", "AliPHOS%s: PHOS geometry intialized for %s", Version().Data(), geom->GetName()) ;
954 Info("Init", "AliPHOS%s: PHOS geometry initialization failed !", Version().Data()) ;
956 Info("Init", "%s", st.Data()) ;