]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDGeometryBuilder.cxx
Use frag model
[u/mrichter/AliRoot.git] / FMD / AliFMDGeometryBuilder.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 /* $Id$ */
16 /** @file    AliFMDGeometryBuilder.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Mon Mar 27 12:41:17 2006
19     @brief   Class to build the FMD geometry 
20 */
21 //____________________________________________________________________
22 //                                                                          
23 // Builder of FMD geometry. 
24 //
25 // This class takes care of actually building the geometry using the 
26 // TGeo classes.  Various parameters are fecthed from the
27 // AliFMDGeometry manager.  
28 // Forward Multiplicity Detector based on Silicon wafers. This class
29 // contains the base procedures for the Forward Multiplicity detector
30 // Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
31 // which has 1 or 2 rings of silicon sensors. 
32 //                                                       
33 // 
34
35 #include <TArrayD.h>            // ROOT_TArrayD
36 #include <TGeoManager.h>        // ROOT_TGeoManager
37 #include <TGeoMatrix.h>         // ROOT_TGeoMatrix
38 #include <TGeoTube.h>           // ROOT_TGeoTube
39 #include <TGeoTrd1.h>           // ROOT_TGeoTrd1
40 #include <TGeoCone.h>           // ROOT_TGeoTrd1
41 #include <TGeoVolume.h>         // ROOT_TGeoVolume
42 #include <TGeoXtru.h>           // ROOT_TGeoXtru
43 #include <TGeoPcon.h>           // ROOT_TGeoPcon
44 #include <TGeoTorus.h>          // ROOT_TGeoTorus
45 #include <TGeoCompositeShape.h>
46 #include <TMath.h>
47 #include <TVector2.h>           // ROOT_TVector2
48 #include <TVector3.h>           // ROOT_TVector3
49 //#include <TGeoMaterial.h>     // ROOT_TGeoMaterial
50 //#include <TGeoMedium.h>               // ROOT_TGeoMedium
51 //#include <TGeoPcon.h>         // ROOT_TGeoPcon
52 //#include <TGeoPolygon.h>      // ROOT_TGeoPolygon
53
54 #include "AliFMDGeometryBuilder.h"      // ALIFMDGEOSIMULATOR_H
55 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
56 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
57 #include "AliFMDRing.h"         // ALIFMDRING_H
58 #include "AliFMD1.h"            // ALIFMD1_H
59 #include "AliFMD2.h"            // ALIFMD2_H
60 #include "AliFMD3.h"            // ALIFMD3_H
61 // #include "AliFMD.h"          // ALIFMD_H
62 #include "AliFMDDebug.h"                // ALILOG_H
63 #include <iostream>
64
65 //====================================================================
66 ClassImp(AliFMDGeometryBuilder)
67 #if 0
68   ; // This is here to keep Emacs for indenting the next line
69 #endif
70
71 //____________________________________________________________________
72 const Char_t* AliFMDGeometryBuilder::fgkActiveName      = "F%cAC";
73 const Char_t* AliFMDGeometryBuilder::fgkSectorName      = "F%cSC";
74 const Char_t* AliFMDGeometryBuilder::fgkStripName       = "F%cST";
75 const Char_t* AliFMDGeometryBuilder::fgkSensorName      = "F%cSE";
76 const Char_t* AliFMDGeometryBuilder::fgkPCBName         = "F%cPB";
77 const Char_t* AliFMDGeometryBuilder::fgkCuName          = "F%cCU";
78 const Char_t* AliFMDGeometryBuilder::fgkChipName        = "F%cCH";
79 const Char_t* AliFMDGeometryBuilder::fgkLongLegName     = "F%cLL";
80 const Char_t* AliFMDGeometryBuilder::fgkShortLegName    = "F%cSL";
81 const Char_t* AliFMDGeometryBuilder::fgkFrontVName      = "F%cFH";
82 const Char_t* AliFMDGeometryBuilder::fgkBackVName       = "F%cBH";
83 const Char_t* AliFMDGeometryBuilder::fgkRingTopName     = "F%cTV";
84 const Char_t* AliFMDGeometryBuilder::fgkRingBotName     = "F%cBV";
85 const Char_t* AliFMDGeometryBuilder::fgkHCName          = "F%dH%c";
86 const Char_t* AliFMDGeometryBuilder::fgkIHCName         = "F%dI%c";
87 const Char_t* AliFMDGeometryBuilder::fgkNoseName        = "F3SN";
88 const Char_t* AliFMDGeometryBuilder::fgkBackName        = "F%dSB";
89 const Char_t* AliFMDGeometryBuilder::fgkTopName         = "F%dSU";
90 const Char_t* AliFMDGeometryBuilder::fgkBeamName        = "F%dSL";
91 const Char_t* AliFMDGeometryBuilder::fgkFlangeName      = "F%dSF";
92 const Char_t* AliFMDGeometryBuilder::fgkFMDDCuName      = "F%cDC";
93 const Char_t* AliFMDGeometryBuilder::fgkFMDDPCBName     = "F%cDP";
94 const Char_t* AliFMDGeometryBuilder::fgkFMDDChipName    = "F%cDI";
95 const Char_t* AliFMDGeometryBuilder::fgkFMDDName        = "F%cDD";
96 const Char_t* AliFMDGeometryBuilder::fgkFMDName         = "F%dM%c";
97
98 //____________________________________________________________________
99 AliFMDGeometryBuilder::AliFMDGeometryBuilder() 
100   : TTask("FMD", "Geomtry builder"),
101     fActiveId(0),
102     fDetailed(kTRUE),
103     fUseAssembly(kTRUE),
104     fSectorOff(0),
105     fModuleOff(0),
106     fRingOff(0),
107     fDetectorOff(0),
108     fSi(0),
109     fC(0),
110     fAl(0),
111     fPCB(0),
112     fChip(0),
113     fAir(0),
114     fPlastic(0),
115     fCopper(0),
116     fSteel(0)
117 {
118   // Default constructor
119   fActiveId.Set(2);
120 }
121
122 //____________________________________________________________________
123 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) 
124   : TTask("FMD", "Geometry builder"),
125     fActiveId(0),
126     fDetailed(detailed),
127     fUseAssembly(kTRUE),
128     fSectorOff(0),
129     fModuleOff(0),
130     fRingOff(0),
131     fDetectorOff(0),
132     fSi(0),
133     fC(0),
134     fAl(0),
135     fPCB(0),
136     fChip(0),
137     fAir(0),
138     fPlastic(0),
139     fCopper(0),
140     fSteel(0)
141 {
142   // Normal constructor
143   // 
144   // Parameters: 
145   // 
146   //      fmd           Pointer to AliFMD object 
147   //      detailed      Whether to make a detailed simulation or not 
148   // 
149   fActiveId.Set(2);
150 }
151
152 //____________________________________________________________________
153 TGeoShape*
154 AliFMDGeometryBuilder::MakeXTRU(const TObjArray& verticies, 
155                                 Double_t thick) const
156 {
157   TArrayD xs(6);
158   TArrayD ys(6);
159   for (Int_t i = 0; i < 3; i++) { 
160     TVector2* v = static_cast<TVector2*>(verticies.At(i+1));
161     xs[i]     =  v->Y();
162     ys[i]     = -v->X();
163     xs[6-1-i] =  v->Y();
164     ys[6-1-i] =  v->X();
165   }
166   TGeoXtru* shape = new TGeoXtru(2);
167   shape->DefinePolygon(xs.fN, xs.fArray, ys.fArray);
168   shape->DefineSection(0, -thick/2);
169   shape->DefineSection(1, +thick/2);
170   
171   return shape;
172 }
173
174 //____________________________________________________________________
175 TGeoVolume*
176 AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r) 
177 {
178   // Setup the geometry of a ring.    The defined TGeoVolume is
179   // returned, and should be used when setting up the rest of the
180   // volumes. 
181   // 
182   // 
183   // Parameters:
184   //
185   //     r              Pointer to ring geometry object 
186   // 
187   // Returns:
188   //    pointer to ring volume 
189   //
190   if (!r) { 
191     AliError("Didn't get a ring object");
192     return 0;
193   }
194   Char_t        id       = r->GetId();
195   Char_t        rng      = toupper(id);
196   const Char_t* lName    = (rng == 'I' ? "inner" : "outer");
197   Double_t siThick  = r->GetSiThickness();
198   Double_t pcbThick = r->GetPrintboardThickness();
199   Double_t cuThick  = r->GetCopperThickness();
200   Double_t chipThick= r->GetChipThickness();
201   Double_t modSpace = r->GetModuleSpacing();
202   Double_t theta    = r->GetTheta();
203   
204   //------------------------------------------------------------------
205   // Sensor
206   // Physical sensor
207   TGeoShape* sensorShape = MakeXTRU(r->GetSensorVerticies(), siThick);
208   sensorShape->SetName(Form("FMD%c_physical_sensor", id));
209   sensorShape->SetTitle(Form("FMD %s physical sensor", lName));
210   TString sensorName = TString::Format(fgkSensorName, id);
211   TGeoVolume* sensorVolume = new TGeoVolume(sensorName, sensorShape, fSi);
212   sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
213   sensorVolume->VisibleDaughters(kFALSE);
214   Int_t sid = sensorVolume->GetNumber();
215
216   fSectorOff   = -1;
217   fModuleOff   = 1;
218   fRingOff     = 2;
219   fDetectorOff = 3;
220   if (fDetailed) {
221     fSectorOff   = 1;
222     fModuleOff   = 4;
223     fRingOff     = 5;
224     fDetectorOff = 6;
225     // Virtual volume shape to divide - This volume is only defined if
226     // the geometry is set to be detailed. 
227     TGeoTubeSeg* activeShape = new TGeoTubeSeg(r->GetLowR(),
228                                                r->GetHighR(), 
229                                                siThick / 2, 
230                                                - theta, 
231                                                + theta);
232     activeShape->SetName(Form(fgkActiveName, id));
233     activeShape->SetTitle(Form("FMD %s active area", lName));
234     TString activeName = TString::Format(fgkActiveName, id);
235     TGeoVolume* activeVolume = new TGeoVolume(activeName,activeShape,fSi);
236     activeVolume->SetTitle(Form("FMD %s active area", lName));
237     TString sectorName = TString::Format(fgkSectorName,id);
238     TGeoVolume* sectorVolume = activeVolume->Divide(sectorName, 2, 2, -theta,
239                                                     0,0,"N");
240
241     Int_t    ns       = r->GetNStrips();
242     Double_t stripoff = r->GetLowR(); // 0; // a->Mod();
243     Double_t dstrip   = (r->GetHighR() - stripoff) / ns;
244
245     sectorVolume->SetTitle(Form("FMD %s sector", lName));
246     TString stripName = TString::Format(fgkStripName, id);
247     TGeoVolume* stripVolume  = sectorVolume->Divide(stripName, 
248                                                     1, ns, stripoff, dstrip, 
249                                                     0, "SX");
250     stripVolume->SetTitle(Form("FMD %s strip", lName));
251     sid = stripVolume->GetNumber();
252     sensorVolume->AddNodeOverlap(activeVolume, 0);
253   }
254   
255   switch (rng) {
256   case 'I': fActiveId[0] = sid; break;
257   case 'O': fActiveId[1] = sid; break;
258   }
259
260   //------------------------------------------------------------------
261   // Hybrid
262   // PCB layer of hybrid 
263   TGeoShape* pcbShape = MakeXTRU(r->GetHybridVerticies(), pcbThick);
264   pcbShape->SetName(Form("FMD%c_hybrid_pcb", id));
265   pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
266   TString pcbName = TString::Format(fgkPCBName, id);
267   TGeoVolume* pcbVolume = new TGeoVolume(pcbName, pcbShape, fPCB);
268   pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
269
270   // Copper layer
271   TGeoShape* cuShape = MakeXTRU(r->GetHybridVerticies(), cuThick);
272   cuShape->SetName(Form("FMD%c_hybrid_copper", id));
273   cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
274   TString cuName = TString::Format(fgkCuName,id);
275   TGeoVolume* cuVolume = new TGeoVolume(cuName,cuShape,fCopper);
276   cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
277
278   // Chip layer
279   TGeoShape* chipShape = MakeXTRU(r->GetHybridVerticies(), chipThick);
280   chipShape->SetName(Form("FMD%c_hybrid_chip", id));
281   chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
282   TString chipName = TString::Format(fgkChipName,id);
283   TGeoVolume* chipVolume = new TGeoVolume(chipName,chipShape,fChip);
284   chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
285
286   //------------------------------------------------------------------
287   // Legs
288   Double_t      legr     = r->GetLegRadius();
289   Double_t      legl     = r->GetLegLength();
290   Double_t      lege     = .05;
291
292   // Short leg shape 
293   TGeoTube*   shortLegShape  = new TGeoTube(0, legr, (legl-lege) / 2);
294   shortLegShape->SetName(Form(fgkShortLegName, id));
295   shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
296   TString shortLegName = TString::Format(fgkShortLegName, id);
297   TGeoVolume* shortLegVolume = new TGeoVolume(shortLegName, 
298                                               shortLegShape, fCopper);
299   shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
300   // Long leg shape
301   TGeoTube*   longLegShape   = new TGeoTube(0, legr, 
302                                             (legl - lege + modSpace) / 2);
303   longLegShape->SetName(Form(fgkLongLegName, id));
304   longLegShape->SetTitle(Form("FMD %s long support foot", lName));
305   TString longLegName = TString::Format(fgkLongLegName, id);
306   TGeoVolume* longLegVolume = new TGeoVolume(longLegName, 
307                                               longLegShape, fCopper);
308   longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
309   
310
311
312   //------------------------------------------------------------------
313   // Placement of module volumes in assemblies 
314   TArrayD xfs(3);
315   TArrayD yfs(3);
316   for (Int_t i = 0; i < 3; i++) { 
317     TVector2* vv = r->GetFootPosition(i);
318     // TVector2  uu = vv->Rotate(TMath::Pi()/2);
319     xfs[i]       = vv->Y();
320     yfs[i]       = vv->X();
321   }
322
323   // Back container volume 
324   TGeoVolume* backVolume     = new TGeoVolumeAssembly(Form(fgkBackVName, id));
325   backVolume->SetTitle(Form("FMD %s back module", lName));
326   TGeoVolume* frontVolume    = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
327   frontVolume->SetTitle(Form("FMD %s front module", lName));
328
329   Double_t space    = r->GetSpacing();
330   Double_t x        = 0;
331   Double_t y        = 0;
332   Double_t zb       = siThick / 2;
333   Double_t zf       = siThick / 2;
334   backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zb));
335   frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zf));
336   zb         += siThick / 2 + space + pcbThick / 2;
337   zf         += siThick / 2 + space + pcbThick / 2;
338   backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zb));
339   frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zf));
340   zb         += (pcbThick + cuThick) / 2;
341   zf         += (pcbThick + cuThick) / 2;
342   backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zf));
343   frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zb));
344   zb         += (cuThick + chipThick) / 2;
345   zf         += (cuThick + chipThick) / 2;
346   backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zb));
347   frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zf));
348   zb         += pcbThick / 2 + (legl)/ 2  - lege;
349   zf         += pcbThick / 2 + (legl + modSpace)/ 2 - lege;
350   for (Int_t i = 0; i < 3; i++) { 
351     x          =  xfs[i]; // a->X() + legoff + legr;
352     y          =  yfs[i]; // 0;
353     backVolume->AddNode(shortLegVolume, i, new TGeoTranslation(x,y,zb));
354     frontVolume->AddNode(longLegVolume, i, new TGeoTranslation(x,y,zf));
355   }
356
357   //------------------------------------------------------------------
358   // FMDD 
359   Double_t ddlr = r->GetFMDDLowR();
360   Double_t ddhr = r->GetFMDDHighR();
361   Double_t ddpt = r->GetFMDDPrintboardThickness();
362   Double_t ddct = r->GetFMDDCopperThickness();
363   Double_t ddit = r->GetFMDDChipThickness();
364   Double_t ddt  = ddpt + ddct + ddit;
365   
366   TString    pcbdName(Form(fgkFMDDPCBName, id));
367   TString    cudName(Form(fgkFMDDCuName, id));
368   TString    chipdName(Form(fgkFMDDChipName, id));
369   new TGeoTubeSeg(Form("%s_inner", pcbdName.Data()),  ddlr, ddhr, ddpt/2,0,180);
370   new TGeoTubeSeg(Form("%s_inner", cudName.Data()),   ddlr, ddhr, ddct/2,0,180);
371   new TGeoTubeSeg(Form("%s_inner", chipdName.Data()), ddlr, ddhr, ddit/2,0,180);
372   
373   Double_t clipWX = 0;
374   Double_t clipWY = 0;
375   Double_t clipY  = 1;
376   
377   if (rng == 'I') { 
378     clipWX = ddhr;
379     clipWY = ddhr/2;
380   }
381   else { 
382     clipWX = ddlr+3;
383     clipWY = ddhr/2;
384   }
385   
386   new TGeoBBox(Form("%s_clip",  pcbdName.Data()), clipWX, clipWY, ddpt);
387   new TGeoBBox(Form("%s_clip",  cudName.Data()),  clipWX, clipWY, ddct);
388   new TGeoBBox(Form("%s_clip",  chipdName.Data()),clipWX, clipWY, ddit);
389   TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
390                                                     pcbdName.Data()), 
391                                                0, clipWY+clipY, 0);
392   trans->RegisterYourself();
393   TGeoShape* fmddPcbShape = 
394     new TGeoCompositeShape(pcbdName.Data(), 
395                            Form("%s_inner*%s_clip:%s_trans",
396                                 pcbdName.Data(), 
397                                 pcbdName.Data(), 
398                                 pcbdName.Data())); 
399   TGeoShape* fmddCuShape = 
400     new TGeoCompositeShape(cudName.Data(), 
401                            Form("%s_inner*%s_clip:%s_trans",
402                                 cudName.Data(), 
403                                 cudName.Data(), 
404                                 pcbdName.Data()));
405   TGeoShape* fmddChipShape = 
406     new TGeoCompositeShape(chipdName.Data(), 
407                            Form("%s_inner*%s_clip:%s_trans",
408                                 chipdName.Data(), 
409                                 chipdName.Data(), 
410                                 pcbdName.Data()));
411   fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
412   fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
413   fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
414
415   TString fmddPcbName = TString::Format(fgkFMDDPCBName, id);
416   TGeoVolume* fmddPcbVolume = new TGeoVolume(fmddPcbName,
417                                               fmddPcbShape, fPCB);
418   TString fmddCuName = TString::Format(fgkFMDDCuName, id);
419   TGeoVolume* fmddCuVolume = new TGeoVolume(fmddCuName,
420                                               fmddCuShape, fCopper);
421   TString fmddChipName = TString::Format(fgkFMDDChipName, id);
422   TGeoVolume* fmddChipVolume = new TGeoVolume(fmddChipName,
423                                               fmddChipShape, fChip);
424   fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
425   fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
426   fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
427
428   //------------------------------------------------------------------
429   // Half ring mother volumes. 
430   TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
431   TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
432   TGeoVolume* halfRing      = ringTopVolume;
433   ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
434   ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
435   
436   //------------------------------------------------------------------
437   // Adding modules to half-rings
438   Int_t    nmod =  r->GetNModules();
439   AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
440   for (Int_t i = 0; i < nmod; i++) {
441     if (i == nmod / 2) halfRing = ringBotVolume;
442     Bool_t      front =  (i % 2 == (rng == 'I' ? 1 : 0));
443     TGeoVolume* vol   =  (front ? frontVolume : backVolume);
444     // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
445     Double_t    z1    =  (front ? -1 : 1) * modSpace / 2;
446     // Double_t z1    =  (front ? 0 : modSpace);
447     Double_t    th    =  (2 * i + 1) * theta;
448     TGeoMatrix* mat1  =  new TGeoCombiTrans(0,0,z1,0); 
449     mat1->RotateZ(th);
450     mat1->SetName(Form("FMD%c_module_%02d", id, i));
451     mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
452     halfRing->AddNode(vol, i, mat1);
453   }
454
455   //------------------------------------------------------------------
456   // Add the FMDD 
457   Double_t zi = r->GetFullDepth() - ddt;
458   Int_t    n  = 2;
459   for (Int_t i = 0; i  < n; i++) {
460     halfRing             = (i == 0 ? ringTopVolume : ringBotVolume);
461     Double_t      phi    = 360. / n * i;
462     TGeoRotation* rot    = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
463     rot->RotateZ(phi);
464     rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
465     Double_t z =  zi + ddpt / 2;
466     halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
467     z          += (ddpt + ddct) / 2;
468     halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
469     z          += (ddct + ddit) / 2;
470     halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
471   }
472   
473
474   return 0;
475 }
476
477
478 //____________________________________________________________________
479 TGeoShape*
480 AliFMDGeometryBuilder::HoneycombShape(Int_t id, Char_t ring,
481                                       double r1, double r2, 
482                                       double w, double t, double c)
483 {
484   // Make a honey comb shape from passed parameters.
485   // Parameters: 
486   //   id       Detector identifier (1,2, or 3)
487   //   ring     Ring identifier ('I' or 'O')
488   //   r1       Inner radius
489   //   r2       Outer radius
490   //   w        width 
491   //   t        Thickness of material 
492   //   c        Clearing from horizontal. 
493   // Return 
494   //   Pointer to newly allocated composite shape. 
495   TString      form  = Form("FMD%d%c_%%c_%%c", id, ring);
496   double       a1    = TMath::ATan2(c, r1) * 180  / TMath::Pi();
497
498   TString      fn    = Form(form.Data(),'F','1');
499   TString      bn    = Form(form.Data(),'B','1');
500   TString      cn    = Form(form.Data(),'C','O');
501   TString      in    = Form(form.Data(),'R','I');
502   TString      on    = Form(form.Data(),'R','O');
503   TString      en    = Form(form.Data(),'E','X');
504   double       y     = c;
505   double       x     = r1 * TMath::Cos(TMath::Pi()*a1/180);
506   new TGeoTubeSeg(fn.Data(),r1,r2,t/2,0,180);
507   new TGeoTubeSeg(bn.Data(),r1,r2,t/2,0,180);
508   new TGeoBBox(cn.Data(),(r2-r1)/2,t/2,w/2);
509   new TGeoTubeSeg(in.Data(),r1,r1+t,w/2,0,180);
510   new TGeoTubeSeg(on.Data(),r2-t,r2,w/2,0,180);
511   new TGeoBBox(en.Data(),r2+.005,c/2+.005,w/2+.005);
512     
513   TString          ftn = Form(form.Data(),'F','T');
514   TString          btn = Form(form.Data(),'F','B');
515   TString          ltn = Form(form.Data(),'C','L');
516   TString          rtn = Form(form.Data(),'C','R');
517   TString          etn = Form(form.Data(),'E','X');
518   (new TGeoTranslation(ftn.Data(),0,0,+w/2-t/2))->RegisterYourself();
519   (new TGeoTranslation(btn.Data(),0,0,-w/2+t/2))->RegisterYourself();
520   (new TGeoTranslation(ltn.Data(),-(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
521   (new TGeoTranslation(rtn.Data(),(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
522   (new TGeoTranslation(etn.Data(),0, c/2,0))->RegisterYourself();
523   
524   TString comp(Form("(%s:%s+%s:%s+%s+%s+%s:%s+%s:%s)-%s:%s", 
525                     fn.Data(),ftn.Data(),
526                     bn.Data(),btn.Data(),
527                     in.Data(),on.Data(),
528                     cn.Data(),ltn.Data(),
529                     cn.Data(),rtn.Data(),
530                     en.Data(),etn.Data()));
531   TGeoCompositeShape* shape = new TGeoCompositeShape(comp.Data());
532   shape->SetName(Form(fgkHCName,id,ring));
533   shape->SetTitle(Form("FMD%d%c Honeycomb shape", id, ring));
534   return shape;
535 }
536
537 //____________________________________________________________________
538 TGeoVolume* 
539 AliFMDGeometryBuilder::TensionBox()
540 {
541   static TGeoVolumeAssembly* tensionBox = 0;
542   if (tensionBox) return tensionBox;
543   
544   TGeoBBox* tensionEndS = new TGeoBBox("FMD_tension_end", .6, 3,  .25);
545   TGeoBBox* tensionTopS = new TGeoBBox("FMD_tension_top", .1, .5, 3.5);
546   TGeoVolume* tensionEndV = new TGeoVolume("FMD_tension_end", tensionEndS,fAl);
547   TGeoVolume* tensionTopV = new TGeoVolume("FMD_tension_top", tensionTopS,fAl);
548   tensionBox = new TGeoVolumeAssembly("FMD_tension_box");
549   tensionBox->AddNode(tensionEndV, 1, new TGeoTranslation(.6, 0,   -3.75));
550   tensionBox->AddNode(tensionEndV, 2, new TGeoTranslation(.6, 0,   +3.75));
551   tensionBox->AddNode(tensionTopV, 1, new TGeoTranslation(0.1, +2.5, 0));
552   tensionBox->AddNode(tensionTopV, 2, new TGeoTranslation(0.1, -2.5, 0));
553   tensionBox->AddNode(tensionTopV, 3, new TGeoTranslation(1.1, +2.5, 0));
554   tensionBox->AddNode(tensionTopV, 4, new TGeoTranslation(1.1, -2.5, 0));
555   return tensionBox;
556 }
557
558
559 //____________________________________________________________________
560 TGeoVolume*
561 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d, 
562                                         TGeoVolume* topMother, 
563                                         TGeoVolume* botMother, 
564                                         Double_t    zMother, 
565                                         TGeoVolume* innerTop, 
566                                         TGeoVolume* innerBot, 
567                                         TGeoVolume* outerTop, 
568                                         TGeoVolume* outerBot) 
569 {
570   // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
571   // This includes putting the Honeycomb support plates and the rings
572   // into the mother volumes.   
573   // 
574   // Parameeters:
575   //    d         The detector geometry to use 
576   //    mother    The mother volume of the detector 
577   //    zmother   The midpoint in global coordinates of detector vol.
578   //    inner     Pointer to inner ring volume 
579   //    outer     Pointer to outer ring volume
580   //
581   // Returns:
582   //    Pointer to mother (detector volume) 
583   // 
584   if (!d) return 0;
585   // Loop over the defined rings 
586   for (int i = 0; i < 2; i++) {
587     AliFMDRing* r     = 0;
588     Double_t    lowr  = 0;
589     Double_t    highr = 0;
590     Double_t    rz    = 0;
591     TGeoVolume* tvol  = 0;
592     TGeoVolume* bvol  = 0;
593     switch (i) {
594     case 0: 
595       r      = d->GetInner();
596       lowr   = d->GetInnerHoneyLowR();
597       highr  = d->GetInnerHoneyHighR();
598       rz     = d->GetInnerZ();
599       tvol   = innerTop;
600       bvol   = innerBot;
601       break;
602     case 1: 
603       r      = d->GetOuter();
604       lowr   = d->GetOuterHoneyLowR();
605       highr  = d->GetOuterHoneyHighR();
606       rz     = d->GetOuterZ();
607       tvol   = outerTop;
608       bvol   = outerBot;
609       break;
610     }
611     if (!r) continue;
612     Char_t   c       = r->GetId();
613     Int_t    id      = d->GetId();
614     Double_t hcThick = r->GetHoneycombThickness();
615     Double_t alThick = r->GetAlThickness();
616     Double_t z       = TMath::Abs(rz - zMother);
617
618     // Place ring in mother volume
619     // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
620     AliFMDDebug(2, ("Placing volumes %s and %s in %s and %s at z=%f", 
621                      tvol->GetName(), bvol->GetName(), 
622                      topMother->GetName(), botMother->GetName(), z));
623     topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
624     botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
625
626     // Honeycomp 
627     TGeoShape*   hcSha = HoneycombShape(id, c, lowr, highr, hcThick, alThick);
628     TGeoVolume*  hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
629     hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
630     
631     z += (r->GetModuleDepth() 
632           + r->GetModuleSpacing() / 2
633           + r->GetHoneycombThickness() / 2);
634
635     AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f", 
636                       hcVol->GetName(), topMother->GetName(), 
637                       botMother->GetName(), z));
638     // Add to top 
639     topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
640
641     // Add to bottom
642     TGeoMatrix*   bhcMatrix = new TGeoCombiTrans(0,0,z,0);
643     bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
644     bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
645     bhcMatrix->RotateZ(180);
646     botMother->AddNode(hcVol, 1, bhcMatrix);
647   }
648   return 0;
649 }
650
651 //____________________________________________________________________
652 TGeoVolume*
653 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1, 
654                                     TGeoVolume* innerTop, 
655                                     TGeoVolume* innerBot) 
656 {
657   // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
658   // special support as it is at the momement. 
659   // 
660   // See also AliFMDGeometryBuilder::DetectorGeometry 
661   // 
662   if (!fmd1 || !innerTop || !innerBot) return 0;
663   AliFMDRing* r             = fmd1->GetInner();
664   Double_t    z             = fmd1->GetInnerZ();  
665   
666   // `Top' or `Outside' master volume
667   TString fmd1TopName = TString::Format(fgkFMDName, fmd1->GetId(), 'T');
668   TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(fmd1TopName);
669   fmd1TopVolume->SetTitle("FMD1 top half");
670
671   // `Bottom' or `Inside' master volume
672   TString fmd1BotName = TString::Format(fgkFMDName, fmd1->GetId(), 'B');
673   TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(fmd1BotName);
674   fmd1BotVolume->SetTitle("FMD1 bottom half");
675   
676   // Basic detector geometry 
677   DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z, 
678                    innerTop, innerBot, 0, 0);
679
680   Double_t lidP[][3] = { {  0.00,  4.20, 20.95 }, 
681                          {  0.15,  4.20, 20.95 }, 
682                          {  0.15, 20.80, 20.95 }, 
683                          {  3.00, 20.80, 20.95 }, 
684                          {  3.00, 20.80, 22.30 }, 
685                          {  3.15, 20.80, 22.30 }, 
686                          {  3.15, 20.95, 24.65 },
687                          {  3.30, 20.95, 24.65 }, 
688                          {  3.30, 24.50, 24.65 }, 
689                          {  6.80, 24.50, 24.65 },
690                          {  6.80, 24.50, 26.00 },
691                          {  6.95, 24.50, 26.00 } };
692   Double_t  lidZStart = lidP[11][0];
693   TGeoPcon* lidBaseS  = new TGeoPcon("FMD1_lid_base", 0, 180, 12);
694   for (size_t i = 0; i < 12; i++) 
695     lidBaseS->DefineSection(i, lidP[i][0] - lidZStart, lidP[i][1], lidP[i][2]);
696   
697   
698   Double_t lidH[][2] = { {  7.84903, 24.15680  }, 
699                          { 20.54900, 14.92970  },
700                          { 21.99700, 12.70000  },
701                          { 25.26090,  2.65502  } };
702   Double_t lidHR = .53 / 2;
703   Double_t lidHL = 0.16;
704   
705   new TGeoTube("FMD1_lid_hole", 0, lidHR, lidHL/2);
706   TString lidComp("FMD1_lid_base-(");
707   TGeoTranslation* trans = 0;
708   for (size_t i = 0; i < 4; i++) { 
709     trans = new TGeoTranslation(-lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
710     trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+0)));
711     trans->RegisterYourself();
712     trans = new TGeoTranslation(+lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
713     trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+1)));
714     trans->RegisterYourself();
715     lidComp.Append(Form("FMD1_lid_hole:FMD1_lid_hole_mat%d+" 
716                         "FMD1_lid_hole:FMD1_lid_hole_mat%d%c", 
717                         int(2 * i), int(2 * i + 1), int(i == 3 ? ')' : '+')));
718   }
719   TGeoCompositeShape* lidS = new TGeoCompositeShape(lidComp.Data());
720   lidS->SetName("FMD1_lid");
721   TGeoVolume* lidV = new TGeoVolume("FMD1_lid", lidS, fC);
722   lidV->SetTransparency(63);
723   
724   // Place top cover
725   Double_t lidZ = (lidZStart - 
726                    (3.3 - r->GetModuleDepth() - r->GetModuleSpacing() / 2));
727   AliFMDDebug(1, ("FMD1 lid offset in Z=%f", lidZ));
728
729   for (Int_t i = 0; i  < 2; i++) {
730     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
731     Double_t      phi    = 360. / 2 * i;
732     TGeoRotation* rot    = new TGeoRotation(Form("FMD1_lid_rot%d",i));
733     rot->RotateZ(phi);
734     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1_lid_mat%d", i),
735                                               0, 0, lidZ, rot);
736     mother->AddNode(lidV, i, matrix);    
737   }
738
739   // Must add this after filling the assembly.
740   TGeoVolume* top    = gGeoManager->GetVolume("ALIC");
741   // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
742   TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
743   rot->RotateZ(90);
744   TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
745
746   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
747                    fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
748   top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
749   top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
750
751
752   // Survey points on V0A (screw holes for the FMD) 
753   const Double_t icb[] = { +12.700, -21.997, 324.670 };
754   const Double_t ict[] = { +12.700, +21.997, 324.670 };
755   const Double_t ocb[] = { -12.700, -21.997, 324.670 };
756   const Double_t oct[] = { -12.700, +21.997, 324.670 };
757
758   TGeoTube* surveyShape = new TGeoTube("FMD1_survey_marker", 
759                                         0, .2, .001);
760
761   TGeoMatrix* outMat = matrix;
762 #if 0
763   if (gGeoManager->cd("/ALIC_1/F1MT_1")) 
764     outMat = gGeoManager->GetCurrentMatrix();
765   else 
766     AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
767 #endif
768
769   Double_t loct[3], locb[3];
770   outMat->MasterToLocal(oct, loct);
771   outMat->MasterToLocal(ocb, locb);
772   TGeoVolume* vOct = new TGeoVolume("V0L_OCT", surveyShape, fPlastic);
773   TGeoVolume* vOcb = new TGeoVolume("V0L_OCB", surveyShape, fPlastic);
774   
775   fmd1TopVolume->AddNode(vOct, 1, new TGeoTranslation(loct[0],loct[1],loct[2]));
776   fmd1TopVolume->AddNode(vOcb, 1, new TGeoTranslation(locb[0],locb[1],locb[2]));
777     
778   
779   TGeoMatrix* inMat = matrix;
780 #if 0
781   if (gGeoManager->cd("/ALIC_1/F1MT_1")) 
782     inMat = gGeoManager->GetCurrentMatrix();
783   else 
784     AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
785 #endif
786
787   Double_t lict[3], licb[3];
788   inMat->MasterToLocal(ict, lict);
789   inMat->MasterToLocal(icb, licb);
790   TGeoVolume* vIct = new TGeoVolume("V0L_ICT", surveyShape, fPlastic);
791   TGeoVolume* vIcb = new TGeoVolume("V0L_ICB", surveyShape, fPlastic);
792   
793   fmd1BotVolume->AddNode(vIct, 1, new TGeoTranslation(lict[0],lict[1],lict[2]));
794   fmd1BotVolume->AddNode(vIcb, 1, new TGeoTranslation(licb[0],licb[1],licb[2]));
795
796   return 0;
797 }
798
799 //____________________________________________________________________
800 TGeoVolume*
801 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, 
802                                     TGeoVolume* innerTop, 
803                                     TGeoVolume* innerBot, 
804                                     TGeoVolume* outerTop,
805                                     TGeoVolume* outerBot) 
806 {
807   // Setup the FMD2 geometry.  The FMD2 has no
808   // special support as it is at the momement. 
809   // 
810   // See also AliFMDGeometryBuilder::DetectorGeometry 
811   // 
812   if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
813   AliFMDRing* ring          = fmd2->GetOuter();
814   Double_t    z             = fmd2->GetOuterZ();  
815   Double_t    framelr       = 32.01;  // fmd2->GetOuterHoneyHighR()+0.5;
816   Double_t    framehr       = 33.611; // fmd2->GetOuterHoneyHighR()+1.8;
817   Double_t    framel        = 14.8; // framehz - framelz;
818   // Double_t    backth        = 0.3;
819   Double_t    backth        = 0.03;
820   Double_t    framelz       = -(2.38 
821                                 - ring->GetModuleDepth() 
822                                 - ring->GetModuleSpacing() / 2);
823   // Double_t    framelz       = -0.8;
824   // Double_t    framehz       = framelz + backth + framel;
825   Double_t    coverlr       = 4.3; // fmd2->GetInner()->GetLowR()+1;
826   Double_t    coverhr       = framehr; //  - 1;
827   
828   TString fmd2TopName = TString::Format(fgkFMDName, fmd2->GetId(), 'T');
829   TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(fmd2TopName);
830   TString fmd2BotName = TString::Format(fgkFMDName, fmd2->GetId(), 'B');
831   TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(fmd2BotName);
832   fmd2TopVolume->SetTitle("FMD2 top half");
833   fmd2BotVolume->SetTitle("FMD2 bottom half");
834   
835   DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, 
836                    innerTop, innerBot, outerTop, outerBot);
837
838   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("FMD2_support");
839   TGeoShape*  cylinderShape   = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
840   TGeoVolume* cylinderVolume  = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
841                                                cylinderShape, fC);
842   TGeoShape*  coverShape      = new TGeoTubeSeg(coverlr,coverhr,backth/2,0,180);
843   TGeoVolume* coverVolume     = new TGeoVolume(Form(fgkTopName, fmd2->GetId()), 
844                                                coverShape, fC);
845   cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
846   cylinderShape->SetTitle("FMD2 cylinder");
847   cylinderVolume->SetTitle("FMD2 cylinder");
848   cylinderVolume->SetTransparency(63);
849   coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
850   coverShape->SetTitle("FMD2 cover");
851   coverVolume->SetTitle("FMD2 cover");
852   coverVolume->SetTransparency(63);
853   
854   TGeoTranslation* trans = 0;
855   support->AddNode(coverVolume,1, new TGeoTranslation(0,0,backth/2));
856   support->AddNode(cylinderVolume, 1, new TGeoTranslation(0,0,backth+framel/2));
857   
858
859   Double_t    f1l            = 15.6085;
860   Double_t    f1w            = 6;
861   Double_t    f1d            = 1;
862   Int_t       nFiducialHoles = 4;
863   Double_t    precHoles[][2] = { { 32.4948, 29.6663 },
864                                  { 33.9104, 31.0819 },
865                                  { 34.8177, 33.4035 }, 
866                                  { 35.5028, 32.6744 } };
867   Double_t    precRadius     = .25;
868   Double_t    flangeA        = TMath::Pi()/4;
869   
870   new TGeoBBox("FMD2_flange_base", f1l/2, f1w/2, f1d/2);
871   new TGeoTube("FMD2_fiducial_hole", 0, precRadius, f1d/2+.1);
872   Double_t         flangeX        = framehr + f1l/2;
873   TVector2         flangeC(flangeX * TMath::Cos(flangeA), 
874                            flangeX * TMath::Sin(flangeA));
875   TString          flangeComb("FMD2_flange_base-(");  
876   new TGeoBBox("FMD2_flange_slit", 7./2, 1.5/2, f1d/2+.1);
877   trans = new TGeoTranslation(-f1l/2+1+7./2, +.5+1.5/2, 0);
878   trans->SetName("FMD2_flange_slit_mat1");
879   trans->RegisterYourself();
880   trans = new TGeoTranslation(-f1l/2+1+7./2, -.5-1.5/2, 0);
881   trans->SetName("FMD2_flange_slit_mat2");
882   trans->RegisterYourself();
883   flangeComb.Append("FMD2_flange_slit:FMD2_flange_slit_mat1+"
884                     "FMD2_flange_slit:FMD2_flange_slit_mat2+");
885   for (Int_t i = 0; i < nFiducialHoles; i++) { 
886     TVector2         v(precHoles[i][0], precHoles[i][1]);
887     v                   -= flangeC;
888     TVector2         r  =  v.Rotate(-flangeA);
889     TGeoTranslation* t1 =  new TGeoTranslation(r.X(),  r.Y(), 0);
890     TGeoTranslation* t2 =  new TGeoTranslation(r.X(), -r.Y(), 0);
891     t1->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+0));
892     t2->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+1));
893     t1->RegisterYourself();
894     t2->RegisterYourself();
895     flangeComb.Append(Form("FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d+"
896                            "FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d%c",
897                            2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
898   }
899   // Final flange shape, and at to full shape 
900   TGeoCompositeShape* flangeS = new TGeoCompositeShape(flangeComb.Data());
901   flangeS->SetName("FMD2_flange");
902   TGeoVolume* flangeV = new TGeoVolume("FMD2_flange", flangeS, fAl);
903   
904   Double_t f2l = 7;
905   Double_t f2d = 12.5;
906   Double_t f2w = 1;
907
908   new TGeoBBox("FMD2_flange_spacer_base", f2l/2, f2w/2, f2d/2);
909   new TGeoTube("FMD2_flange_spacer_hole", 0, 2.5, f2w/2+.1);
910   TGeoRotation* holeRot = new TGeoRotation();
911   holeRot->RotateY(90);
912   holeRot->RotateZ(90);
913   TGeoCombiTrans* combo = 0;
914   combo = new TGeoCombiTrans(0, 0, f2d/2-.5-2.5, holeRot);
915   combo->SetName("FMD2_flange_spacer_hole_mat1");
916   combo->RegisterYourself();
917   combo = new TGeoCombiTrans(0, 0, -f2d/2+.5+2.5, holeRot);
918   combo->SetName("FMD2_flange_spacer_hole_mat2");
919   combo->RegisterYourself();
920   TString spacerComp("FMD2_flange_spacer_base-("
921                      "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat1+"
922                      "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat2)");
923   TGeoCompositeShape* spacerS = new TGeoCompositeShape(spacerComp.Data());
924   TGeoVolume*         spacerV = new TGeoVolume("FMD2_flange_spacer",
925                                                spacerS, fAl);
926
927   Double_t            extraL  = framehr-framelr;
928   TGeoBBox*           extraS  = new TGeoBBox("FMD2_flange_extra", 
929                                              extraL/2, f1w/2, f1d/2);
930   TGeoVolume*         extraV  = new TGeoVolume("FMD2_flange_extra", extraS,fAl);
931   TGeoVolumeAssembly* wingV   = new TGeoVolumeAssembly("FMD2_wing");
932   TGeoVolume*         tension = TensionBox();
933   TGeoTube*           wireS   = new TGeoTube(0, .05, (framehr-coverlr)/2);
934   TGeoVolume*         wireV   = new TGeoVolume("FMD2_tension_wire", 
935                                                wireS, fSteel);
936   wingV->AddNode(flangeV, 1, new TGeoTranslation(f1l/2,    0, f1d/2));
937   wingV->AddNode(flangeV, 2, new TGeoTranslation(f1l/2,    0, -f2d-f1d/2));
938   wingV->AddNode(extraV, 1, new TGeoCombiTrans(-extraL/2, 0, f1d/2, 0));
939   wingV->AddNode(spacerV, 1, new TGeoTranslation(1+f2l/2,-f2w/2+f1w/2,
940                                                  -f2d/2));
941   wingV->AddNode(spacerV, 2, new TGeoTranslation(1+f2l/2,+f2w/2-f1w/2,
942                                                  -f2d/2));
943   TGeoRotation* tensionR = new TGeoRotation;
944   tensionR->RotateY(90);
945   wingV->AddNode(tension, 1, new TGeoCombiTrans(4, 0, f1d+1.2, tensionR));
946   TGeoRotation* wireR = new TGeoRotation;
947   wireR->RotateY(90);
948   wingV->AddNode(wireV, 1, new TGeoCombiTrans(-(framehr-coverlr)/2, 0, f1d+1,
949                                               wireR));
950   
951   TGeoCombiTrans* extraM1 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
952   extraM1->RotateZ(45);
953   extraM1->RegisterYourself();
954   extraM1->SetName("FMD2_back_cover_slit1");
955   TGeoCombiTrans* extraM2 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
956   extraM2->RotateZ(135);
957   extraM2->RegisterYourself();
958   extraM2->SetName("FMD2_back_cover_slit2");
959   TString coverComp(Form(fgkTopName, fmd2->GetId()));
960   coverComp.Append("-(FMD2_flange_extra:FMD2_back_cover_slit1"
961                    "+FMD2_flange_extra:FMD2_back_cover_slit2)");
962   TGeoCompositeShape* cover2Shape = new TGeoCompositeShape(coverComp.Data());
963   cover2Shape->SetName("FMD2_back_cover");
964   TGeoVolume* cover2Volume = new TGeoVolume("FMD2_back_cover", cover2Shape,fC);
965   support->AddNode(cover2Volume,2, 
966                    new TGeoTranslation(0,0,backth+framel+backth/2));
967
968   TGeoCombiTrans* trans1 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
969   TGeoCombiTrans* trans2 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
970   trans1->RotateZ(45);
971   trans2->RotateZ(135);
972   support->AddNode(wingV, 1, trans1);
973   support->AddNode(wingV, 2, trans2);
974   AliFMDDebug(1, ("FMD2 support offset is %f", framelz));
975   
976   for (Int_t i = 0; i  < 2; i++) {
977     TGeoVolume*   mother = (i < 1 ? fmd2TopVolume : fmd2BotVolume);
978     
979     Double_t      phi    = 360. / 2 * i;
980     TGeoRotation* rot    = new TGeoRotation(Form("FMD2 support rot %d",i)); 
981     rot->RotateZ(phi);
982     TGeoMatrix*   matrix = new TGeoCombiTrans(0, 0, framelz, rot);
983     mother->AddNode(support, i, matrix);    
984   }
985   
986   // Must be done after filling the assemblies 
987   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
988   TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
989   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
990                    fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
991   top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
992   top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
993
994
995   return 0;
996 }
997   
998 //____________________________________________________________________
999 TGeoVolume*
1000 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, 
1001                                     TGeoVolume* innerTop, 
1002                                     TGeoVolume* innerBot, 
1003                                     TGeoVolume* outerTop,
1004                                     TGeoVolume* outerBot) 
1005 {
1006   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
1007   // structure, as the support will also support the vacuum
1008   // beam-pipe. 
1009   // 
1010   // See also AliFMDGeometryBuilder::DetectorGeometry 
1011   // 
1012   if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
1013
1014   //__________________________________________________________________
1015   // Basic detector set-up.
1016   TString fmd3TopName = TString::Format(fgkFMDName, fmd3->GetId(), 'T');
1017   TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(fmd3TopName);
1018   TString fmd3BotName = TString::Format(fgkFMDName, fmd3->GetId(), 'B');
1019   TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(fmd3BotName);
1020   fmd3TopVolume->SetTitle("FMD3 top half");
1021   fmd3BotVolume->SetTitle("FMD3 bottom half");
1022   DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, fmd3->GetInnerZ(), 
1023                    innerTop, innerBot, outerTop, outerBot);
1024
1025   //__________________________________________________________________
1026   // Mother for all support material
1027   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
1028   support->SetTitle("FMD3 support");
1029
1030   //__________________________________________________________________
1031   // Base of cone
1032   const TObjArray& radii    = fmd3->ConeRadii();
1033   Int_t            nRadii   = radii.GetEntriesFast();
1034   TGeoPcon*        coneBase = new TGeoPcon("FMD3_cone_base", 0., 180., nRadii);
1035   TVector3*        r5       = 0;
1036   TVector3*        r4       = 0;
1037   for (Int_t i = 0; i < nRadii; i++) { 
1038     TVector3* v = static_cast<TVector3*>(radii.At(i));
1039     coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
1040     if      (i == 5) r5 = v;
1041     else if (i == 4) r4 = v;
1042   }
1043   TString          coneComb("(FMD3_cone_base");
1044
1045   //__________________________________________________________________
1046   // Flanges 
1047   double    flangeDepth    = fmd3->GetFlangeDepth() / 2;
1048   double    flangeLength   = fmd3->GetFlangeLength() / 2;
1049   double    flangeWidth    = fmd3->GetFlangeWidth() / 2;
1050   new TGeoBBox("FMD3_flange_base", flangeLength, flangeWidth, flangeDepth);
1051
1052   // Fiducial holes 
1053   const TObjArray& fiducialHoles  = fmd3->FiducialHoles();
1054   double           fiducialRadius = fmd3->GetFiducialRadius();
1055 #if 0
1056   TGeoTube*        fiducialShape  = 
1057 #endif
1058     new TGeoTube("FMD3_fiducial_hole", 0, fiducialRadius, flangeDepth+.1);
1059   Int_t            nFiducialHoles = fiducialHoles.GetEntriesFast();
1060   double           flangeAngle    = TMath::Pi() / 4;
1061   double           flangeX        = r5->Y()+flangeLength;
1062   TVector2         flangeC(flangeX * TMath::Cos(flangeAngle), 
1063                            flangeX * TMath::Sin(flangeAngle));
1064   TString          flangeComb("FMD3_flange_base-(");
1065 #if 0// For debugging geometry 
1066   TGeoVolume* fiducialVolume = new TGeoVolume("FMD3_fiducial", fiducialShape);
1067   fiducialVolume->SetLineColor(kGreen);
1068 #endif
1069   for (Int_t i = 0; i < nFiducialHoles; i++) { 
1070     TVector2&        v  =  *(static_cast<TVector2*>(fiducialHoles.At(i)));
1071     v                   -= flangeC;
1072     TVector2         r  =  v.Rotate(-flangeAngle);
1073     TGeoTranslation* t1 =  new TGeoTranslation(r.X(),  r.Y(), 0);
1074     TGeoTranslation* t2 =  new TGeoTranslation(r.X(), -r.Y(), 0);
1075     t1->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+0));
1076     t2->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+1));
1077     t1->RegisterYourself();
1078     t2->RegisterYourself();
1079     flangeComb.Append(Form("FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d+"
1080                            "FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d%c",
1081                            2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
1082 #if 0 // For debugging geometry 
1083     support->AddNode(fiducialVolume, 2*i+0, t1);
1084     support->AddNode(fiducialVolume, 2*i+1, t2);
1085 #endif
1086   }
1087   
1088   // Final flange shape, and at to full shape 
1089   TGeoCompositeShape* flangeShape = new TGeoCompositeShape(flangeComb.Data());
1090   flangeShape->SetName("FMD3_flange");
1091   for (Int_t i = 0; i < 2; i++) { 
1092     TGeoRotation* rot = new TGeoRotation();
1093     rot->RotateZ((i+.5)*90);
1094     TVector2 v(flangeX, 0);
1095     TVector2 w = v.Rotate((i+.5) * 2 * flangeAngle);
1096     TGeoCombiTrans* trans = new TGeoCombiTrans(w.X(),w.Y(),
1097                                                r4->X()+flangeDepth, rot);
1098     trans->SetName(Form("FMD3_flange_matrix%d", i));
1099     trans->RegisterYourself();
1100     coneComb.Append(Form("+FMD3_flange:FMD3_flange_matrix%d", i));
1101   }
1102   coneComb.Append(")-(");
1103   
1104   //__________________________________________________________________
1105   // Holes 
1106   Double_t holeL  = fmd3->GetHoleLength()/2;
1107   Double_t holeD  = fmd3->GetHoleDepth()/2;
1108   Double_t holeLW = fmd3->GetHoleLowWidth()/2;
1109   Double_t holeHW = fmd3->GetHoleHighWidth()/2;
1110   Double_t holeA  = fmd3->GetConeOuterAngle();
1111   Double_t holeA2 = TMath::Pi() - fmd3->GetConeOuterAngle();
1112   Double_t holeO  = fmd3->GetHoleOffset();
1113   Double_t holeZ  = (holeO
1114                      + holeL * TMath::Cos(holeA)
1115                      - holeD * TMath::Sin(holeA2));
1116   Double_t holeX  = (fmd3->ConeR(-holeZ + fmd3->GetInnerZ() + fmd3->GetNoseZ())
1117                      - holeD * TMath::Sin(holeA2));
1118   new TGeoTrd1("FMD3_cone_hole", holeLW, holeHW, holeD, holeL);
1119   TGeoTrd1* plateShape = new TGeoTrd1("FMD3_cooling_plate", 
1120                                       holeLW, holeHW, .033, holeL);
1121   TGeoRotation* holeRot = new TGeoRotation();
1122   holeRot->SetName("FMD3_cone_hole_rotation");
1123   holeRot->RotateZ(90);
1124   holeRot->RotateY(holeA*180/TMath::Pi());
1125   TGeoCombiTrans* holeBaseTrans = new TGeoCombiTrans(holeX, 0, holeZ, holeRot);
1126   holeBaseTrans->SetName("FMD3_cone_hole_base_matrix");
1127   // TGeoRotation* plateRot = new TGeoRotation();
1128   // plateRot->SetName("FMD3_cone_plate_rotation");
1129   // plateRot->RotateZ(90);
1130   // plateRot->RotateY(plateA*180/TMath::Pi());
1131   // TGeoCombiTrans* plateBaseTrans = new 
1132   //                  TGeoCombiTrans(plateX,0,plateZ,plateRot);
1133   TGeoVolume* plateVolume = new TGeoVolume("FMD3_cooling_plate", 
1134                                            plateShape, fAl);
1135   plateShape->SetTitle("FMD3 cooling plate");
1136   plateVolume->SetTitle("FMD3 cooling plate");
1137   for (Int_t i = 0; i < 4; i++) { 
1138     Double_t        ang   = 360. / 8 * (i + .5);
1139     TGeoCombiTrans* trans = new TGeoCombiTrans(*holeBaseTrans);
1140     trans->RotateZ(ang);
1141     trans->SetName(Form("FMD3_cone_hole_matrix%d", i));
1142     trans->RegisterYourself();
1143     trans = new TGeoCombiTrans(*holeBaseTrans);
1144     trans->RotateZ(ang);
1145     trans->SetName(Form("FMD3_cooling_plate_matrix%d", i));
1146     coneComb.Append(Form("FMD3_cone_hole:FMD3_cone_hole_matrix%d+", i));
1147     support->AddNode(plateVolume, i, trans);
1148   }
1149   
1150   //__________________________________________________________________
1151   // Bolts
1152   Double_t boltRadius = fmd3->GetBoltRadius();
1153   Double_t boltLength = fmd3->GetBoltLength() / 2;
1154   Double_t boltZ1     = fmd3->GetInnerZ()+fmd3->GetNoseZ()-10;
1155   Double_t boltZ2     = fmd3->GetInnerZ()+fmd3->GetNoseZ()-20;
1156   Double_t boltXE     = 2*boltLength*TMath::Cos(fmd3->GetConeOuterAngle());
1157   Double_t boltX1     = (fmd3->ConeR(boltZ1) - boltXE);
1158   Double_t boltX2     = (fmd3->ConeR(boltZ2) - boltXE);
1159   
1160   new TGeoTube("FMD3_bolt_hole", 0, boltRadius, boltLength+.2);
1161   TGeoTube* boltShape = new TGeoTube("FMD3_bolt", 0, boltRadius, boltLength);
1162   TGeoRotation* boltRot = new TGeoRotation();
1163   boltRot->RotateY(-fmd3->GetConeOuterAngle()*180/TMath::Pi());
1164   TGeoCombiTrans* boltTrans1 = new TGeoCombiTrans(boltX1, 0, 10, boltRot);
1165   TGeoCombiTrans* boltTrans2 = new TGeoCombiTrans(boltX2, 0, 20, boltRot);
1166   TGeoCombiTrans* boltTrans3 = new TGeoCombiTrans(*boltTrans1);
1167   TGeoCombiTrans* boltTrans4 = new TGeoCombiTrans(*boltTrans2);
1168   boltTrans3->RotateZ(180);
1169   boltTrans4->RotateZ(180);
1170   boltTrans1->SetName("FMD3_bolt_matrix1");
1171   boltTrans2->SetName("FMD3_bolt_matrix2");
1172   boltTrans3->SetName("FMD3_bolt_matrix3");
1173   boltTrans4->SetName("FMD3_bolt_matrix4");
1174   boltTrans1->RegisterYourself();
1175   boltTrans2->RegisterYourself();
1176   boltTrans3->RegisterYourself();
1177   boltTrans4->RegisterYourself();
1178   coneComb.Append("FMD3_bolt_hole:FMD3_bolt_matrix1"
1179                   "+FMD3_bolt_hole:FMD3_bolt_matrix2"
1180                   "+FMD3_bolt_hole:FMD3_bolt_matrix3"
1181                   "+FMD3_bolt_hole:FMD3_bolt_matrix4");
1182   TGeoVolume*     boltVolume = new TGeoVolume("FMD3_bolt", boltShape, fSteel);
1183   support->AddNode(boltVolume, 1, boltTrans1);
1184   support->AddNode(boltVolume, 2, boltTrans2);
1185   boltShape->SetTitle("FMD3 steering bolt");
1186   boltVolume->SetTitle("FMD3 steering bolt");
1187   
1188   //__________________________________________________________________
1189   // Cut-outs for tension wheel sheeve 
1190   new TGeoBBox("FMD3_sheeve_hole", .55, .75, 1.16);
1191   Double_t        sheeveHoleZ = fmd3->GetInnerZ() + fmd3->GetNoseZ() - .75;
1192   Double_t        sheeveHoleR = fmd3->ConeR(sheeveHoleZ) - .55 + .2572222;
1193   TGeoCombiTrans* sheeveMat1  = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1194   TGeoCombiTrans* sheeveMat2  = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1195   sheeveMat1->RotateZ(45);
1196   sheeveMat2->RotateZ(135);
1197   sheeveMat1->SetName("FMD3_sheeve_hole_matrix1");
1198   sheeveMat2->SetName("FMD3_sheeve_hole_matrix2");
1199   sheeveMat1->RegisterYourself();
1200   sheeveMat2->RegisterYourself();
1201   coneComb.Append("+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix1"
1202                   "+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix2)");
1203   
1204   //__________________________________________________________________
1205   // Sheeve boxes 
1206   Double_t       sheeveL     = 1.15;
1207   TGeoBBox*      sheeveSideS = new TGeoBBox("FMD3_sheeve_side",
1208                                            .55, .25, 1.15);
1209   TGeoBBox*      sheeveBackS = new TGeoBBox("FMD3_sheeve_back", 
1210                                             .55, .25, .15);
1211   TGeoBBox*      sheeveWingS = new TGeoBBox("FMD3_sheeve_wing", 
1212                                             .15, .15, 1.15);
1213   TGeoPcon*      sheeveWheelS = new TGeoPcon("FMD3_sheeve_wheel", 0, 360, 9);
1214   Double_t       sheeveInnerR = 0; // .2;
1215   Double_t       sheeveR      = .875;
1216   Double_t       sheeveWheelZ = .95;
1217   sheeveWheelS->DefineSection(0, -.25,   sheeveInnerR, 1);
1218   sheeveWheelS->DefineSection(1, -.125,  sheeveInnerR, 1);
1219   sheeveWheelS->DefineSection(2, -.125,  sheeveInnerR, sheeveWheelZ);
1220   sheeveWheelS->DefineSection(3, -.0625, sheeveInnerR, sheeveR+.02);
1221   sheeveWheelS->DefineSection(4, 0.000,  sheeveInnerR, sheeveR);
1222   sheeveWheelS->DefineSection(5, +.0625, sheeveInnerR, sheeveR+.02);
1223   sheeveWheelS->DefineSection(6, +.125,  sheeveInnerR, sheeveWheelZ);
1224   sheeveWheelS->DefineSection(7, +.125,  sheeveInnerR, 1);
1225   sheeveWheelS->DefineSection(8, +.25,   sheeveInnerR, 1);
1226   TGeoVolume*    sheeveSideV = new TGeoVolume("FMD3_sheeve_side", 
1227                                               sheeveSideS, fPlastic);
1228   TGeoVolume*    sheeveBackV = new TGeoVolume("FMD3_sheeve_back", 
1229                                               sheeveBackS, fPlastic);
1230   TGeoVolume*    sheeveWingV = new TGeoVolume("FMD3_sheeve_wing", 
1231                                               sheeveWingS, fPlastic);
1232   TGeoVolume*    sheeveWheelV= new TGeoVolume("FMD3_sheeve_wheel", 
1233                                               sheeveWheelS, fPlastic);
1234   TGeoVolumeAssembly* sheeveBox = new TGeoVolumeAssembly("FMD3_sheeve_box");
1235   sheeveBox->AddNode(sheeveSideV, 1, new TGeoTranslation(0, -.5, 0));
1236   sheeveBox->AddNode(sheeveSideV, 2, new TGeoTranslation(0, +.5, 0));
1237   sheeveBox->AddNode(sheeveBackV, 1, new TGeoTranslation(0, 0, 2.0+.15-1.15));
1238   sheeveBox->AddNode(sheeveWingV, 1, new TGeoTranslation(.55-.15, -.90, 0));
1239   sheeveBox->AddNode(sheeveWingV, 2, new TGeoTranslation(.55-.15, +.90, 0));
1240   TGeoRotation*   sheeveWheelR = new TGeoRotation;
1241   sheeveWheelR->RotateX(90);
1242   TGeoCombiTrans* sheeveWheelM = new TGeoCombiTrans(0, 0, sheeveWheelZ-sheeveL,
1243                                                     sheeveWheelR);
1244   sheeveBox->AddNode(sheeveWheelV, 1, sheeveWheelM);
1245   support->AddNode(sheeveBox, 1, sheeveMat1);
1246   support->AddNode(sheeveBox, 2, sheeveMat2);
1247   
1248   
1249
1250   //__________________________________________________________________
1251   // Final cone
1252   TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneComb.Data());
1253   coneShape->SetName("FMD3_cone");
1254   coneShape->SetTitle("FMD3 cone");
1255   TGeoVolume*  coneVolume = new TGeoVolume("FMD3_Cone", coneShape, fC);
1256   coneVolume->SetLineColor(kRed);
1257   support->AddNode(coneVolume, 0, new TGeoTranslation(0, 0, 0));
1258
1259   //__________________________________________________________________
1260   // Tension boxes. 
1261   TGeoVolume*     tensionBox = TensionBox();
1262   Double_t        tensionH  = .6;
1263   Double_t        tensionL  = 4;
1264   Double_t        tensionZ  = 23.654;
1265   Double_t        tensionR  = fmd3->ConeR(fmd3->GetInnerZ() + fmd3->GetNoseZ() 
1266                                           -  tensionZ);
1267   Double_t        tensionAr = fmd3->GetConeOuterAngle();
1268   Double_t        tensionA  = tensionAr * 180 / TMath::Pi();
1269   TGeoRotation*   tensionQ  = new TGeoRotation;
1270   tensionQ->RotateY(tensionA);
1271   TGeoCombiTrans* tensionM1 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1272   TGeoCombiTrans* tensionM2 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1273   tensionM1->RotateZ(45);
1274   tensionM2->RotateZ(135);
1275   support->AddNode(tensionBox, 1, tensionM1);
1276   support->AddNode(tensionBox, 2, tensionM2);
1277   
1278   // Double_t         tensionHR    = 0.15;
1279   Double_t         wireT        = .1/2;
1280   Double_t         wireZ1       = (tensionZ
1281                                    - tensionL * TMath::Cos(tensionAr) 
1282                                    - tensionH * TMath::Sin(tensionAr));
1283   Double_t         wireR1       = (tensionR 
1284                                    - tensionL * TMath::Sin(tensionAr) 
1285                                    + tensionH * TMath::Cos(tensionAr));
1286   AliFMDDebug(10, ("Wire Z1: %f=%f-%f*cos(%f)-%f*sin(%f)", 
1287                   wireZ1, tensionZ, tensionL, tensionAr, tensionH, tensionAr));
1288   AliFMDDebug(10, ("Wire R1: %f=%f-%f*sin(%f)-%f*cos(%f)", 
1289                   wireR1, tensionR, tensionL, tensionAr, tensionH, tensionAr));
1290   
1291   Double_t         wireStartA   = 42.3 * TMath::Pi() / 180;
1292   Double_t         wireZ2       = (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1293                                    // - sheeveL - 
1294                                    - wireT * TMath::Sin(wireStartA));
1295   /* (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1296                                    - wireT * TMath::Sin(wireStartA) 
1297                                    - sheeveL); */
1298   AliFMDDebug(10, ("wireZ2=%f=%f*(1-%f)", wireZ2, sheeveWheelZ, 
1299                   TMath::Sin(wireStartA)));
1300   Double_t         wireR2       = (sheeveHoleR + 
1301                                    sheeveWheelZ * TMath::Cos(wireStartA) + 
1302                                    wireT * TMath::Cos(wireStartA));
1303   Double_t         wireDR       = wireR1-wireR2;
1304   Double_t         wireDZ       = wireZ1-wireZ2;
1305   Double_t         wireL        = TMath::Sqrt(wireDR*wireDR+wireDZ*wireDZ)-.01;
1306   Double_t         wireAngle    = TMath::ATan2(wireDR,wireDZ);
1307   TGeoTube*        wireShape    = new TGeoTube("FMD3_wire", 0, wireT, wireL/2);
1308   TGeoVolume*      wireVolume   = new TGeoVolume("FMD3_wire", wireShape,fSteel);
1309   TGeoRotation*    wireRot      = new TGeoRotation();
1310   wireRot->RotateY(180/TMath::Pi()*wireAngle);
1311   Double_t         wireR        = wireR2 + wireDR / 2;
1312   Double_t         wireZ        = wireZ2 + wireDZ / 2;
1313   TGeoCombiTrans*  wireM1       = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1314   TGeoCombiTrans*  wireM2       = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1315   wireM1->RotateZ(45);
1316   wireM2->RotateZ(135);
1317   support->AddNode(wireVolume, 1, wireM1);
1318   support->AddNode(wireVolume, 2, wireM2);
1319
1320
1321   TGeoTorus*       wireTS  = new TGeoTorus(sheeveWheelZ+wireT, 0, wireT, 0, 
1322                                            90-wireStartA*180/TMath::Pi());
1323   TGeoVolume*      wireTV  = new TGeoVolume("FMD3_bend_wire",wireTS,fSteel);
1324   TGeoRotation*    wireTR  = new TGeoRotation;
1325   wireTR->RotateY(90);
1326   wireTR->RotateZ(-90);
1327   Double_t         wireTZ  = sheeveWheelZ;
1328   TGeoCombiTrans*  wireTM1 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1329   TGeoCombiTrans*  wireTM2 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1330   wireTM1->RotateZ(45);
1331   wireTM2->RotateZ(135);
1332   support->AddNode(wireTV, 1, wireTM1);
1333   support->AddNode(wireTV, 2, wireTM2);
1334
1335   Double_t         colarR = 4.05;
1336   Double_t         wireEL = sheeveHoleR - colarR;
1337   TGeoTube*        wireES = new TGeoTube("FMD3_end_wire", 0, wireT, wireEL/2);
1338   TGeoVolume*      wireEV = new TGeoVolume("FMD3_end_wire", wireES, fSteel);
1339   TGeoRotation*    wireER = new TGeoRotation;
1340   wireER->RotateY(90);
1341   TGeoCombiTrans*  wireEM1 = new TGeoCombiTrans(colarR+wireEL/2,0,
1342                                                 -wireT,wireER);
1343   TGeoCombiTrans*  wireEM2 = new TGeoCombiTrans(colarR+wireEL/2,0,
1344                                                 -wireT,wireER);
1345   wireEM1->RotateZ(45);
1346   wireEM2->RotateZ(135);
1347   support->AddNode(wireEV, 1, wireEM1);
1348   support->AddNode(wireEV, 2, wireEM2);
1349   
1350   
1351
1352   
1353   //__________________________________________________________________
1354   // Place support volumes in half-detector volumes 
1355   Double_t         z  = fmd3->GetInnerZ();
1356   AliFMDDebug(1, ("FMD3 support at z=%f", -fmd3->GetNoseZ()));
1357   TGeoTranslation* t1 = new TGeoTranslation(0, 0, -fmd3->GetNoseZ());
1358   fmd3TopVolume->AddNode(support, 1, t1);
1359   TGeoCombiTrans*  t2 = new TGeoCombiTrans(*t1);
1360   t2->RotateZ(180);
1361   fmd3BotVolume->AddNode(support, 2, t2);
1362
1363   TGeoRotation*   rot        = new TGeoRotation("FMD3 rotatation");
1364   rot->RotateY(180);
1365   TGeoVolume*     top        = gGeoManager->GetVolume("ALIC");
1366   TGeoMatrix* mmatrix        = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1367   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
1368                    fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1369   top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1370   top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1371
1372   return 0;
1373 }
1374
1375
1376 //____________________________________________________________________
1377 void
1378 AliFMDGeometryBuilder::Exec(Option_t*) 
1379 {
1380   // Setup up the FMD geometry. 
1381   AliFMDDebug(1, ("\tGeometry options: %s",
1382                     (fDetailed  ? "divided into strips" : "one volume")));
1383   if (!gGeoManager) {
1384     AliFatal("No TGeoManager defined");
1385     return;
1386   }
1387
1388   fSi      = gGeoManager->GetMedium("FMD_Si$");
1389   fC       = gGeoManager->GetMedium("FMD_Carbon$");
1390   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
1391   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
1392   fAir     = gGeoManager->GetMedium("FMD_Air$");
1393   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
1394   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1395   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
1396   fSteel   = gGeoManager->GetMedium("FMD_Steel$");
1397
1398   if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1399     AliError("Failed to get some or all tracking mediums");
1400     return;
1401   }    
1402   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1403   AliFMDRing* inner = fmd->GetInner();
1404   AliFMDRing* outer = fmd->GetOuter();
1405   RingGeometry(inner);
1406   RingGeometry(outer);
1407   TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
1408                                                      inner->GetId()));
1409   TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
1410                                                      inner->GetId()));
1411   TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
1412                                                      outer->GetId()));
1413   TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
1414                                                      outer->GetId()));
1415   
1416   FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1417   FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1418   FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1419 #ifndef USE_PRE_MOVE
1420   fmd->SetSectorOff(fSectorOff);
1421   fmd->SetModuleOff(fModuleOff);
1422   fmd->SetRingOff(fRingOff);
1423   fmd->SetDetectorOff(fDetectorOff);
1424   fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1425 #endif
1426   // fmd->ExtractGeomInfo();
1427   
1428 }
1429
1430
1431 //____________________________________________________________________
1432 //
1433 // EOF
1434 //