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.87 2007/04/01 07:37:10 kharlov
21 * TGeo RS to Local RS transf matr added
23 * Revision 1.86 2007/03/06 06:55:46 kharlov
24 * DP:Misalignment of CPV added
26 * Revision 1.85 2007/03/01 11:37:37 kharlov
27 * Strip units changed from 8x1 to 8x2 (T.Pocheptsov)
29 * Revision 1.84 2006/12/20 16:56:43 kharlov
30 * Optional geometry without CPV
32 * Revision 1.83 2006/11/14 17:11:15 hristov
33 * 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
35 * Revision 1.82 2006/09/27 19:55:57 kharlov
36 * Alignment object with symbolic volume names are introduced
38 * Revision 1.81 2006/03/04 20:25:56 kharlov
39 * Set geom parameters from CDB
41 * Revision 1.80 2005/06/17 07:39:07 hristov
42 * Removing GetDebug and SetDebug from AliRun and AliModule. Using AliLog for the messages
44 * Revision 1.79 2005/05/28 14:19:05 schutz
45 * Compilation warnings fixed by T.P.
49 //_________________________________________________________________________
50 // Implementation version v0 of PHOS Manager class
51 // An object of this class does not produce hits nor digits
52 // It is the one to use if you do not want to produce outputs in TREEH or TREED
54 //*-- Author: Yves Schutz (SUBATECH) & Dmitri Peressounko (RRC KI & SUBATECH)
57 // --- ROOT system ---
61 #include <TGeometry.h>
67 #include <TVirtualMC.h>
68 #include <TGeoPhysicalNode.h>
69 #include <TGeoManager.h>
72 // --- Standard library ---
77 // --- AliRoot header files ---
80 #include "AliPHOSGeometry.h"
81 #include "AliPHOSLoader.h"
82 #include "AliPHOSv0.h"
88 //____________________________________________________________________________
89 AliPHOSv0::AliPHOSv0(const char *name, const char *title):
92 // ctor : title is used to identify the layout
96 //____________________________________________________________________________
97 void AliPHOSv0::BuildGeometry()
99 // Build the PHOS geometry for the ROOT display
103 PHOS in ALICE displayed by root
109 <IMG Align=BOTTOM ALT="All Views" SRC="../images/AliPHOSv0AllViews.gif">
114 <IMG Align=BOTTOM ALT="Front View" SRC="../images/AliPHOSv0FrontView.gif">
119 <IMG Align=BOTTOM ALT="3D View 1" SRC="../images/AliPHOSv03DView1.gif">
124 <IMG Align=BOTTOM ALT="3D View 2" SRC="../images/AliPHOSv03DView2.gif">
130 this->BuildGeometryforEMC() ;
131 this->BuildGeometryforCPV() ;
135 //____________________________________________________________________________
136 void AliPHOSv0:: BuildGeometryforEMC(void)
138 // Build the PHOS-EMC geometry for the ROOT display
140 const Int_t kColorPHOS = kRed ;
141 const Int_t kColorXTAL = kBlue ;
143 Double_t const kRADDEG = 180.0 / TMath::Pi() ;
145 AliPHOSGeometry * geom = GetGeometry() ;
146 AliPHOSEMCAGeometry * emcg = geom->GetEMCAGeometry() ;
147 Float_t * boxparams = emcg->GetEMCParams() ;
149 new TTRD1("OuterBox", "PHOS box", "void",boxparams[0],boxparams[1],boxparams[2], boxparams[3] );
154 Float_t * cribox = emcg->GetInnerThermoHalfSize() ;
155 new TBRIK( "CrystalsBox", "PHOS crystals box", "void", cribox[0], cribox[2], cribox[1] ) ;
157 // position PHOS into ALICE
159 Float_t r = geom->GetIPtoOuterCoverDistance() + boxparams[3] ;
161 TNode * top = gAlice->GetGeometry()->GetNode("alice") ;
163 char * nodename = new char[20] ;
164 char * rotname = new char[20] ;
166 new TRotMatrix("cribox", "cribox", 90, 0, 90, 90, 0, 0);
168 for( Int_t i = 1; i <= geom->GetNModules(); i++ ) {
170 Float_t angle = geom->GetPHOSAngle(i) ;
171 sprintf(rotname, "%s%d", "rot", number++) ;
172 new TRotMatrix(rotname, rotname, 90, angle, 0, 0, 90, 270 + angle);
175 sprintf(nodename,"%s%d", "Module", i) ;
176 Float_t x = r * TMath::Sin( angle / kRADDEG ) ;
177 Float_t y = -r * TMath::Cos( angle / kRADDEG ) ;
178 TNode * outerboxnode = new TNode(nodename, nodename, "OuterBox", x, y, 0, rotname ) ;
179 outerboxnode->SetLineColor(kColorPHOS) ;
180 fNodes->Add(outerboxnode) ;
183 Float_t z = -boxparams[3] - geom->GetIPtoOuterCoverDistance() +
184 cribox[1] + geom->GetIPtoCrystalSurface() ;
185 TNode * crystalsboxnode = new TNode(nodename, nodename, "CrystalsBox", 0, 0, z) ;
186 crystalsboxnode->SetLineColor(kColorXTAL) ;
187 fNodes->Add(crystalsboxnode) ;
195 //____________________________________________________________________________
196 void AliPHOSv0:: BuildGeometryforCPV(void)
198 // Build the PHOS-CPV geometry for the ROOT display
199 // Author: Yuri Kharlov 11 September 2000
204 CPV displayed by root
209 <td>CPV perspective view</td>
210 <td>CPV front view </td>
214 <td> <img height=300 width=290 src="../images/CPVRootPersp.gif"> </td>
215 <td> <img height=300 width=290 src="../images/CPVRootFront.gif"> </td>
223 const Double_t kRADDEG = 180.0 / TMath::Pi() ;
224 const Int_t kColorCPV = kGreen ;
225 const Int_t kColorFrame = kYellow ;
226 const Int_t kColorGassiplex = kRed;
227 const Int_t kColorPCB = kCyan;
229 AliPHOSGeometry * geom = GetGeometry() ;
231 // Box for a full PHOS module
233 new TBRIK ("CPVBox", "CPV box", "void", geom->GetCPVBoxSize(0)/2,
234 geom->GetCPVBoxSize(1)/2,
235 geom->GetCPVBoxSize(2)/2 );
236 new TBRIK ("CPVFrameLR", "CPV frame Left-Right", "void", geom->GetCPVFrameSize(0)/2,
237 geom->GetCPVFrameSize(1)/2,
238 geom->GetCPVBoxSize(2)/2 );
239 new TBRIK ("CPVFrameUD", "CPV frame Up-Down", "void", geom->GetCPVBoxSize(0)/2 - geom->GetCPVFrameSize(0),
240 geom->GetCPVFrameSize(1)/2,
241 geom->GetCPVFrameSize(2)/2);
242 new TBRIK ("CPVPCB", "CPV PCB", "void", geom->GetCPVActiveSize(0)/2,
243 geom->GetCPVTextoliteThickness()/2,
244 geom->GetCPVActiveSize(1)/2);
245 new TBRIK ("CPVGassiplex", "CPV Gassiplex PCB", "void", geom->GetGassiplexChipSize(0)/2,
246 geom->GetGassiplexChipSize(1)/2,
247 geom->GetGassiplexChipSize(2)/2);
249 // position CPV into ALICE
251 char * nodename = new char[25] ;
252 char * rotname = new char[25] ;
254 Float_t r = geom->GetIPtoCPVDistance() + geom->GetCPVBoxSize(1) / 2.0 ;
256 TNode * top = gAlice->GetGeometry()->GetNode("alice") ;
258 Int_t lastModule = 0 ;
259 lastModule = geom->GetNModules();
261 for( Int_t i = 1; i <= lastModule; i++ ) { // the number of PHOS modules
265 Float_t angle = geom->GetPHOSAngle(i) ;
266 sprintf(rotname, "%s%d", "rotg", number+i) ;
267 new TRotMatrix(rotname, rotname, 90, angle, 90, 90 + angle, 0, 0);
269 sprintf(nodename, "%s%d", "CPVModule", i) ;
270 Float_t x = r * TMath::Sin( angle / kRADDEG ) ;
271 Float_t y = -r * TMath::Cos( angle / kRADDEG ) ;
273 TNode * cpvBoxNode = new TNode(nodename , nodename ,"CPVBox", x, y, 0, rotname ) ;
274 cpvBoxNode->SetLineColor(kColorCPV) ;
275 fNodes->Add(cpvBoxNode) ;
278 // inside each CPV box:
282 for (j=0; j<=1; j++) {
283 sprintf(nodename, "CPVModule%d Frame%d", i, j+1) ;
284 x = TMath::Sign(1,2*j-1) * (geom->GetCPVBoxSize(0) - geom->GetCPVFrameSize(0)) / 2;
285 TNode * cpvFrameNode = new TNode(nodename , nodename ,"CPVFrameLR", x, 0, 0) ;
286 cpvFrameNode->SetLineColor(kColorFrame) ;
287 fNodes->Add(cpvFrameNode) ;
289 sprintf(nodename, "CPVModule%d Frame%d", i, j+3) ;
290 z = TMath::Sign(1,2*j-1) * (geom->GetCPVBoxSize(2) - geom->GetCPVFrameSize(2)) / 2;
291 cpvFrameNode = new TNode(nodename , nodename ,"CPVFrameUD", 0, 0, z) ;
292 cpvFrameNode->SetLineColor(kColorFrame) ;
293 fNodes->Add(cpvFrameNode) ;
296 // 4 printed circuit boards
297 for (j=0; j<4; j++) {
298 sprintf(nodename, "CPVModule%d PCB%d", i, j+1) ;
299 y = geom->GetCPVFrameSize(1) / 2 - geom->GetFTPosition(j) + geom->GetCPVTextoliteThickness()/2;
300 TNode * cpvPCBNode = new TNode(nodename , nodename ,"CPVPCB", 0, y, 0) ;
301 cpvPCBNode->SetLineColor(kColorPCB) ;
302 fNodes->Add(cpvPCBNode) ;
306 Float_t xStep = geom->GetCPVActiveSize(0) / (geom->GetNumberOfCPVChipsPhi() + 1);
307 Float_t zStep = geom->GetCPVActiveSize(1) / (geom->GetNumberOfCPVChipsZ() + 1);
308 y = geom->GetCPVFrameSize(1)/2 - geom->GetFTPosition(0) +
309 geom->GetCPVTextoliteThickness() / 2 + geom->GetGassiplexChipSize(1) / 2 + 0.1;
310 for (Int_t ix=0; ix<geom->GetNumberOfCPVChipsPhi(); ix++) {
311 x = xStep * (ix+1) - geom->GetCPVActiveSize(0)/2;
312 for (Int_t iz=0; iz<geom->GetNumberOfCPVChipsZ(); iz++) {
313 z = zStep * (iz+1) - geom->GetCPVActiveSize(1)/2;
314 sprintf(nodename, "CPVModule%d Chip(%dx%d)", i, ix+1,iz+1) ;
315 TNode * cpvGassiplexNode = new TNode(nodename , nodename ,"CPVGassiplex", x, y, z) ;
316 cpvGassiplexNode->SetLineColor(kColorGassiplex) ;
317 fNodes->Add(cpvGassiplexNode) ;
327 //____________________________________________________________________________
328 void AliPHOSv0::CreateGeometry()
330 // Create the PHOS geometry for Geant
332 AliPHOSv0 *phostmp = dynamic_cast<AliPHOSv0*>(gAlice->GetModule("PHOS")) ;
334 if ( phostmp == NULL ) {
336 fprintf(stderr, "PHOS detector not found!\n") ;
341 AliPHOSGeometry * geom = GetGeometry() ;
343 // Get pointer to the array containing media indeces
344 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
346 // Create a PHOS module.
348 gMC->Gsvolu("PHOS", "TRD1", idtmed[798], geom->GetPHOSParams(), 4) ;
350 this->CreateGeometryforEMC() ;
352 if (strstr(fTitle.Data(),"noCPV") == 0)
353 this->CreateGeometryforCPV() ;
355 this->CreateGeometryforSupport() ;
357 // --- Position PHOS mdules in ALICE setup ---
361 for (Int_t iModule = 0; iModule < geom->GetNModules(); iModule++ ) {
364 for (iXYZ=0; iXYZ<3; iXYZ++)
365 for (iAngle=0; iAngle<2; iAngle++)
366 angle[iXYZ][iAngle] = geom->GetModuleAngle(iModule,iXYZ, iAngle);
367 AliMatrix(idrotm[iModule],
368 angle[0][0],angle[0][1],
369 angle[1][0],angle[1][1],
370 angle[2][0],angle[2][1]) ;
373 for (iXYZ=0; iXYZ<3; iXYZ++)
374 pos[iXYZ] = geom->GetModuleCenter(iModule,iXYZ);
375 gMC->Gspos("PHOS", iModule+1, "ALIC", pos[0], pos[1], pos[2],
376 idrotm[iModule], "ONLY") ;
381 //____________________________________________________________________________
382 void AliPHOSv0::CreateGeometryforEMC()
384 // Create the PHOS-EMC geometry for GEANT
385 // Author: Dmitri Peressounko August 2001
386 // The used coordinate system:
387 // 1. in Module: X along longer side, Y out of beam, Z along shorter side (along beam)
388 // 2. In Strip the same: X along longer side, Y out of beam, Z along shorter side (along beam)
394 Geant3 geometry tree of PHOS-EMC in ALICE
397 <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/EMCinAlice.gif">
402 // Get pointer to the array containing media indexes
403 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
405 AliPHOSGeometry * geom = GetGeometry() ;
406 AliPHOSEMCAGeometry * emcg = geom->GetEMCAGeometry() ;
408 // ======= Define the strip ===============
410 gMC->Gsvolu("PSTR", "BOX ", idtmed[716], emcg->GetStripHalfSize(), 3) ; //Made of stell
412 // --- define steel volume (cell of the strip unit)
413 gMC->Gsvolu("PCEL", "BOX ", idtmed[716], emcg->GetSteelCellHalfSize(), 3);
415 // --- define wrapped crystal and put it into steel cell
417 gMC->Gsvolu("PWRA", "BOX ", idtmed[702], emcg->GetWrappedHalfSize(), 3);
418 Float_t * pin = emcg->GetAPDHalfSize() ;
419 Float_t * preamp = emcg->GetPreampHalfSize() ;
420 Float_t y = (emcg->GetAirGapLed()-2*pin[1]-2*preamp[1])/2;
421 gMC->Gspos("PWRA", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ;
423 // --- Define crystal and put it into wrapped crystall ---
424 gMC->Gsvolu("PXTL", "BOX ", idtmed[699], emcg->GetCrystalHalfSize(), 3) ;
425 gMC->Gspos("PXTL", 1, "PWRA", 0.0, 0.0, 0.0, 0, "ONLY") ;
427 // --- define APD/PIN preamp and put it into AirCell
429 gMC->Gsvolu("PPIN", "BOX ", idtmed[705], emcg->GetAPDHalfSize(), 3) ;
430 Float_t * crystal = emcg->GetCrystalHalfSize() ;
431 y = crystal[1] + emcg->GetAirGapLed() /2 - preamp[1];
432 gMC->Gspos("PPIN", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ;
434 gMC->Gsvolu("PREA", "BOX ", idtmed[711], emcg->GetPreampHalfSize(), 3) ; // Here I assumed preamp
435 // as a printed Circuit
436 y = crystal[1] + emcg->GetAirGapLed() /2 + pin[1] ; // May it should be changed
437 gMC->Gspos("PREA", 1, "PCEL", 0.0, y, 0.0, 0, "ONLY") ; // to ceramics?
440 // --- Fill strip with wrapped cristals in steel cells
442 Float_t* splate = emcg->GetSupportPlateHalfSize();
444 Float_t* acel = emcg->GetSteelCellHalfSize() ;
446 for(Int_t lev = 2, icel = 1; icel <= emcg->GetNCellsXInStrip()*emcg->GetNCellsZInStrip(); icel += 2, lev += 2){
447 Float_t x = (2*(lev / 2) - 1 - emcg->GetNCellsXInStrip())* acel[0] ;
449 gMC->Gspos("PCEL", icel, "PSTR", x, y, +z, 0, "ONLY") ;
450 gMC->Gspos("PCEL", icel + 1, "PSTR", x, y, -z, 0, "ONLY") ;
453 // --- define the support plate, hole in it and position it in strip ----
454 gMC->Gsvolu("PSUP", "BOX ", idtmed[701], emcg->GetSupportPlateHalfSize(), 3) ;
456 gMC->Gsvolu("PSHO", "BOX ", idtmed[798], emcg->GetSupportPlateInHalfSize(), 3) ;
457 Float_t z = emcg->GetSupportPlateThickness()/2 ;
458 gMC->Gspos("PSHO", 1, "PSUP", 0.0, 0.0, z, 0, "ONLY") ;
461 gMC->Gspos("PSUP", 1, "PSTR", 0.0, y, 0.0, 0, "ONLY") ;
464 // ========== Fill module with strips and put them into inner thermoinsulation=============
465 gMC->Gsvolu("PTII", "BOX ", idtmed[706], emcg->GetInnerThermoHalfSize(), 3) ;
467 Float_t * inthermo = emcg->GetInnerThermoHalfSize() ;
468 Float_t * strip = emcg->GetStripHalfSize() ;
469 y = inthermo[1] - strip[1] ;
474 for(irow = 0; irow < emcg->GetNStripX(); irow ++){
475 Float_t x = (2*irow + 1 - emcg->GetNStripX())* strip[0] ;
476 for(icol = 0; icol < emcg->GetNStripZ(); icol ++){
477 z = (2*icol + 1 - emcg->GetNStripZ()) * strip[2] ;
478 gMC->Gspos("PSTR", nr, "PTII", x, y, z, 0, "ONLY") ;
484 // ------- define the air gap between thermoinsulation and cooler
485 gMC->Gsvolu("PAGA", "BOX ", idtmed[798], emcg->GetAirGapHalfSize(), 3) ;
486 Float_t * agap = emcg->GetAirGapHalfSize() ;
487 y = agap[1] - inthermo[1] ;
489 gMC->Gspos("PTII", 1, "PAGA", 0.0, y, 0.0, 0, "ONLY") ;
493 // ------- define the Al passive cooler
494 gMC->Gsvolu("PCOR", "BOX ", idtmed[701], emcg->GetCoolerHalfSize(), 3) ;
495 Float_t * cooler = emcg->GetCoolerHalfSize() ;
496 y = cooler[1] - agap[1] ;
498 gMC->Gspos("PAGA", 1, "PCOR", 0.0, y, 0.0, 0, "ONLY") ;
500 // ------- define the outer thermoinsulating cover
501 gMC->Gsvolu("PTIO", "TRD1", idtmed[706], emcg->GetOuterThermoParams(), 4) ;
502 Float_t * outparams = emcg->GetOuterThermoParams() ;
505 AliMatrix(idrotm[1], 90.0, 0.0, 0.0, 0.0, 90.0, 270.0) ;
506 // Frame in outer thermoinsulation and so on: z out of beam, y along beam, x across beam
508 z = outparams[3] - cooler[1] ;
509 gMC->Gspos("PCOR", 1, "PTIO", 0., 0.0, z, idrotm[1], "ONLY") ;
511 // -------- Define the outer Aluminium cover -----
512 gMC->Gsvolu("PCOL", "TRD1", idtmed[701], emcg->GetAlCoverParams(), 4) ;
513 Float_t * covparams = emcg->GetAlCoverParams() ;
514 z = covparams[3] - outparams[3] ;
515 gMC->Gspos("PTIO", 1, "PCOL", 0., 0.0, z, 0, "ONLY") ;
517 // --------- Define front fiberglass cover -----------
518 gMC->Gsvolu("PFGC", "BOX ", idtmed[717], emcg->GetFiberGlassHalfSize(), 3) ;
520 gMC->Gspos("PFGC", 1, "PCOL", 0., 0.0, z, 0, "ONLY") ;
522 //=============This is all with cold section==============
525 //------ Warm Section --------------
526 gMC->Gsvolu("PWAR", "BOX ", idtmed[701], emcg->GetWarmAlCoverHalfSize(), 3) ;
527 Float_t * warmcov = emcg->GetWarmAlCoverHalfSize() ;
529 // --- Define the outer thermoinsulation ---
530 gMC->Gsvolu("PWTI", "BOX ", idtmed[706], emcg->GetWarmThermoHalfSize(), 3) ;
531 Float_t * warmthermo = emcg->GetWarmThermoHalfSize() ;
532 z = -warmcov[2] + warmthermo[2] ;
534 gMC->Gspos("PWTI", 1, "PWAR", 0., 0.0, z, 0, "ONLY") ;
536 // --- Define cables area and put in it T-supports ----
537 gMC->Gsvolu("PCA1", "BOX ", idtmed[718], emcg->GetTCables1HalfSize(), 3) ;
538 Float_t * cbox = emcg->GetTCables1HalfSize() ;
540 gMC->Gsvolu("PBE1", "BOX ", idtmed[701], emcg->GetTSupport1HalfSize(), 3) ;
541 Float_t * beams = emcg->GetTSupport1HalfSize() ;
543 for(isup = 0; isup < emcg->GetNTSuppots(); isup++){
544 Float_t x = -cbox[0] + beams[0] + (2*beams[0]+emcg->GetTSupportDist())*isup ;
545 gMC->Gspos("PBE1", isup, "PCA1", x, 0.0, 0.0, 0, "ONLY") ;
548 z = -warmthermo[2] + cbox[2] ;
549 gMC->Gspos("PCA1", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;
551 gMC->Gsvolu("PCA2", "BOX ", idtmed[718], emcg->GetTCables2HalfSize(), 3) ;
552 Float_t * cbox2 = emcg->GetTCables2HalfSize() ;
554 gMC->Gsvolu("PBE2", "BOX ", idtmed[701], emcg->GetTSupport2HalfSize(), 3) ;
555 for(isup = 0; isup < emcg->GetNTSuppots(); isup++){
556 Float_t x = -cbox[0] + beams[0] + (2*beams[0]+emcg->GetTSupportDist())*isup ;
557 gMC->Gspos("PBE2", isup, "PCA2", x, 0.0, 0.0, 0, "ONLY") ;
560 z = -warmthermo[2] + 2*cbox[2] + cbox2[2];
561 gMC->Gspos("PCA2", 1, "PWTI", 0.0, 0.0, z, 0, "ONLY") ;
564 // --- Define frame ---
565 gMC->Gsvolu("PFRX", "BOX ", idtmed[716], emcg->GetFrameXHalfSize(), 3) ;
566 Float_t * posit = emcg->GetFrameXPosition() ;
567 gMC->Gspos("PFRX", 1, "PWTI", posit[0], posit[1], posit[2], 0, "ONLY") ;
568 gMC->Gspos("PFRX", 2, "PWTI", posit[0], -posit[1], posit[2], 0, "ONLY") ;
570 gMC->Gsvolu("PFRZ", "BOX ", idtmed[716], emcg->GetFrameZHalfSize(), 3) ;
571 posit = emcg->GetFrameZPosition() ;
572 gMC->Gspos("PFRZ", 1, "PWTI", posit[0], posit[1], posit[2], 0, "ONLY") ;
573 gMC->Gspos("PFRZ", 2, "PWTI", -posit[0], posit[1], posit[2], 0, "ONLY") ;
575 // --- Define Fiber Glass support ---
576 gMC->Gsvolu("PFG1", "BOX ", idtmed[717], emcg->GetFGupXHalfSize(), 3) ;
577 posit = emcg->GetFGupXPosition() ;
578 gMC->Gspos("PFG1", 1, "PWTI", posit[0], posit[1], posit[2], 0, "ONLY") ;
579 gMC->Gspos("PFG1", 2, "PWTI", posit[0], -posit[1], posit[2], 0, "ONLY") ;
581 gMC->Gsvolu("PFG2", "BOX ", idtmed[717], emcg->GetFGupZHalfSize(), 3) ;
582 posit = emcg->GetFGupZPosition() ;
583 gMC->Gspos("PFG2", 1, "PWTI", posit[0], posit[1], posit[2], 0, "ONLY") ;
584 gMC->Gspos("PFG2", 2, "PWTI", -posit[0], posit[1], posit[2], 0, "ONLY") ;
586 gMC->Gsvolu("PFG3", "BOX ", idtmed[717], emcg->GetFGlowXHalfSize(), 3) ;
587 posit = emcg->GetFGlowXPosition() ;
588 gMC->Gspos("PFG3", 1, "PWTI", posit[0], posit[1], posit[2], 0, "ONLY") ;
589 gMC->Gspos("PFG3", 2, "PWTI", posit[0], -posit[1], posit[2], 0, "ONLY") ;
591 gMC->Gsvolu("PFG4", "BOX ", idtmed[717], emcg->GetFGlowZHalfSize(), 3) ;
592 posit = emcg->GetFGlowZPosition() ;
593 gMC->Gspos("PFG4", 1, "PWTI", posit[0], posit[1], posit[2], 0, "ONLY") ;
594 gMC->Gspos("PFG4", 2, "PWTI", -posit[0], posit[1], posit[2], 0, "ONLY") ;
596 // --- Define Air Gap for FEE electronics -----
598 gMC->Gsvolu("PAFE", "BOX ", idtmed[798], emcg->GetFEEAirHalfSize(), 3) ;
599 posit = emcg->GetFEEAirPosition() ;
600 gMC->Gspos("PAFE", 1, "PWTI", posit[0], posit[1], posit[2], 0, "ONLY") ;
602 // Define the EMC module volume and combine Cool and Warm sections
604 gMC->Gsvolu("PEMC", "TRD1", idtmed[798], emcg->GetEMCParams(), 4) ;
607 gMC->Gspos("PCOL", 1, "PEMC", 0., 0., z, 0, "ONLY") ;
609 gMC->Gspos("PWAR", 1, "PEMC", 0., 0., z, 0, "ONLY") ;
612 // Put created EMC geometry into PHOS volume
614 z = geom->GetCPVBoxSize(1) / 2. ;
615 gMC->Gspos("PEMC", 1, "PHOS", 0., 0., z, 0, "ONLY") ;
619 //____________________________________________________________________________
620 void AliPHOSv0::CreateGeometryforCPV()
622 // Create the PHOS-CPV geometry for GEANT
623 // Author: Yuri Kharlov 11 September 2000
627 Geant3 geometry of PHOS-CPV in ALICE
632 <td>CPV perspective view</td>
633 <td>CPV front view </td>
637 <td> <img height=300 width=290 src="../images/CPVallPersp.gif"> </td>
638 <td> <img height=300 width=290 src="../images/CPVallFront.gif"> </td>
642 <td>One CPV module, perspective view </td>
643 <td>One CPV module, front view (extended in vertical direction) </td>
647 <td><img height=300 width=290 src="../images/CPVmodulePers.gif"></td>
648 <td><img height=300 width=290 src="../images/CPVmoduleSide.gif"></td>
654 Geant3 geometry tree of PHOS-CPV in ALICE
657 <img height=300 width=290 src="../images/CPVtree.gif">
662 Float_t par[3], x,y,z;
664 // Get pointer to the array containing media indexes
665 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
667 AliPHOSGeometry * geom = GetGeometry() ;
669 // The box containing all CPV for one PHOS module filled with air
670 par[0] = geom->GetCPVBoxSize(0) / 2.0 ;
671 par[1] = geom->GetCPVBoxSize(1) / 2.0 ;
672 par[2] = geom->GetCPVBoxSize(2) / 2.0 ;
673 gMC->Gsvolu("PCPV", "BOX ", idtmed[798], par, 3) ;
675 Float_t * emcParams = geom->GetEMCAGeometry()->GetEMCParams() ;
678 AliMatrix(rotm, 90.,0., 0., 0., 90., 90.) ;
680 gMC->Gspos("PCPV", 1, "PHOS", 0.0, 0.0, z, rotm, "ONLY") ;
684 par[0] = geom->GetGassiplexChipSize(0)/2.;
685 par[1] = geom->GetGassiplexChipSize(1)/2.;
686 par[2] = geom->GetGassiplexChipSize(2)/2.;
687 gMC->Gsvolu("PCPC","BOX ",idtmed[707],par,3);
689 // Cu+Ni foil covers Gassiplex board
691 par[1] = geom->GetCPVCuNiFoilThickness()/2;
692 gMC->Gsvolu("PCPD","BOX ",idtmed[710],par,3);
693 y = -(geom->GetGassiplexChipSize(1)/2 - par[1]);
694 gMC->Gspos("PCPD",1,"PCPC",0,y,0,0,"ONLY");
696 // Position of the chip inside CPV
698 Float_t xStep = geom->GetCPVActiveSize(0) / (geom->GetNumberOfCPVChipsPhi() + 1);
699 Float_t zStep = geom->GetCPVActiveSize(1) / (geom->GetNumberOfCPVChipsZ() + 1);
701 y = geom->GetCPVFrameSize(1)/2 - geom->GetFTPosition(0) +
702 geom->GetCPVTextoliteThickness() / 2 + geom->GetGassiplexChipSize(1) / 2 + 0.1;
703 for (Int_t ix=0; ix<geom->GetNumberOfCPVChipsPhi(); ix++) {
704 x = xStep * (ix+1) - geom->GetCPVActiveSize(0)/2;
705 for (Int_t iz=0; iz<geom->GetNumberOfCPVChipsZ(); iz++) {
707 z = zStep * (iz+1) - geom->GetCPVActiveSize(1)/2;
708 gMC->Gspos("PCPC",copy,"PCPV",x,y,z,0,"ONLY");
712 // Foiled textolite (1 mm of textolite + 50 mkm of Cu + 6 mkm of Ni)
714 par[0] = geom->GetCPVActiveSize(0) / 2;
715 par[1] = geom->GetCPVTextoliteThickness() / 2;
716 par[2] = geom->GetCPVActiveSize(1) / 2;
717 gMC->Gsvolu("PCPF","BOX ",idtmed[707],par,3);
721 par[1] = (geom->GetFTPosition(2) - geom->GetFTPosition(1) - geom->GetCPVTextoliteThickness()) / 2;
722 gMC->Gsvolu("PCPG","BOX ",idtmed[715],par,3);
724 for (Int_t i=0; i<4; i++) {
725 y = geom->GetCPVFrameSize(1) / 2 - geom->GetFTPosition(i) + geom->GetCPVTextoliteThickness()/2;
726 gMC->Gspos("PCPF",i+1,"PCPV",0,y,0,0,"ONLY");
728 y-= (geom->GetFTPosition(2) - geom->GetFTPosition(1)) / 2;
729 gMC->Gspos("PCPG",1,"PCPV ",0,y,0,0,"ONLY");
733 // Dummy sensitive plane in the middle of argone gas volume
736 gMC->Gsvolu("PCPQ","BOX ",idtmed[715],par,3);
737 gMC->Gspos ("PCPQ",1,"PCPG",0,0,0,0,"ONLY");
739 // Cu+Ni foil covers textolite
741 par[1] = geom->GetCPVCuNiFoilThickness() / 2;
742 gMC->Gsvolu("PCP1","BOX ",idtmed[710],par,3);
743 y = geom->GetCPVTextoliteThickness()/2 - par[1];
744 gMC->Gspos ("PCP1",1,"PCPF",0,y,0,0,"ONLY");
746 // Aluminum frame around CPV
748 par[0] = geom->GetCPVFrameSize(0)/2;
749 par[1] = geom->GetCPVFrameSize(1)/2;
750 par[2] = geom->GetCPVBoxSize(2) /2;
751 gMC->Gsvolu("PCF1","BOX ",idtmed[701],par,3);
753 par[0] = geom->GetCPVBoxSize(0)/2 - geom->GetCPVFrameSize(0);
754 par[1] = geom->GetCPVFrameSize(1)/2;
755 par[2] = geom->GetCPVFrameSize(2)/2;
756 gMC->Gsvolu("PCF2","BOX ",idtmed[701],par,3);
758 for (Int_t j=0; j<=1; j++) {
759 x = TMath::Sign(1,2*j-1) * (geom->GetCPVBoxSize(0) - geom->GetCPVFrameSize(0)) / 2;
760 gMC->Gspos("PCF1",j+1,"PCPV", x,0,0,0,"ONLY");
761 z = TMath::Sign(1,2*j-1) * (geom->GetCPVBoxSize(2) - geom->GetCPVFrameSize(2)) / 2;
762 gMC->Gspos("PCF2",j+1,"PCPV",0, 0,z,0,"ONLY");
768 //____________________________________________________________________________
769 void AliPHOSv0::CreateGeometryforSupport()
771 // Create the PHOS' support geometry for GEANT
775 Geant3 geometry of the PHOS's support
778 <IMG Align=BOTTOM ALT="EMC geant tree" SRC="../images/PHOS_support.gif">
783 Float_t par[5], x0,y0,z0 ;
786 // Get pointer to the array containing media indexes
787 Int_t *idtmed = fIdtmed->GetArray() - 699 ;
789 AliPHOSGeometry * geom = GetGeometry() ;
791 // --- Dummy box containing two rails on which PHOS support moves
792 // --- Put these rails to the bottom of the L3 magnet
794 par[0] = geom->GetRailRoadSize(0) / 2.0 ;
795 par[1] = geom->GetRailRoadSize(1) / 2.0 ;
796 par[2] = geom->GetRailRoadSize(2) / 2.0 ;
797 gMC->Gsvolu("PRRD", "BOX ", idtmed[798], par, 3) ;
799 y0 = -(geom->GetRailsDistanceFromIP() - geom->GetRailRoadSize(1) / 2.0) ;
800 gMC->Gspos("PRRD", 1, "ALIC", 0.0, y0, 0.0, 0, "ONLY") ;
802 // --- Dummy box containing one rail
804 par[0] = geom->GetRailOuterSize(0) / 2.0 ;
805 par[1] = geom->GetRailOuterSize(1) / 2.0 ;
806 par[2] = geom->GetRailOuterSize(2) / 2.0 ;
807 gMC->Gsvolu("PRAI", "BOX ", idtmed[798], par, 3) ;
809 for (i=0; i<2; i++) {
810 x0 = (2*i-1) * geom->GetDistanceBetwRails() / 2.0 ;
811 gMC->Gspos("PRAI", i, "PRRD", x0, 0.0, 0.0, 0, "ONLY") ;
814 // --- Upper and bottom steel parts of the rail
816 par[0] = geom->GetRailPart1(0) / 2.0 ;
817 par[1] = geom->GetRailPart1(1) / 2.0 ;
818 par[2] = geom->GetRailPart1(2) / 2.0 ;
819 gMC->Gsvolu("PRP1", "BOX ", idtmed[716], par, 3) ;
821 y0 = - (geom->GetRailOuterSize(1) - geom->GetRailPart1(1)) / 2.0 ;
822 gMC->Gspos("PRP1", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
823 y0 = (geom->GetRailOuterSize(1) - geom->GetRailPart1(1)) / 2.0 - geom->GetRailPart3(1);
824 gMC->Gspos("PRP1", 2, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
826 // --- The middle vertical steel parts of the rail
828 par[0] = geom->GetRailPart2(0) / 2.0 ;
829 par[1] = geom->GetRailPart2(1) / 2.0 ;
830 par[2] = geom->GetRailPart2(2) / 2.0 ;
831 gMC->Gsvolu("PRP2", "BOX ", idtmed[716], par, 3) ;
833 y0 = - geom->GetRailPart3(1) / 2.0 ;
834 gMC->Gspos("PRP2", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
836 // --- The most upper steel parts of the rail
838 par[0] = geom->GetRailPart3(0) / 2.0 ;
839 par[1] = geom->GetRailPart3(1) / 2.0 ;
840 par[2] = geom->GetRailPart3(2) / 2.0 ;
841 gMC->Gsvolu("PRP3", "BOX ", idtmed[716], par, 3) ;
843 y0 = (geom->GetRailOuterSize(1) - geom->GetRailPart3(1)) / 2.0 ;
844 gMC->Gspos("PRP3", 1, "PRAI", 0.0, y0, 0.0, 0, "ONLY") ;
846 // --- The wall of the cradle
847 // --- The wall is empty: steel thin walls and air inside
849 par[1] = TMath::Sqrt(TMath::Power((geom->GetIPtoCPVDistance() + geom->GetOuterBoxSize(3)),2) +
850 TMath::Power((geom->GetOuterBoxSize(1)/2),2))+10. ;
851 par[0] = par[1] - geom->GetCradleWall(1) ;
852 par[2] = geom->GetCradleWall(2) / 2.0 ;
853 par[3] = geom->GetCradleWall(3) ;
854 par[4] = geom->GetCradleWall(4) ;
855 gMC->Gsvolu("PCRA", "TUBS", idtmed[716], par, 5) ;
857 par[0] += geom->GetCradleWallThickness() ;
858 par[1] -= geom->GetCradleWallThickness() ;
859 par[2] -= geom->GetCradleWallThickness() ;
860 gMC->Gsvolu("PCRE", "TUBS", idtmed[798], par, 5) ;
861 gMC->Gspos ("PCRE", 1, "PCRA", 0.0, 0.0, 0.0, 0, "ONLY") ;
863 for (i=0; i<2; i++) {
864 z0 = (2*i-1) * (geom->GetOuterBoxSize(2) + geom->GetCradleWall(2) )/ 2.0 ;
865 gMC->Gspos("PCRA", i, "ALIC", 0.0, 0.0, z0, 0, "ONLY") ;
868 // --- The "wheels" of the cradle
870 par[0] = geom->GetCradleWheel(0) / 2;
871 par[1] = geom->GetCradleWheel(1) / 2;
872 par[2] = geom->GetCradleWheel(2) / 2;
873 gMC->Gsvolu("PWHE", "BOX ", idtmed[716], par, 3) ;
875 y0 = -(geom->GetRailsDistanceFromIP() - geom->GetRailRoadSize(1) -
876 geom->GetCradleWheel(1)/2) ;
877 for (i=0; i<2; i++) {
878 z0 = (2*i-1) * ((geom->GetOuterBoxSize(2) + geom->GetCradleWheel(2))/ 2.0 +
879 geom->GetCradleWall(2));
880 for (j=0; j<2; j++) {
882 x0 = (2*j-1) * geom->GetDistanceBetwRails() / 2.0 ;
883 gMC->Gspos("PWHE", copy, "ALIC", x0, y0, z0, 0, "ONLY") ;
889 //_____________________________________________________________________________
890 void AliPHOSv0::AddAlignableVolumes() const
893 // Create entries for alignable volumes associating the symbolic volume
894 // name with the corresponding volume path. Needs to be syncronized with
895 // eventual changes in the geometry
896 // Alignable volumes are:
897 // 1) PHOS modules as a whole
900 // 4) Strip units (group of 2x8 crystals)
902 TString volpath, symname;
905 // Volume path /ALIC_1/PHOS_<i> => symbolic name /PHOS/Module<i>, <i>=1,2,3,4,5
907 TString physModulePath="/ALIC_1/PHOS_";
908 TString symbModuleName="PHOS/Module";
909 Int_t nModules = GetGeometry()->GetNModules();
911 for(Int_t iModule=1; iModule<=nModules; iModule++){
912 volpath = physModulePath;
914 symname = symbModuleName;
916 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
919 //Aligning of CPV should be done for volume PCPV_1
920 symbModuleName="PHOS/Module";
921 Double_t rotMatrix[9] ;
922 for(Int_t iModule=1; iModule<=nModules; iModule++){
923 volpath = physModulePath;
925 volpath += "/PCPV_1";
926 symname = symbModuleName;
929 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
931 // Creates the TGeo Local to Tracking transformation matrix ...
932 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntry(symname.Data()) ;
933 const char *path = alignableEntry->GetTitle();
934 if (!gGeoManager->cd(path))
935 AliFatal(Form("Volume path %s not valid!",path));
936 TGeoHMatrix *matLtoT = new TGeoHMatrix;
940 rotMatrix[0]= 1; rotMatrix[1]= 0; rotMatrix[2]= 0; //
941 rotMatrix[3]= 0; rotMatrix[4]= 0; rotMatrix[5]= 1; //
942 rotMatrix[6]= 0; rotMatrix[7]= 1; rotMatrix[8]= 0;
944 rot.SetMatrix(rotMatrix);
945 matLtoT->MultiplyLeft(&rot);
946 TGeoHMatrix *matTtoL = new TGeoHMatrix(matLtoT->Inverse());
948 alignableEntry->SetMatrix(matTtoL);
952 // Alignable cradle walls
953 // Volume path /ALIC_1/PCRA_<i> => symbolic name /PHOS/Cradle<i>, <i>=0,1
955 TString physCradlePath="/ALIC_1/PCRA_";
956 TString symbCradleName="PHOS/Cradle";
959 for(Int_t iCradle=0; iCradle<nCradles; iCradle++){
960 volpath = physCradlePath;
962 symname = symbCradleName;
964 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
968 // Volume path /ALIC_1/PWHE_<i> => symbolic name /PHOS/Wheel<i>, i=0,1,2,3
970 TString physWheelPath="/ALIC_1/PWHE_";
971 TString symbWheelName="PHOS/Wheel";
974 for(Int_t iWheel=0; iWheel<nWheels; iWheel++){
975 volpath = physWheelPath;
977 symname = symbWheelName;
979 gGeoManager->SetAlignableEntry(symname.Data(),volpath.Data());
982 //Physical strip path is a combination of: physModulePath + module number +
983 //physStripPath + strip number == ALIC_1/PHOS_N/..../PSTR_M
984 const Int_t nStripsX = GetGeometry()->GetEMCAGeometry()->GetNStripX();
985 const Int_t nStripsZ = GetGeometry()->GetEMCAGeometry()->GetNStripZ();
986 TString partialPhysStripName(100);
987 TString fullPhysStripName(100);
988 TString partialSymbStripName(100);
989 TString fullSymbStripName(100);
991 for(Int_t module = 1; module <= nModules; ++module){
992 partialPhysStripName = physModulePath;
993 partialPhysStripName += module;
994 partialPhysStripName += "/PEMC_1/PCOL_1/PTIO_1/PCOR_1/PAGA_1/PTII_1/PSTR_";
996 partialSymbStripName = symbModuleName;
997 partialSymbStripName += module;
998 partialSymbStripName += "/Strip_";
1000 for(Int_t i = 0, ind1D = 1; i < nStripsX; ++i){//ind1D starts from 1 (PSTR_1...PSTR_224...)
1001 for(Int_t j = 0; j < nStripsZ; ++j, ++ind1D){
1002 fullPhysStripName = partialPhysStripName;
1003 fullPhysStripName += ind1D;
1005 fullSymbStripName = partialSymbStripName;
1006 fullSymbStripName += i;//ind1D;
1007 fullSymbStripName += '_';
1008 fullSymbStripName += j;
1010 gGeoManager->SetAlignableEntry(fullSymbStripName.Data(), fullPhysStripName.Data());
1012 // Creates the TGeo Local to Tracking transformation matrix ...
1013 TGeoPNEntry *alignableEntry = gGeoManager->GetAlignableEntry(fullSymbStripName.Data()) ;
1014 const char *path = alignableEntry->GetTitle();
1015 if (!gGeoManager->cd(path))
1016 AliFatal(Form("Volume path %s not valid!",path));
1017 TGeoHMatrix matLtoT = *gGeoManager->GetCurrentMatrix() ;
1018 Double_t refl[3]={-1.,-1.,-1.} ;
1019 matLtoT.SetScale(refl) ;
1020 TGeoHMatrix *matTtoL = new TGeoHMatrix(matLtoT.Inverse());
1023 sprintf(phosPath,"/ALIC_1/PHOS_%d",module) ;
1024 if (!gGeoManager->cd(phosPath)){
1025 AliFatal("Geo manager can not find path \n");
1027 TGeoHMatrix *mPHOS = gGeoManager->GetCurrentMatrix();
1029 matTtoL->Multiply(mPHOS);
1031 AliFatal("Geo matrixes are not loaded \n") ;
1034 Double_t rot[9]={1.,0.,0., 0.,1.,0., 0.,0.,1.} ;
1035 matTtoL->SetRotation(rot) ;
1036 alignableEntry->SetMatrix(matTtoL);
1039 //Check poisition of corner cell of the strip
1040 AliPHOSGeometry * geom = AliPHOSGeometry::GetInstance() ;
1044 Int_t iStrip=ind1D ;
1046 Int_t raw = geom->GetEMCAGeometry()->GetNCellsXInStrip()*((iStrip-1)/geom->GetEMCAGeometry()->GetNStripZ()) +
1047 1 + (icell-1)/geom->GetEMCAGeometry()->GetNCellsZInStrip() ;
1048 Int_t col = geom->GetEMCAGeometry()->GetNCellsZInStrip()*(1+(iStrip-1)%geom->GetEMCAGeometry()->GetNStripZ()) -
1049 (icell-1)%geom->GetEMCAGeometry()->GetNCellsZInStrip() ;
1050 if(col==0) col=geom->GetNZ() ;
1054 geom->RelPosInModule(relid, xG, zG) ;
1055 printf("============\n") ;
1056 printf("Geometry: x=%f, z=%f \n",xG,zG) ;
1058 geom->RelToAbsNumbering(relid,absid) ;
1059 Double_t pos[3]= {-2.2*3.5,0.0,1.1}; //Position incide the strip (Y coordinalte is not important)
1060 Double_t posC[3]={0.0,0.0,0.}; //Global position
1062 matTtoL->MasterToLocal(pos,posC);
1063 printf("Matrix: x=%f, z=%f, y=%f \n",posC[0],posC[2],posC[1]) ;
1070 //____________________________________________________________________________
1071 Float_t AliPHOSv0::ZMin(void) const
1073 // Overall dimension of the PHOS (min)
1075 AliPHOSGeometry * geom = GetGeometry() ;
1077 return -geom->GetOuterBoxSize(2)/2.;
1080 //____________________________________________________________________________
1081 Float_t AliPHOSv0::ZMax(void) const
1083 // Overall dimension of the PHOS (max)
1085 AliPHOSGeometry * geom = GetGeometry() ;
1087 return geom->GetOuterBoxSize(2)/2.;
1090 //____________________________________________________________________________
1091 void AliPHOSv0::Init(void)
1093 // Just prints an information message
1097 if(AliLog::GetGlobalDebugLevel()>0) {
1101 Info("Init", "%s", st.Data()) ;
1102 // Here the PHOS initialisation code (if any!)
1104 AliPHOSGeometry * geom = GetGeometry() ;
1107 Info("Init", "AliPHOS%s: PHOS geometry intialized for %s", Version().Data(), geom->GetName()) ;
1109 Info("Init", "AliPHOS%s: PHOS geometry initialization failed !", Version().Data()) ;
1111 Info("Init", "%s", st.Data()) ;